diff options
author | Christian Williams <christianw@google.com> | 2017-12-12 23:56:42 -0800 |
---|---|---|
committer | Christian Williams <christianw@google.com> | 2017-12-13 14:44:49 -0800 |
commit | ccbff72212761af56631d25e8ddb10cbb2cb2c81 (patch) | |
tree | aaacf3fc3099f31e25270f1acb7a7049321aa881 /resources | |
parent | cfc51d06c41790b6c4e1227dd206d584748c8735 (diff) | |
download | robolectric-shadows-ccbff72212761af56631d25e8ddb10cbb2cb2c81.tar.gz |
Apply changes between 7.1.1_r13 and 8.0.0_r4.
Diffstat (limited to 'resources')
3 files changed, 512 insertions, 199 deletions
diff --git a/resources/src/main/java/org/robolectric/res/android/AConfiguration.java b/resources/src/main/java/org/robolectric/res/android/AConfiguration.java index 9d5b76ce3..f6d9588e9 100644 --- a/resources/src/main/java/org/robolectric/res/android/AConfiguration.java +++ b/resources/src/main/java/org/robolectric/res/android/AConfiguration.java @@ -1,6 +1,6 @@ package org.robolectric.res.android; -// transliterated from https://android.googlesource.com/platform/frameworks/native/+/android-7.1.1_r13/include/android/configuration.h +// transliterated from https://android.googlesource.com/platform/frameworks/native/+/android-8.0.0_r4/include/android/configuration.h public class AConfiguration { /** Orientation: not specified. */ public static final int ACONFIGURATION_ORIENTATION_ANY = 0x0000; @@ -211,6 +211,37 @@ public class AConfiguration { public static final int ACONFIGURATION_SCREENROUND_ANY = 0x00; public static final int ACONFIGURATION_SCREENROUND_NO = 0x1; public static final int ACONFIGURATION_SCREENROUND_YES = 0x2; + + /** Wide color gamut: not specified. */ + public static final int ACONFIGURATION_WIDE_COLOR_GAMUT_ANY = 0x00; + /** + * Wide color gamut: value that corresponds to + * <a href="@dacRoot/guide/topics/resources/providing-resources.html#WideColorGamutQualifier">no + * nowidecg</a> resource qualifier specified. + */ + public static final int ACONFIGURATION_WIDE_COLOR_GAMUT_NO = 0x1; + /** + * Wide color gamut: value that corresponds to + * <a href="@dacRoot/guide/topics/resources/providing-resources.html#WideColorGamutQualifier"> + * widecg</a> resource qualifier specified. + */ + public static final int ACONFIGURATION_WIDE_COLOR_GAMUT_YES = 0x2; + + /** HDR: not specified. */ + public static final int ACONFIGURATION_HDR_ANY = 0x00; + /** + * HDR: value that corresponds to + * <a href="@dacRoot/guide/topics/resources/providing-resources.html#HDRQualifier"> + * lowdr</a> resource qualifier specified. + */ + public static final int ACONFIGURATION_HDR_NO = 0x1; + /** + * HDR: value that corresponds to + * <a href="@dacRoot/guide/topics/resources/providing-resources.html#HDRQualifier"> + * highdr</a> resource qualifier specified. + */ + public static final int ACONFIGURATION_HDR_YES = 0x2; + /** UI mode: not specified. */ public static final int ACONFIGURATION_UI_MODE_TYPE_ANY = 0x00; /** @@ -244,6 +275,11 @@ public class AConfiguration { * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a> resource qualifier specified. */ public static final int ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06; + /** + * UI mode: value that corresponds to + * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">vr</a> resource qualifier specified. + */ + public static final int ACONFIGURATION_UI_MODE_TYPE_VR_HEADSET = 0x07; /** UI night mode: not specified.*/ public static final int ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00; /** @@ -364,6 +400,12 @@ public class AConfiguration { public static final int ACONFIGURATION_LAYOUTDIR = 0x4000; public static final int ACONFIGURATION_SCREEN_ROUND = 0x8000; /** + * Bit mask for + * <a href="@dacRoot/guide/topics/resources/providing-resources.html#WideColorGamutQualifier">wide color gamut</a> + * and <a href="@dacRoot/guide/topics/resources/providing-resources.html#HDRQualifier">HDR</a> configurations. + */ + public static final int ACONFIGURATION_COLOR_MODE = 0x10000; + /** * Constant used to to represent MNC (Mobile Network Code) zero. * 0 cannot be used, since it is used to represent an undefined MNC. */ diff --git a/resources/src/main/java/org/robolectric/res/android/ConfigDescription.java b/resources/src/main/java/org/robolectric/res/android/ConfigDescription.java index 18d30f9cc..2dd9779ba 100644 --- a/resources/src/main/java/org/robolectric/res/android/ConfigDescription.java +++ b/resources/src/main/java/org/robolectric/res/android/ConfigDescription.java @@ -10,7 +10,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** - * From android/frameworks/base/tools/aapt2/ConfigDescription.cpp + * transliterated from + * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r4/tools/aapt2/ConfigDescription.cpp */ public class ConfigDescription { public static int SDK_CUPCAKE = 3; @@ -278,6 +279,20 @@ public class ConfigDescription { } } + if (part_iter.hasNext() && parseWideColorGamut(part_iter.peek(), out)) { + part_iter.next(); + if (!part_iter.hasNext()) { + success = !part_iter.hasNext(); + } + } + + if (part_iter.hasNext() && parseHdr(part_iter.peek(), out)) { + part_iter.next(); + if (!part_iter.hasNext()) { + success = !part_iter.hasNext(); + } + } + if (part_iter.hasNext() && parseOrientation(part_iter.peek(), out)) { part_iter.next(); if (!part_iter.hasNext()) { @@ -530,6 +545,52 @@ public class ConfigDescription { return false; } + private boolean parseWideColorGamut(String name, ResTable_config out) { + if (Objects.equals(name, kWildcardName)) { + if (out != null) + out.colorMode = + (byte) ((out.colorMode & ~ResTable_config.MASK_WIDE_COLOR_GAMUT) | + ResTable_config.WIDE_COLOR_GAMUT_ANY); + return true; + } else if (Objects.equals(name, "widecg")) { + if (out != null) + out.colorMode = + (byte) ((out.colorMode & ~ResTable_config.MASK_WIDE_COLOR_GAMUT) | + ResTable_config.WIDE_COLOR_GAMUT_YES); + return true; + } else if (Objects.equals(name, "nowidecg")) { + if (out != null) + out.colorMode = + (byte) ((out.colorMode & ~ResTable_config.MASK_WIDE_COLOR_GAMUT) | + ResTable_config.WIDE_COLOR_GAMUT_NO); + return true; + } + return false; + } + + private boolean parseHdr(String name, ResTable_config out) { + if (Objects.equals(name, kWildcardName)) { + if (out != null) + out.colorMode = + (byte) ((out.colorMode & ~ResTable_config.MASK_HDR) | + ResTable_config.HDR_ANY); + return true; + } else if (Objects.equals(name, "highdr")) { + if (out != null) + out.colorMode = + (byte) ((out.colorMode & ~ResTable_config.MASK_HDR) | + ResTable_config.HDR_YES); + return true; + } else if (Objects.equals(name, "lowdr")) { + if (out != null) + out.colorMode = + (byte) ((out.colorMode & ~ResTable_config.MASK_HDR) | + ResTable_config.HDR_NO); + return true; + } + return false; + } + private boolean parseOrientation(String name, ResTable_config out) { if (Objects.equals(name, kWildcardName)) { if (out != null) { @@ -593,6 +654,12 @@ public class ConfigDescription { ResTable_config.UI_MODE_TYPE_WATCH; } return true; + } else if (Objects.equals(name, "vrheadset")) { + if (out != null) { + out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_TYPE) | + ResTable_config.UI_MODE_TYPE_VR_HEADSET; + } + return true; } return false; @@ -917,29 +984,34 @@ public class ConfigDescription { if (config == null) { return; } - int minSdk = 0; - if (isTruthy(config.screenLayout2 & ResTable_config.MASK_SCREENROUND)) { - minSdk = SDK_MNC; + int min_sdk = 0; + if (((config.uiMode & ResTable_config.MASK_UI_MODE_TYPE) + == ResTable_config.UI_MODE_TYPE_VR_HEADSET) || + (config.colorMode & ResTable_config.MASK_WIDE_COLOR_GAMUT) != 0 || + (config.colorMode & ResTable_config.MASK_HDR) != 0) { + min_sdk = SDK_O; + } else if (isTruthy(config.screenLayout2 & ResTable_config.MASK_SCREENROUND)) { + min_sdk = SDK_MNC; } else if (config.density == ResTable_config.DENSITY_ANY) { - minSdk = SDK_LOLLIPOP; + min_sdk = SDK_LOLLIPOP; } else if (config.smallestScreenWidthDp != ResTable_config.SCREENWIDTH_ANY || config.screenWidthDp != ResTable_config.SCREENWIDTH_ANY || config.screenHeightDp != ResTable_config.SCREENHEIGHT_ANY) { - minSdk = SDK_HONEYCOMB_MR2; + min_sdk = SDK_HONEYCOMB_MR2; } else if ((config.uiMode & ResTable_config.MASK_UI_MODE_TYPE) != ResTable_config.UI_MODE_TYPE_ANY || (config.uiMode & ResTable_config.MASK_UI_MODE_NIGHT) != ResTable_config.UI_MODE_NIGHT_ANY) { - minSdk = SDK_FROYO; + min_sdk = SDK_FROYO; } else if ((config.screenLayout & ResTable_config.MASK_SCREENSIZE) != ResTable_config.SCREENSIZE_ANY || (config.screenLayout & ResTable_config.MASK_SCREENLONG) != ResTable_config.SCREENLONG_ANY || config.density != ResTable_config.DENSITY_DEFAULT) { - minSdk = SDK_DONUT; + min_sdk = SDK_DONUT; } - if (minSdk > config.sdkVersion) { - config.sdkVersion = minSdk; + if (min_sdk > config.sdkVersion) { + config.sdkVersion = min_sdk; } } } diff --git a/resources/src/main/java/org/robolectric/res/android/ResTable_config.java b/resources/src/main/java/org/robolectric/res/android/ResTable_config.java index b6fd1a4a7..b55d320b4 100644 --- a/resources/src/main/java/org/robolectric/res/android/ResTable_config.java +++ b/resources/src/main/java/org/robolectric/res/android/ResTable_config.java @@ -12,10 +12,10 @@ import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_DENSITY_ import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_DENSITY_XHIGH; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_DENSITY_XXHIGH; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_DENSITY_XXXHIGH; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_KEYBOARD_12KEY; +import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_HDR_ANY; +import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_HDR_NO; +import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_HDR_YES; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_KEYBOARD_ANY; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_KEYBOARD_NOKEYS; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_KEYBOARD_QWERTY; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_KEYSHIDDEN_ANY; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_KEYSHIDDEN_NO; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_KEYSHIDDEN_SOFT; @@ -27,10 +27,6 @@ import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_NAVHIDDE import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_NAVHIDDEN_NO; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_NAVHIDDEN_YES; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_NAVIGATION_ANY; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_NAVIGATION_DPAD; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_NAVIGATION_NONAV; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_NAVIGATION_TRACKBALL; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_NAVIGATION_WHEEL; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_ORIENTATION_ANY; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_ORIENTATION_LAND; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_ORIENTATION_PORT; @@ -47,19 +43,12 @@ import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_SCREENSI import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_SCREENSIZE_SMALL; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_SCREENSIZE_XLARGE; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_TOUCHSCREEN_ANY; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_TOUCHSCREEN_FINGER; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_TOUCHSCREEN_NOTOUCH; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_TOUCHSCREEN_STYLUS; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_NIGHT_ANY; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_NIGHT_NO; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_NIGHT_YES; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_TYPE_ANY; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_TYPE_APPLIANCE; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_TYPE_CAR; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_TYPE_DESK; import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_TYPE_NORMAL; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_TYPE_TELEVISION; -import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_UI_MODE_TYPE_WATCH; +import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_WIDE_COLOR_GAMUT_ANY; +import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_WIDE_COLOR_GAMUT_NO; +import static org.robolectric.res.android.AConfiguration.ACONFIGURATION_WIDE_COLOR_GAMUT_YES; import static org.robolectric.res.android.LocaleData.localeDataCompareRegions; import static org.robolectric.res.android.LocaleData.localeDataComputeScript; import static org.robolectric.res.android.LocaleData.localeDataIsCloseToUsEnglish; @@ -68,14 +57,16 @@ import static org.robolectric.res.android.Util.dtohl; import static org.robolectric.res.android.Util.dtohs; import static org.robolectric.res.android.Util.isTruthy; +import com.google.common.base.Charsets; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; +import com.google.common.primitives.Bytes; import com.google.common.primitives.UnsignedBytes; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -85,6 +76,8 @@ import java.util.Map; * Transliterated from: * * https://android.googlesource.com/platform/frameworks/base/+/android-7.1.1_r13/libs/androidfw/ResourceTypes.cpp * * https://android.googlesource.com/platform/frameworks/base/+/android-7.1.1_r13/include/androidfw/ResourceTypes.h (struct ResTable_config) + * + * Changes from 8.0.0_r4 partially applied. */ public class ResTable_config { public static final boolean kDebugTableSuperNoisy = false; @@ -119,7 +112,7 @@ public class ResTable_config { static final byte[] kFilipino = new byte[] {(byte)0xAD, 0x05}; // packed version of "fil" ported from C {'\xAD', '\x05'} static final byte[] kTagalog = new byte[] {'t', 'l'}; // packed version of "tl" - static org.robolectric.res.android.ResTable_config createConfig(ByteBuffer buffer) { + static ResTable_config createConfig(ByteBuffer buffer) { int startPosition = buffer.position(); // The starting buffer position to calculate bytes read. int size = buffer.getInt(); int mcc = buffer.getShort() & 0xFFFF; @@ -180,18 +173,25 @@ public class ResTable_config { byte[] unknown = new byte[size - bytesRead]; buffer.get(unknown); - return new org.robolectric.res.android.ResTable_config(size, mcc, mnc, language, region, orientation, + return new ResTable_config(size, mcc, mnc, language, region, orientation, touchscreen, density, keyboard, navigation, inputFlags, screenWidth, screenHeight, sdkVersion, minorVersion, screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp, screenHeightDp, localeScript, localeVariant, screenLayout2, screenConfigPad1, screenConfigPad2, unknown); } - /** The different types of configs that can be present in a {@link org.robolectric.res.android.ResTable_config}. */ + /** + * The different types of configs that can be present in a {@link ResTable_config}. + * + * The ordering of these types is roughly the same as {@code #isBetterThan}, but is not + * guaranteed to be the same. + */ public enum Type { MCC, MNC, LANGUAGE_STRING, + LOCALE_SCRIPT_STRING, REGION_STRING, + LOCALE_VARIANT_STRING, SCREEN_LAYOUT_DIRECTION, SMALLEST_SCREEN_WIDTH_DP, SCREEN_WIDTH_DP, @@ -199,6 +199,8 @@ public class ResTable_config { SCREEN_LAYOUT_SIZE, SCREEN_LAYOUT_LONG, SCREEN_LAYOUT_ROUND, + COLOR_MODE_WIDE_COLOR_GAMUT, // NB: COLOR_GAMUT takes priority over HDR in #isBetterThan. + COLOR_MODE_HDR, ORIENTATION, UI_MODE_TYPE, UI_MODE_NIGHT, @@ -208,6 +210,7 @@ public class ResTable_config { KEYBOARD, NAVIGATION_HIDDEN, NAVIGATION, + SCREEN_SIZE, SDK_VERSION } @@ -230,18 +233,11 @@ public class ResTable_config { public static final int MASK_UI_MODE_TYPE = 0x0f; public static final int UI_MODE_TYPE_ANY = ACONFIGURATION_UI_MODE_TYPE_ANY; public static final int UI_MODE_TYPE_NORMAL = ACONFIGURATION_UI_MODE_TYPE_NORMAL; - public static final int UI_MODE_TYPE_DESK = ACONFIGURATION_UI_MODE_TYPE_DESK; - public static final int UI_MODE_TYPE_CAR = ACONFIGURATION_UI_MODE_TYPE_CAR; - public static final int UI_MODE_TYPE_TELEVISION = ACONFIGURATION_UI_MODE_TYPE_TELEVISION; - public static final int UI_MODE_TYPE_APPLIANCE = ACONFIGURATION_UI_MODE_TYPE_APPLIANCE; - public static final int UI_MODE_TYPE_WATCH = ACONFIGURATION_UI_MODE_TYPE_WATCH; // uiMode bits for the night switch; public static final int MASK_UI_MODE_NIGHT = 0x30; public static final int SHIFT_UI_MODE_NIGHT = 4; public static final int UI_MODE_NIGHT_ANY = ACONFIGURATION_UI_MODE_NIGHT_ANY << SHIFT_UI_MODE_NIGHT; - public static final int UI_MODE_NIGHT_NO = ACONFIGURATION_UI_MODE_NIGHT_NO << SHIFT_UI_MODE_NIGHT; - public static final int UI_MODE_NIGHT_YES = ACONFIGURATION_UI_MODE_NIGHT_YES << SHIFT_UI_MODE_NIGHT; public static final int DENSITY_DEFAULT = ACONFIGURATION_DENSITY_DEFAULT; public static final int DENSITY_LOW = ACONFIGURATION_DENSITY_LOW; @@ -255,9 +251,6 @@ public class ResTable_config { public static final int DENSITY_NONE = ACONFIGURATION_DENSITY_NONE; public static final int TOUCHSCREEN_ANY = ACONFIGURATION_TOUCHSCREEN_ANY; - public static final int TOUCHSCREEN_NOTOUCH = ACONFIGURATION_TOUCHSCREEN_NOTOUCH; - public static final int TOUCHSCREEN_STYLUS = ACONFIGURATION_TOUCHSCREEN_STYLUS; - public static final int TOUCHSCREEN_FINGER = ACONFIGURATION_TOUCHSCREEN_FINGER; public static final int MASK_KEYSHIDDEN = 0x0003; public static final byte KEYSHIDDEN_ANY = ACONFIGURATION_KEYSHIDDEN_ANY; @@ -266,9 +259,6 @@ public class ResTable_config { public static final byte KEYSHIDDEN_SOFT = ACONFIGURATION_KEYSHIDDEN_SOFT; public static final int KEYBOARD_ANY = ACONFIGURATION_KEYBOARD_ANY; - public static final int KEYBOARD_NOKEYS = ACONFIGURATION_KEYBOARD_NOKEYS; - public static final int KEYBOARD_QWERTY = ACONFIGURATION_KEYBOARD_QWERTY; - public static final int KEYBOARD_12KEY = ACONFIGURATION_KEYBOARD_12KEY; public static final int MASK_NAVHIDDEN = 0x000c; public static final int SHIFT_NAVHIDDEN = 2; @@ -277,122 +267,167 @@ public class ResTable_config { public static final byte NAVHIDDEN_YES = ACONFIGURATION_NAVHIDDEN_YES << SHIFT_NAVHIDDEN; public static final int NAVIGATION_ANY = ACONFIGURATION_NAVIGATION_ANY; - public static final int NAVIGATION_NONAV = ACONFIGURATION_NAVIGATION_NONAV; - public static final int NAVIGATION_DPAD = ACONFIGURATION_NAVIGATION_DPAD; - public static final int NAVIGATION_TRACKBALL = ACONFIGURATION_NAVIGATION_TRACKBALL; - public static final int NAVIGATION_WHEEL = ACONFIGURATION_NAVIGATION_WHEEL; public static final int SCREENHEIGHT_ANY = 0; public static final int SDKVERSION_ANY = 0; public static final int MINORVERSION_ANY = 0; + // from https://github.com/google/android-arscblamer/blob/master/java/com/google/devrel/gmscore/tools/apk/arsc/ResourceConfiguration.java /** The below constants are from android.content.res.Configuration. */ - private static final int DENSITY_DPI_UNDEFINED = 0; - private static final int DENSITY_DPI_LDPI = 120; - private static final int DENSITY_DPI_MDPI = 160; - private static final int DENSITY_DPI_TVDPI = 213; - private static final int DENSITY_DPI_HDPI = 240; - private static final int DENSITY_DPI_XHDPI = 320; - private static final int DENSITY_DPI_XXHDPI = 480; - private static final int DENSITY_DPI_XXXHDPI = 640; - private static final int DENSITY_DPI_ANY = 0xFFFE; - private static final int DENSITY_DPI_NONE = 0xFFFF; - private static final Map<Integer, String> DENSITY_DPI_VALUES = - ImmutableMap.<Integer, String>builder() - .put(DENSITY_DPI_UNDEFINED, "") - .put(DENSITY_DPI_LDPI, "ldpi") - .put(DENSITY_DPI_MDPI, "mdpi") - .put(DENSITY_DPI_TVDPI, "tvdpi") - .put(DENSITY_DPI_HDPI, "hdpi") - .put(DENSITY_DPI_XHDPI, "xhdpi") - .put(DENSITY_DPI_XXHDPI, "xxhdpi") - .put(DENSITY_DPI_XXXHDPI, "xxxhdpi") - .put(DENSITY_DPI_ANY, "anydpi") - .put(DENSITY_DPI_NONE, "nodpi") - .build(); - - private static final Map<Integer, String> KEYBOARD_VALUES = ImmutableMap.of( - KEYBOARD_NOKEYS, "nokeys", - KEYBOARD_QWERTY, "qwerty", - KEYBOARD_12KEY, "12key"); - - private static final int KEYBOARDHIDDEN_MASK = 0x03; - private static final int KEYBOARDHIDDEN_NO = 1; - private static final int KEYBOARDHIDDEN_YES = 2; - private static final int KEYBOARDHIDDEN_SOFT = 3; - private static final Map<Integer, String> KEYBOARDHIDDEN_VALUES = ImmutableMap.of( - KEYBOARDHIDDEN_NO, "keysexposed", - KEYBOARDHIDDEN_YES, "keyshidden", - KEYBOARDHIDDEN_SOFT, "keyssoft"); - - private static final Map<Integer, String> NAVIGATION_VALUES = ImmutableMap.of( - NAVIGATION_NONAV, "nonav", - NAVIGATION_DPAD, "dpad", - NAVIGATION_TRACKBALL, "trackball", - NAVIGATION_WHEEL, "wheel"); - - private static final int NAVIGATIONHIDDEN_MASK = 0x0C; - private static final int NAVIGATIONHIDDEN_NO = 0x04; - private static final int NAVIGATIONHIDDEN_YES = 0x08; - private static final Map<Integer, String> NAVIGATIONHIDDEN_VALUES = ImmutableMap.of( - NAVIGATIONHIDDEN_NO, "navexposed", - NAVIGATIONHIDDEN_YES, "navhidden"); - - private static final int ORIENTATION_PORTRAIT = 0x01; - private static final int ORIENTATION_LANDSCAPE = 0x02; - private static final Map<Integer, String> ORIENTATION_VALUES = ImmutableMap.of( - ORIENTATION_PORTRAIT, "port", - ORIENTATION_LANDSCAPE, "land"); - - private static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0; + static final int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0x03; + + public static final int WIDE_COLOR_GAMUT_ANY = ACONFIGURATION_WIDE_COLOR_GAMUT_ANY; + public static final int WIDE_COLOR_GAMUT_NO = ACONFIGURATION_WIDE_COLOR_GAMUT_NO; + public static final int WIDE_COLOR_GAMUT_YES = ACONFIGURATION_WIDE_COLOR_GAMUT_YES; + static final int MASK_WIDE_COLOR_GAMUT = 0x03; + static final int COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED = 0; + static final int COLOR_MODE_WIDE_COLOR_GAMUT_NO = 0x01; + static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x02; + + private static final Map<Integer, String> COLOR_MODE_WIDE_COLOR_GAMUT_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(COLOR_MODE_WIDE_COLOR_GAMUT_UNDEFINED, ""); + map.put(COLOR_MODE_WIDE_COLOR_GAMUT_NO, "nowidecg"); + map.put(COLOR_MODE_WIDE_COLOR_GAMUT_YES, "widecg"); + COLOR_MODE_WIDE_COLOR_GAMUT_VALUES = Collections.unmodifiableMap(map); + } + + public static final int HDR_ANY = ACONFIGURATION_HDR_ANY; + public static final int HDR_NO = ACONFIGURATION_HDR_NO << 2; + public static final int HDR_YES = ACONFIGURATION_HDR_YES << 2; + public static final int MASK_HDR = 0x0c; + static final int COLOR_MODE_HDR_MASK = 0x0C; + static final int COLOR_MODE_HDR_UNDEFINED = 0; + static final int COLOR_MODE_HDR_NO = 0x04; + static final int COLOR_MODE_HDR_YES = 0x08; + + private static final Map<Integer, String> COLOR_MODE_HDR_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(COLOR_MODE_HDR_UNDEFINED, ""); + map.put(COLOR_MODE_HDR_NO, "lowdr"); + map.put(COLOR_MODE_HDR_YES, "highdr"); + COLOR_MODE_HDR_VALUES = Collections.unmodifiableMap(map); + } + + static final int DENSITY_DPI_UNDEFINED = 0; + static final int DENSITY_DPI_LDPI = 120; + static final int DENSITY_DPI_MDPI = 160; + static final int DENSITY_DPI_TVDPI = 213; + static final int DENSITY_DPI_HDPI = 240; + static final int DENSITY_DPI_XHDPI = 320; + static final int DENSITY_DPI_XXHDPI = 480; + static final int DENSITY_DPI_XXXHDPI = 640; + static final int DENSITY_DPI_ANY = 0xFFFE; + static final int DENSITY_DPI_NONE = 0xFFFF; + + private static final Map<Integer, String> DENSITY_DPI_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(DENSITY_DPI_UNDEFINED, ""); + map.put(DENSITY_DPI_LDPI, "ldpi"); + map.put(DENSITY_DPI_MDPI, "mdpi"); + map.put(DENSITY_DPI_TVDPI, "tvdpi"); + map.put(DENSITY_DPI_HDPI, "hdpi"); + map.put(DENSITY_DPI_XHDPI, "xhdpi"); + map.put(DENSITY_DPI_XXHDPI, "xxhdpi"); + map.put(DENSITY_DPI_XXXHDPI, "xxxhdpi"); + map.put(DENSITY_DPI_ANY, "anydpi"); + map.put(DENSITY_DPI_NONE, "nodpi"); + DENSITY_DPI_VALUES = Collections.unmodifiableMap(map); + } + + static final int KEYBOARD_NOKEYS = 1; + static final int KEYBOARD_QWERTY = 2; + static final int KEYBOARD_12KEY = 3; + + private static final Map<Integer, String> KEYBOARD_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(KEYBOARD_NOKEYS, "nokeys"); + map.put(KEYBOARD_QWERTY, "qwerty"); + map.put(KEYBOARD_12KEY, "12key"); + KEYBOARD_VALUES = Collections.unmodifiableMap(map); + } + + static final int KEYBOARDHIDDEN_MASK = 0x03; + static final int KEYBOARDHIDDEN_NO = 1; + static final int KEYBOARDHIDDEN_YES = 2; + static final int KEYBOARDHIDDEN_SOFT = 3; + + private static final Map<Integer, String> KEYBOARDHIDDEN_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(KEYBOARDHIDDEN_NO, "keysexposed"); + map.put(KEYBOARDHIDDEN_YES, "keyshidden"); + map.put(KEYBOARDHIDDEN_SOFT, "keyssoft"); + KEYBOARDHIDDEN_VALUES = Collections.unmodifiableMap(map); + } + + static final int NAVIGATION_NONAV = 1; + static final int NAVIGATION_DPAD = 2; + static final int NAVIGATION_TRACKBALL = 3; + static final int NAVIGATION_WHEEL = 4; + + private static final Map<Integer, String> NAVIGATION_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(NAVIGATION_NONAV, "nonav"); + map.put(NAVIGATION_DPAD, "dpad"); + map.put(NAVIGATION_TRACKBALL, "trackball"); + map.put(NAVIGATION_WHEEL, "wheel"); + NAVIGATION_VALUES = Collections.unmodifiableMap(map); + } + + static final int NAVIGATIONHIDDEN_MASK = 0x0C; + static final int NAVIGATIONHIDDEN_NO = 0x04; + static final int NAVIGATIONHIDDEN_YES = 0x08; + + private static final Map<Integer, String> NAVIGATIONHIDDEN_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(NAVIGATIONHIDDEN_NO, "navexposed"); + map.put(NAVIGATIONHIDDEN_YES, "navhidden"); + NAVIGATIONHIDDEN_VALUES = Collections.unmodifiableMap(map); + } + + public static final int ORIENTATION_ANY = ACONFIGURATION_ORIENTATION_ANY; + public static final int ORIENTATION_PORT = ACONFIGURATION_ORIENTATION_PORT; + public static final int ORIENTATION_LAND = ACONFIGURATION_ORIENTATION_LAND; + public static final int ORIENTATION_SQUARE = ACONFIGURATION_ORIENTATION_SQUARE; + static final int ORIENTATION_PORTRAIT = 0x01; + static final int ORIENTATION_LANDSCAPE = 0x02; + + private static final Map<Integer, String> ORIENTATION_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(ORIENTATION_PORTRAIT, "port"); + map.put(ORIENTATION_LANDSCAPE, "land"); + ORIENTATION_VALUES = Collections.unmodifiableMap(map); + } + + static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0; static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x40; static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x80; - private static final Map<Integer, String> SCREENLAYOUT_LAYOUTDIR_VALUES = ImmutableMap.of( - SCREENLAYOUT_LAYOUTDIR_LTR, "ldltr", - SCREENLAYOUT_LAYOUTDIR_RTL, "ldrtl"); - - private static final int SCREENLAYOUT_LONG_MASK = 0x30; - private static final int SCREENLAYOUT_LONG_NO = 0x10; - private static final int SCREENLAYOUT_LONG_YES = 0x20; - private static final Map<Integer, String> SCREENLAYOUT_LONG_VALUES = ImmutableMap.of( - SCREENLAYOUT_LONG_NO, "notlong", - SCREENLAYOUT_LONG_YES, "long"); - - private static final int SCREENLAYOUT_ROUND_MASK = 0x0300; - private static final int SCREENLAYOUT_ROUND_NO = 0x0100; - private static final int SCREENLAYOUT_ROUND_YES = 0x0200; - private static final Map<Integer, String> SCREENLAYOUT_ROUND_VALUES = ImmutableMap.of( - SCREENLAYOUT_ROUND_NO, "notround", - SCREENLAYOUT_ROUND_YES, "round"); - - private static final int SCREENLAYOUT_SIZE_MASK = 0x0F; - private static final int SCREENLAYOUT_SIZE_SMALL = 0x01; - private static final int SCREENLAYOUT_SIZE_NORMAL = 0x02; - private static final int SCREENLAYOUT_SIZE_LARGE = 0x03; - private static final int SCREENLAYOUT_SIZE_XLARGE = 0x04; - private static final Map<Integer, String> SCREENLAYOUT_SIZE_VALUES = ImmutableMap.of( - SCREENLAYOUT_SIZE_SMALL, "small", - SCREENLAYOUT_SIZE_NORMAL, "normal", - SCREENLAYOUT_SIZE_LARGE, "large", - SCREENLAYOUT_SIZE_XLARGE, "xlarge"); - - private static final Map<Integer, String> TOUCHSCREEN_VALUES = ImmutableMap.of( - TOUCHSCREEN_NOTOUCH, "notouch", - TOUCHSCREEN_FINGER, "finger"); - - private static final int UI_MODE_NIGHT_MASK = 0x30; - private static final Map<Integer, String> UI_MODE_NIGHT_VALUES = ImmutableMap.of( - UI_MODE_NIGHT_NO, "notnight", - UI_MODE_NIGHT_YES, "night"); - - private static final int UI_MODE_TYPE_MASK = 0x0F; - private static final Map<Integer, String> UI_MODE_TYPE_VALUES = ImmutableMap.of( - UI_MODE_TYPE_DESK, "desk", - UI_MODE_TYPE_CAR, "car", - UI_MODE_TYPE_TELEVISION, "television", - UI_MODE_TYPE_APPLIANCE, "appliance", - UI_MODE_TYPE_WATCH, "watch"); + + private static final Map<Integer, String> SCREENLAYOUT_LAYOUTDIR_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(SCREENLAYOUT_LAYOUTDIR_LTR, "ldltr"); + map.put(SCREENLAYOUT_LAYOUTDIR_RTL, "ldrtl"); + SCREENLAYOUT_LAYOUTDIR_VALUES = Collections.unmodifiableMap(map); + } // screenLayout bits for wide/long screen variation. public static final int MASK_SCREENLONG = 0x30; @@ -400,17 +435,101 @@ public class ResTable_config { public static final int SCREENLONG_ANY = ACONFIGURATION_SCREENLONG_ANY << SHIFT_SCREENLONG; public static final int SCREENLONG_NO = ACONFIGURATION_SCREENLONG_NO << SHIFT_SCREENLONG; public static final int SCREENLONG_YES = ACONFIGURATION_SCREENLONG_YES << SHIFT_SCREENLONG; + static final int SCREENLAYOUT_LONG_MASK = 0x30; + static final int SCREENLAYOUT_LONG_NO = 0x10; + static final int SCREENLAYOUT_LONG_YES = 0x20; + + private static final Map<Integer, String> SCREENLAYOUT_LONG_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(SCREENLAYOUT_LONG_NO, "notlong"); + map.put(SCREENLAYOUT_LONG_YES, "long"); + SCREENLAYOUT_LONG_VALUES = Collections.unmodifiableMap(map); + } // screenLayout2 bits for round/notround. - public static final int MASK_SCREENROUND = 0x03; + static final int MASK_SCREENROUND = 0x03; public static final int SCREENROUND_ANY = ACONFIGURATION_SCREENROUND_ANY; public static final int SCREENROUND_NO = ACONFIGURATION_SCREENROUND_NO; public static final int SCREENROUND_YES = ACONFIGURATION_SCREENROUND_YES; - public static final int ORIENTATION_ANY = ACONFIGURATION_ORIENTATION_ANY; - public static final int ORIENTATION_PORT = ACONFIGURATION_ORIENTATION_PORT; - public static final int ORIENTATION_LAND = ACONFIGURATION_ORIENTATION_LAND; - public static final int ORIENTATION_SQUARE = ACONFIGURATION_ORIENTATION_SQUARE; + static final int SCREENLAYOUT_ROUND_MASK = 0x03; + static final int SCREENLAYOUT_ROUND_NO = 0x01; + static final int SCREENLAYOUT_ROUND_YES = 0x02; + + private static final Map<Integer, String> SCREENLAYOUT_ROUND_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(SCREENLAYOUT_ROUND_NO, "notround"); + map.put(SCREENLAYOUT_ROUND_YES, "round"); + SCREENLAYOUT_ROUND_VALUES = Collections.unmodifiableMap(map); + } + + static final int SCREENLAYOUT_SIZE_MASK = 0x0F; + static final int SCREENLAYOUT_SIZE_SMALL = 0x01; + static final int SCREENLAYOUT_SIZE_NORMAL = 0x02; + static final int SCREENLAYOUT_SIZE_LARGE = 0x03; + static final int SCREENLAYOUT_SIZE_XLARGE = 0x04; + + private static final Map<Integer, String> SCREENLAYOUT_SIZE_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(SCREENLAYOUT_SIZE_SMALL, "small"); + map.put(SCREENLAYOUT_SIZE_NORMAL, "normal"); + map.put(SCREENLAYOUT_SIZE_LARGE, "large"); + map.put(SCREENLAYOUT_SIZE_XLARGE, "xlarge"); + SCREENLAYOUT_SIZE_VALUES = Collections.unmodifiableMap(map); + } + + static final int TOUCHSCREEN_NOTOUCH = 1; + @Deprecated static final int TOUCHSCREEN_STYLUS = 2; + public static final int TOUCHSCREEN_FINGER = 3; + + private static final Map<Integer, String> TOUCHSCREEN_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(TOUCHSCREEN_NOTOUCH, "notouch"); + map.put(TOUCHSCREEN_FINGER, "finger"); + TOUCHSCREEN_VALUES = Collections.unmodifiableMap(map); + } + + static final int UI_MODE_NIGHT_MASK = 0x30; + public static final int UI_MODE_NIGHT_NO = 0x10; + static final int UI_MODE_NIGHT_YES = 0x20; + + private static final Map<Integer, String> UI_MODE_NIGHT_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(UI_MODE_NIGHT_NO, "notnight"); + map.put(UI_MODE_NIGHT_YES, "night"); + UI_MODE_NIGHT_VALUES = Collections.unmodifiableMap(map); + } + + static final int UI_MODE_TYPE_MASK = 0x0F; + static final int UI_MODE_TYPE_DESK = 0x02; + static final int UI_MODE_TYPE_CAR = 0x03; + static final int UI_MODE_TYPE_TELEVISION = 0x04; + static final int UI_MODE_TYPE_APPLIANCE = 0x05; + static final int UI_MODE_TYPE_WATCH = 0x06; + static final int UI_MODE_TYPE_VR_HEADSET = 0x07; + + private static final Map<Integer, String> UI_MODE_TYPE_VALUES; + + static { + Map<Integer, String> map = new HashMap<>(); + map.put(UI_MODE_TYPE_DESK, "desk"); + map.put(UI_MODE_TYPE_CAR, "car"); + map.put(UI_MODE_TYPE_TELEVISION, "television"); + map.put(UI_MODE_TYPE_APPLIANCE, "appliance"); + map.put(UI_MODE_TYPE_WATCH, "watch"); + map.put(UI_MODE_TYPE_VR_HEADSET, "vrheadset"); + UI_MODE_TYPE_VALUES = Collections.unmodifiableMap(map); + } /** The number of bytes that this resource configuration takes up. */ int size; @@ -427,6 +546,31 @@ public class ResTable_config { return unpackLanguage(); } + /** Returns the {@link #localeScript} as a string. */ + public final String localeScriptString() { + return byteArrayToString(localeScript); + } + + /** Returns the {@link #localeVariant} as a string. */ + public final String localeVariantString() { + return byteArrayToString(localeVariant); + } + + private String byteArrayToString(byte[] data) { + int length = Bytes.indexOf(data, (byte) 0); + return new String(data, 0, length >= 0 ? length : data.length, Charsets.US_ASCII); + } + + /** Returns the wide color gamut section of {@link #colorMode}. */ + public final int colorModeWideColorGamut() { + return colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK; + } + + /** Returns the HDR section of {@link #colorMode}. */ + public final int colorModeHdr() { + return colorMode & COLOR_MODE_HDR_MASK; + } + /** Returns a packed 2-byte country code. */ @SuppressWarnings("mutable") public final byte[] country; @@ -470,22 +614,22 @@ public class ResTable_config { * @param sdkVersion The SDK version of the returned configuration. * @return A copy of this configuration with the only difference being #sdkVersion. */ - public final org.robolectric.res.android.ResTable_config withSdkVersion(int sdkVersion) { + public final ResTable_config withSdkVersion(int sdkVersion) { if (sdkVersion == this.sdkVersion) { return this; } - return new org.robolectric.res.android.ResTable_config(size, mcc, mnc, language, country, + return new ResTable_config(size, mcc, mnc, language, country, orientation, touchscreen, density, keyboard, navigation, inputFlags, screenWidth, screenHeight, sdkVersion, minorVersion, screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp, screenHeightDp, localeScript, localeVariant, - screenLayout2, screenConfigPad1, screenConfigPad2, unknown); + screenLayout2, colorMode, screenConfigPad2, unknown); } public ResTable_config(int size, int mcc, int mnc, byte[] language, byte[] country, int orientation, int touchscreen, int density, int keyboard, int navigation, int inputFlags, int screenWidth, int screenHeight, int sdkVersion, int minorVersion, int screenLayout, int uiMode, int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, - byte[] localeScript, byte[] localeVariant, byte screenLayout2, byte screenConfigPad1, + byte[] localeScript, byte[] localeVariant, byte screenLayout2, byte colorMode, short screenConfigPad2, byte[] unknown) { this.size = size; this.mcc = mcc; @@ -510,7 +654,7 @@ public class ResTable_config { this.localeScript = localeScript; this.localeVariant = localeVariant; this.screenLayout2 = screenLayout2; - this.screenConfigPad1 = screenConfigPad1; + this.colorMode = colorMode; this.screenConfigPad2 = screenConfigPad2; this.unknown = unknown; } @@ -550,15 +694,13 @@ public class ResTable_config { } public final int screenLayoutRound() { - return screenLayout2 & MASK_SCREENROUND; + return screenLayout2 & SCREENLAYOUT_ROUND_MASK; } public final void screenLayoutRound(int value) { - screenLayout2 = (byte) ((screenLayout2 & ~MASK_SCREENROUND) | value); + screenLayout2 = (byte) ((screenLayout2 & ~SCREENLAYOUT_ROUND_MASK) | value); } - public int colorMode; - public int uiMode; public final int uiModeType() { @@ -590,9 +732,9 @@ public class ResTable_config { public final byte[] localeVariant; /** An extension to {@link #screenLayout}. Contains round/notround qualifier. */ - public byte screenLayout2; - public byte screenConfigPad1; - public short screenConfigPad2; + public byte screenLayout2; // Contains round/notround qualifier. + public byte colorMode; // Wide-gamut, HDR, etc. + public short screenConfigPad2; // Reserved padding. /** Any remaining bytes in this resource configuration that are unaccounted for. */ @SuppressWarnings("mutable") @@ -611,7 +753,7 @@ public class ResTable_config { }; */ private int screenConfig2() { - return ((screenLayout2 & 0xff) << 24) | ((screenConfigPad1 * 0xff) << 16) | (screenConfigPad2 & 0xffff); + return ((screenLayout2 & 0xff) << 24) | ((colorMode * 0xff) << 16) | (screenConfigPad2 & 0xffff); } // If false and localeScript is set, it means that the script of the locale @@ -701,8 +843,8 @@ public class ResTable_config { // } // void ResTable_config::copyFromDtoH(const ResTable_config& o) { - static org.robolectric.res.android.ResTable_config fromDtoH(final org.robolectric.res.android.ResTable_config o) { - return new org.robolectric.res.android.ResTable_config( + static ResTable_config fromDtoH(final ResTable_config o) { + return new ResTable_config( 0 /*sizeof(ResTable_config)*/, dtohs((short) o.mcc), dtohs((short) o.mnc), @@ -726,7 +868,7 @@ public class ResTable_config { o.localeScript, o.localeVariant, o.screenLayout2, - o.screenConfigPad1, + o.colorMode, o.screenConfigPad2, o.unknown ); @@ -746,7 +888,7 @@ public class ResTable_config { // screenHeightDp = htods(screenHeightDp); } - static final int compareLocales(final org.robolectric.res.android.ResTable_config l, final org.robolectric.res.android.ResTable_config r) { + static final int compareLocales(final ResTable_config l, final ResTable_config r) { if (l.locale() != r.locale()) { // NOTE: This is the old behaviour with respect to comparison orders. // The diff value here doesn't make much sense (given our bit packing scheme) @@ -781,7 +923,7 @@ public class ResTable_config { return 0; } - int compare(final org.robolectric.res.android.ResTable_config o) { + int compare(final ResTable_config o) { int diff = imsi() - o.imsi(); if (diff != 0) return diff; diff = compareLocales(this, o); @@ -798,6 +940,8 @@ public class ResTable_config { if (diff != 0) return diff; diff = (screenLayout2 - o.screenLayout2); if (diff != 0) return diff; + diff = (colorMode - o.colorMode); + if (diff != 0) return diff; diff = (uiMode - o.uiMode); if (diff != 0) return diff; diff = (smallestScreenWidthDp - o.smallestScreenWidthDp); @@ -830,7 +974,9 @@ public class ResTable_config { && screenHeightDp == 0 && isZeroes(localeScript) && isZeroes(localeVariant) - && screenLayout2 == 0; + && screenLayout2 == 0 + && colorMode == 0 + ; } private boolean isZeroes(byte[] bytes1) { @@ -855,27 +1001,33 @@ public class ResTable_config { /** * Returns a map of the configuration parts for {@link #toString}. * - * If a configuration part is not defined for this {@link org.robolectric.res.android.ResTable_config}, its value + * If a configuration part is not defined for this {@link ResTable_config}, its value * will be the empty string. */ public final Map<Type, String> toStringParts() { Map<Type, String> result = new LinkedHashMap<>(); // Preserve order for #toString(). - result.put(Type.MCC, isTruthy(mcc) ? "mcc" + mcc : ""); - result.put(Type.MNC, isTruthy(mnc) ? "mnc" + mnc : ""); - result.put(Type.LANGUAGE_STRING, !languageString().isEmpty() ? "" + languageString() : ""); + result.put(Type.MCC, mcc != 0 ? "mcc" + mcc : ""); + result.put(Type.MNC, mnc != 0 ? "mnc" + mnc : ""); + result.put(Type.LANGUAGE_STRING, languageString()); + result.put(Type.LOCALE_SCRIPT_STRING, localeScriptString()); result.put(Type.REGION_STRING, !regionString().isEmpty() ? "r" + regionString() : ""); + result.put(Type.LOCALE_VARIANT_STRING, localeVariantString()); result.put(Type.SCREEN_LAYOUT_DIRECTION, getOrDefault(SCREENLAYOUT_LAYOUTDIR_VALUES, screenLayoutDirection(), "")); result.put(Type.SMALLEST_SCREEN_WIDTH_DP, - isTruthy(smallestScreenWidthDp) ? "sw" + smallestScreenWidthDp + "dp" : ""); - result.put(Type.SCREEN_WIDTH_DP, isTruthy(screenWidthDp) ? "w" + screenWidthDp + "dp" : ""); - result.put(Type.SCREEN_HEIGHT_DP, isTruthy(screenHeightDp) ? "h" + screenHeightDp + "dp" : ""); + smallestScreenWidthDp != 0 ? "sw" + smallestScreenWidthDp + "dp" : ""); + result.put(Type.SCREEN_WIDTH_DP, screenWidthDp != 0 ? "w" + screenWidthDp + "dp" : ""); + result.put(Type.SCREEN_HEIGHT_DP, screenHeightDp != 0 ? "h" + screenHeightDp + "dp" : ""); result.put(Type.SCREEN_LAYOUT_SIZE, getOrDefault(SCREENLAYOUT_SIZE_VALUES, screenLayoutSize(), "")); result.put(Type.SCREEN_LAYOUT_LONG, getOrDefault(SCREENLAYOUT_LONG_VALUES, screenLayoutLong(), "")); result.put(Type.SCREEN_LAYOUT_ROUND, getOrDefault(SCREENLAYOUT_ROUND_VALUES, screenLayoutRound(), "")); + result.put(Type.COLOR_MODE_HDR, getOrDefault(COLOR_MODE_HDR_VALUES, colorModeHdr(), "")); + result.put( + Type.COLOR_MODE_WIDE_COLOR_GAMUT, + getOrDefault(COLOR_MODE_WIDE_COLOR_GAMUT_VALUES, colorModeWideColorGamut(), "")); result.put(Type.ORIENTATION, getOrDefault(ORIENTATION_VALUES, orientation, "")); result.put(Type.UI_MODE_TYPE, getOrDefault(UI_MODE_TYPE_VALUES, uiModeType(), "")); result.put(Type.UI_MODE_NIGHT, getOrDefault(UI_MODE_NIGHT_VALUES, uiModeNight(), "")); @@ -886,7 +1038,17 @@ public class ResTable_config { result.put(Type.NAVIGATION_HIDDEN, getOrDefault(NAVIGATIONHIDDEN_VALUES, navigationHidden(), "")); result.put(Type.NAVIGATION, getOrDefault(NAVIGATION_VALUES, navigation, "")); - result.put(Type.SDK_VERSION, isTruthy(sdkVersion) ? "v" + sdkVersion : ""); + result.put(Type.SCREEN_SIZE, + screenWidth != 0 || screenHeight != 0 ? screenWidth + "x" + screenHeight : ""); + + String sdkVersion = ""; + if (this.sdkVersion != 0) { + sdkVersion = "v" + this.sdkVersion; + if (minorVersion != 0) { + sdkVersion += "." + minorVersion; + } + } + result.put(Type.SDK_VERSION, sdkVersion); return result; } @@ -905,11 +1067,12 @@ public class ResTable_config { // transliterated from https://android.googlesource.com/platform/frameworks/base/+/android-7.1.1_r13/libs/androidfw/ResourceTypes.cpp + // Changes from 8.0.0_r4 partially applied. /* */ /** - * Is {@code requested} a better match to this {@link org.robolectric.res.android.ResTable_config} object than {@code o} + * Is {@code requested} a better match to this {@link ResTable_config} object than {@code o} *//* public boolean isBetterThan(ResTable_config o, ResTable_config requested) { @@ -924,7 +1087,7 @@ public class ResTable_config { */ public boolean isBetterThan( - org.robolectric.res.android.ResTable_config o, org.robolectric.res.android.ResTable_config requested) { + ResTable_config o, ResTable_config requested) { if (isTruthy(requested)) { if (isTruthy(imsi()) || isTruthy(o.imsi())) { if ((mcc != o.mcc) && isTruthy(requested.mcc)) { @@ -1023,6 +1186,17 @@ public class ResTable_config { } } + if (isTruthy(colorMode) || isTruthy(o.colorMode)) { + if (((colorMode^o.colorMode) & MASK_WIDE_COLOR_GAMUT) != 0 && + isTruthy((requested.colorMode & MASK_WIDE_COLOR_GAMUT))) { + return isTruthy(colorMode & MASK_WIDE_COLOR_GAMUT); + } + if (((colorMode^o.colorMode) & MASK_HDR) != 0 && + isTruthy((requested.colorMode & MASK_HDR))) { + return isTruthy(colorMode & MASK_HDR); + } + } + if ((orientation != o.orientation) && isTruthy(requested.orientation)) { return isTruthy(orientation); } @@ -1180,7 +1354,7 @@ public class ResTable_config { } */ - public boolean match(final org.robolectric.res.android.ResTable_config settings) { + public boolean match(final ResTable_config settings) { if (imsi() != 0) { if (mcc != 0 && mcc != settings.mcc) { return false; @@ -1198,7 +1372,7 @@ public class ResTable_config { // // If two configs differ only in their country and variant, // they can be weeded out in the isMoreSpecificThan test. - if (language[0] != settings.language[0] || language[1] != settings.language[1]) { + if (!langsAreEquivalent(language, settings.language)) { return false; } @@ -1226,9 +1400,7 @@ public class ResTable_config { } if (countriesMustMatch) { - if (country[0] != '\0' - && (country[0] != settings.country[0] - || country[1] != settings.country[1])) { + if (country[0] != '\0' && !areIdentical(country, settings.country)) { return false; } } else { @@ -1285,6 +1457,18 @@ public class ResTable_config { } } + final int hdr = colorMode & MASK_HDR; + final int setHdr = settings.colorMode & MASK_HDR; + if (hdr != 0 && hdr != setHdr) { + return false; + } + + final int wideColorGamut = colorMode & MASK_WIDE_COLOR_GAMUT; + final int setWideColorGamut = settings.colorMode & MASK_WIDE_COLOR_GAMUT; + if (wideColorGamut != 0 && wideColorGamut != setWideColorGamut) { + return false; + } + if (screenSizeDp() != 0) { if (screenWidthDp != 0 && screenWidthDp > settings.screenWidthDp) { if (kDebugTableSuperNoisy) { @@ -1410,18 +1594,21 @@ public class ResTable_config { // } // } - String getBcp47Locale() { + String getBcp47Locale(boolean canonicalize) { StringBuilder str = new StringBuilder(); // This represents the "any" locale value, which has traditionally been // represented by the empty string. - if (!isTruthy(language[0]) && !isTruthy(country[0])) { + if (language[0] == '\0' && country[0] == '\0') { return ""; } - if (isTruthy(language[0])) { - String languageStr = unpackLanguage(); - str.append(languageStr); + if (language[0] != '\0') { + if (canonicalize && areIdentical(language, kTagalog)) { + // Replace Tagalog with Filipino if we are canonicalizing + str.setLength(0); + str.append("fil");// 3-letter code for Filipino + } } if (isTruthy(localeScript[0]) && !localeScriptWasComputed) { @@ -1433,7 +1620,7 @@ public class ResTable_config { } } - if (isTruthy(country[0])) { + if (country[0] != '\0') { if (str.length() > 0) { str.append('-'); } @@ -1454,7 +1641,7 @@ public class ResTable_config { return str.toString(); } - static boolean assignLocaleComponent(org.robolectric.res.android.ResTable_config config, + static boolean assignLocaleComponent(ResTable_config config, final String start, int size) { switch (size) { @@ -1826,7 +2013,7 @@ public class ResTable_config { return score - oScore; } - private boolean isMoreSpecificThan(org.robolectric.res.android.ResTable_config o) { + private boolean isMoreSpecificThan(ResTable_config o) { // The order of the following tests defines the importance of one // configuration parameter over another. Those tests first are more // important, trumping any values in those following them. @@ -1887,6 +2074,18 @@ public class ResTable_config { if (!isTruthy((o.screenLayout2 & MASK_SCREENROUND))) return true; } } + + if (isTruthy(colorMode) || isTruthy(o.colorMode)) { + if (((colorMode^o.colorMode) & MASK_HDR) != 0) { + if (!isTruthy((colorMode & MASK_HDR))) return false; + if (!isTruthy((o.colorMode & MASK_HDR))) return true; + } + if (((colorMode^o.colorMode) & MASK_WIDE_COLOR_GAMUT) != 0) { + if (!isTruthy((colorMode & MASK_WIDE_COLOR_GAMUT))) return false; + if (!isTruthy((o.colorMode & MASK_WIDE_COLOR_GAMUT))) return true; + } + } + if (orientation != o.orientation) { if (!isTruthy(orientation)) return false; if (!isTruthy(o.orientation)) return true; |