From 24c9aa65411207067f509c5e88ad31b303d26fcd Mon Sep 17 00:00:00 2001 From: MÃ¥rten Kongstad Date: Wed, 20 Jun 2018 08:46:41 +0200 Subject: libandroidfw: move ConfigDescription from aapt2 to libandroidfw This is to allow idmap2 to access ConfigDescription. Test: libandroidfw_tests Test: aapt2_tests Change-Id: I54210bbbd8dad5903cb7100807df977efa394ad5 --- libs/androidfw/Android.bp | 4 + libs/androidfw/ConfigDescription.cpp | 993 ++++++++++++++++++++ libs/androidfw/Locale.cpp | 260 ++++++ libs/androidfw/Util.cpp | 24 + .../include/androidfw/ConfigDescription.h | 216 +++++ libs/androidfw/include/androidfw/Locale.h | 117 +++ libs/androidfw/include/androidfw/Util.h | 3 + libs/androidfw/tests/ConfigDescription_test.cpp | 157 ++++ libs/androidfw/tests/Locale_test.cpp | 95 ++ tools/aapt2/Android.bp | 2 - tools/aapt2/ConfigDescription.cpp | 999 --------------------- tools/aapt2/ConfigDescription.h | 185 ---- tools/aapt2/ConfigDescription_test.cpp | 155 ---- tools/aapt2/DominatorTree.cpp | 3 +- tools/aapt2/DominatorTree_test.cpp | 2 + tools/aapt2/Locale.cpp | 261 ------ tools/aapt2/Locale.h | 117 --- tools/aapt2/Locale_test.cpp | 96 -- tools/aapt2/Resource.h | 12 +- tools/aapt2/ResourceParser.cpp | 1 + tools/aapt2/ResourceParser.h | 6 +- tools/aapt2/ResourceParser_test.cpp | 1 + tools/aapt2/ResourceTable.cpp | 3 +- tools/aapt2/ResourceTable.h | 38 +- tools/aapt2/ResourceTable_test.cpp | 1 + tools/aapt2/ResourceUtils.cpp | 1 + tools/aapt2/ResourceUtils.h | 4 +- tools/aapt2/StringPool.h | 8 +- tools/aapt2/cmd/Compile.cpp | 3 +- tools/aapt2/cmd/Dump.cpp | 5 +- tools/aapt2/cmd/Link.cpp | 3 +- tools/aapt2/cmd/Optimize.cpp | 2 + tools/aapt2/cmd/Util.cpp | 6 +- tools/aapt2/cmd/Util_test.cpp | 2 + tools/aapt2/compile/PseudolocaleGenerator.cpp | 1 + tools/aapt2/compile/PseudolocaleGenerator_test.cpp | 2 + tools/aapt2/configuration/ConfigurationParser.cpp | 4 +- tools/aapt2/configuration/ConfigurationParser.h | 7 +- .../configuration/ConfigurationParser.internal.h | 6 +- .../configuration/ConfigurationParser_test.cpp | 2 + tools/aapt2/dump/DumpManifest.cpp | 5 +- tools/aapt2/filter/ConfigFilter.cpp | 3 +- tools/aapt2/filter/ConfigFilter.h | 10 +- tools/aapt2/format/binary/BinaryResourceParser.h | 19 +- tools/aapt2/format/proto/ProtoDeserialize.cpp | 4 +- tools/aapt2/format/proto/ProtoDeserialize.h | 13 +- tools/aapt2/format/proto/ProtoSerialize.cpp | 2 + tools/aapt2/format/proto/ProtoSerialize.h | 4 +- tools/aapt2/format/proto/ProtoSerialize_test.cpp | 1 + tools/aapt2/java/ProguardRules_test.cpp | 1 + tools/aapt2/link/AutoVersioner.cpp | 6 +- tools/aapt2/link/AutoVersioner_test.cpp | 4 +- tools/aapt2/link/Linkers.h | 8 +- tools/aapt2/link/NoDefaultResourceRemover.cpp | 4 + tools/aapt2/link/ProductFilter_test.cpp | 2 + tools/aapt2/optimize/MultiApkGenerator.cpp | 2 + tools/aapt2/optimize/MultiApkGenerator.h | 4 +- tools/aapt2/optimize/MultiApkGenerator_test.cpp | 2 + tools/aapt2/optimize/ResourceDeduper.cpp | 2 + tools/aapt2/optimize/ResourceDeduper_test.cpp | 1 + tools/aapt2/optimize/ResourceFilter_test.cpp | 1 + tools/aapt2/optimize/VersionCollapser.cpp | 2 + tools/aapt2/process/SymbolTable.cpp | 3 +- tools/aapt2/split/TableSplitter.cpp | 4 +- tools/aapt2/split/TableSplitter.h | 4 +- tools/aapt2/split/TableSplitter_test.cpp | 2 + tools/aapt2/test/Builders.cpp | 1 + tools/aapt2/test/Builders.h | 20 +- tools/aapt2/test/Common.cpp | 2 + tools/aapt2/test/Common.h | 14 +- 70 files changed, 2048 insertions(+), 1909 deletions(-) create mode 100644 libs/androidfw/ConfigDescription.cpp create mode 100644 libs/androidfw/Locale.cpp create mode 100644 libs/androidfw/include/androidfw/ConfigDescription.h create mode 100644 libs/androidfw/include/androidfw/Locale.h create mode 100644 libs/androidfw/tests/ConfigDescription_test.cpp create mode 100644 libs/androidfw/tests/Locale_test.cpp delete mode 100644 tools/aapt2/ConfigDescription.cpp delete mode 100644 tools/aapt2/ConfigDescription.h delete mode 100644 tools/aapt2/ConfigDescription_test.cpp delete mode 100644 tools/aapt2/Locale.cpp delete mode 100644 tools/aapt2/Locale.h delete mode 100644 tools/aapt2/Locale_test.cpp diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index bba36bcba804..74cab920cf2d 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -43,8 +43,10 @@ cc_library { "AssetManager2.cpp", "AttributeResolution.cpp", "ChunkIterator.cpp", + "ConfigDescription.cpp", "Idmap.cpp", "LoadedArsc.cpp", + "Locale.cpp", "LocaleData.cpp", "misc.cpp", "ObbFile.cpp", @@ -135,10 +137,12 @@ cc_test { "tests/AttributeResolution_test.cpp", "tests/ByteBucketArray_test.cpp", "tests/Config_test.cpp", + "tests/ConfigDescription_test.cpp", "tests/ConfigLocale_test.cpp", "tests/DynamicRefTable_test.cpp", "tests/Idmap_test.cpp", "tests/LoadedArsc_test.cpp", + "tests/Locale_test.cpp", "tests/ResourceUtils_test.cpp", "tests/ResTable_test.cpp", "tests/Split_test.cpp", diff --git a/libs/androidfw/ConfigDescription.cpp b/libs/androidfw/ConfigDescription.cpp new file mode 100644 index 000000000000..1f3a89edb8af --- /dev/null +++ b/libs/androidfw/ConfigDescription.cpp @@ -0,0 +1,993 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "androidfw/ConfigDescription.h" +#include "androidfw/Locale.h" +#include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" +#include "androidfw/Util.h" + +#include +#include + +namespace android { + +static const char* kWildcardName = "any"; + +const ConfigDescription& ConfigDescription::DefaultConfig() { + static ConfigDescription config = {}; + return config; +} + +static bool parseMcc(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->mcc = 0; + return true; + } + const char* c = name; + if (tolower(*c) != 'm') return false; + c++; + if (tolower(*c) != 'c') return false; + c++; + if (tolower(*c) != 'c') return false; + c++; + + const char* val = c; + + while (*c >= '0' && *c <= '9') { + c++; + } + if (*c != 0) return false; + if (c - val != 3) return false; + + int d = atoi(val); + if (d != 0) { + if (out) out->mcc = d; + return true; + } + + return false; +} + +static bool parseMnc(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->mnc = 0; + return true; + } + const char* c = name; + if (tolower(*c) != 'm') return false; + c++; + if (tolower(*c) != 'n') return false; + c++; + if (tolower(*c) != 'c') return false; + c++; + + const char* val = c; + + while (*c >= '0' && *c <= '9') { + c++; + } + if (*c != 0) return false; + if (c - val == 0 || c - val > 3) return false; + + if (out) { + out->mnc = atoi(val); + if (out->mnc == 0) { + out->mnc = ACONFIGURATION_MNC_ZERO; + } + } + + return true; +} + +static bool parseLayoutDirection(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) | + ResTable_config::LAYOUTDIR_ANY; + return true; + } else if (strcmp(name, "ldltr") == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) | + ResTable_config::LAYOUTDIR_LTR; + return true; + } else if (strcmp(name, "ldrtl") == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) | + ResTable_config::LAYOUTDIR_RTL; + return true; + } + + return false; +} + +static bool parseScreenLayoutSize(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | + ResTable_config::SCREENSIZE_ANY; + return true; + } else if (strcmp(name, "small") == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | + ResTable_config::SCREENSIZE_SMALL; + return true; + } else if (strcmp(name, "normal") == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | + ResTable_config::SCREENSIZE_NORMAL; + return true; + } else if (strcmp(name, "large") == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | + ResTable_config::SCREENSIZE_LARGE; + return true; + } else if (strcmp(name, "xlarge") == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | + ResTable_config::SCREENSIZE_XLARGE; + return true; + } + + return false; +} + +static bool parseScreenLayoutLong(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) | + ResTable_config::SCREENLONG_ANY; + return true; + } else if (strcmp(name, "long") == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) | + ResTable_config::SCREENLONG_YES; + return true; + } else if (strcmp(name, "notlong") == 0) { + if (out) + out->screenLayout = + (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) | + ResTable_config::SCREENLONG_NO; + return true; + } + + return false; +} + +static bool parseScreenRound(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->screenLayout2 = + (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) | + ResTable_config::SCREENROUND_ANY; + return true; + } else if (strcmp(name, "round") == 0) { + if (out) + out->screenLayout2 = + (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) | + ResTable_config::SCREENROUND_YES; + return true; + } else if (strcmp(name, "notround") == 0) { + if (out) + out->screenLayout2 = + (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) | + ResTable_config::SCREENROUND_NO; + return true; + } + return false; +} + +static bool parseWideColorGamut(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->colorMode = + (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | + ResTable_config::WIDE_COLOR_GAMUT_ANY; + return true; + } else if (strcmp(name, "widecg") == 0) { + if (out) + out->colorMode = + (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | + ResTable_config::WIDE_COLOR_GAMUT_YES; + return true; + } else if (strcmp(name, "nowidecg") == 0) { + if (out) + out->colorMode = + (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | + ResTable_config::WIDE_COLOR_GAMUT_NO; + return true; + } + return false; +} + +static bool parseHdr(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->colorMode = + (out->colorMode & ~ResTable_config::MASK_HDR) | + ResTable_config::HDR_ANY; + return true; + } else if (strcmp(name, "highdr") == 0) { + if (out) + out->colorMode = + (out->colorMode & ~ResTable_config::MASK_HDR) | + ResTable_config::HDR_YES; + return true; + } else if (strcmp(name, "lowdr") == 0) { + if (out) + out->colorMode = + (out->colorMode & ~ResTable_config::MASK_HDR) | + ResTable_config::HDR_NO; + return true; + } + return false; +} + +static bool parseOrientation(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->orientation = out->ORIENTATION_ANY; + return true; + } else if (strcmp(name, "port") == 0) { + if (out) out->orientation = out->ORIENTATION_PORT; + return true; + } else if (strcmp(name, "land") == 0) { + if (out) out->orientation = out->ORIENTATION_LAND; + return true; + } else if (strcmp(name, "square") == 0) { + if (out) out->orientation = out->ORIENTATION_SQUARE; + return true; + } + + return false; +} + +static bool parseUiModeType(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | + ResTable_config::UI_MODE_TYPE_ANY; + return true; + } else if (strcmp(name, "desk") == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | + ResTable_config::UI_MODE_TYPE_DESK; + return true; + } else if (strcmp(name, "car") == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | + ResTable_config::UI_MODE_TYPE_CAR; + return true; + } else if (strcmp(name, "television") == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | + ResTable_config::UI_MODE_TYPE_TELEVISION; + return true; + } else if (strcmp(name, "appliance") == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | + ResTable_config::UI_MODE_TYPE_APPLIANCE; + return true; + } else if (strcmp(name, "watch") == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | + ResTable_config::UI_MODE_TYPE_WATCH; + return true; + } else if (strcmp(name, "vrheadset") == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | + ResTable_config::UI_MODE_TYPE_VR_HEADSET; + return true; + } + + return false; +} + +static bool parseUiModeNight(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) | + ResTable_config::UI_MODE_NIGHT_ANY; + return true; + } else if (strcmp(name, "night") == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) | + ResTable_config::UI_MODE_NIGHT_YES; + return true; + } else if (strcmp(name, "notnight") == 0) { + if (out) + out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) | + ResTable_config::UI_MODE_NIGHT_NO; + return true; + } + + return false; +} + +static bool parseDensity(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->density = ResTable_config::DENSITY_DEFAULT; + return true; + } + + if (strcmp(name, "anydpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_ANY; + return true; + } + + if (strcmp(name, "nodpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_NONE; + return true; + } + + if (strcmp(name, "ldpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_LOW; + return true; + } + + if (strcmp(name, "mdpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_MEDIUM; + return true; + } + + if (strcmp(name, "tvdpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_TV; + return true; + } + + if (strcmp(name, "hdpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_HIGH; + return true; + } + + if (strcmp(name, "xhdpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_XHIGH; + return true; + } + + if (strcmp(name, "xxhdpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_XXHIGH; + return true; + } + + if (strcmp(name, "xxxhdpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_XXXHIGH; + return true; + } + + char* c = (char*)name; + while (*c >= '0' && *c <= '9') { + c++; + } + + // check that we have 'dpi' after the last digit. + if (toupper(c[0]) != 'D' || toupper(c[1]) != 'P' || toupper(c[2]) != 'I' || + c[3] != 0) { + return false; + } + + // temporarily replace the first letter with \0 to + // use atoi. + char tmp = c[0]; + c[0] = '\0'; + + int d = atoi(name); + c[0] = tmp; + + if (d != 0) { + if (out) out->density = d; + return true; + } + + return false; +} + +static bool parseTouchscreen(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->touchscreen = out->TOUCHSCREEN_ANY; + return true; + } else if (strcmp(name, "notouch") == 0) { + if (out) out->touchscreen = out->TOUCHSCREEN_NOTOUCH; + return true; + } else if (strcmp(name, "stylus") == 0) { + if (out) out->touchscreen = out->TOUCHSCREEN_STYLUS; + return true; + } else if (strcmp(name, "finger") == 0) { + if (out) out->touchscreen = out->TOUCHSCREEN_FINGER; + return true; + } + + return false; +} + +static bool parseKeysHidden(const char* name, ResTable_config* out) { + uint8_t mask = 0; + uint8_t value = 0; + if (strcmp(name, kWildcardName) == 0) { + mask = ResTable_config::MASK_KEYSHIDDEN; + value = ResTable_config::KEYSHIDDEN_ANY; + } else if (strcmp(name, "keysexposed") == 0) { + mask = ResTable_config::MASK_KEYSHIDDEN; + value = ResTable_config::KEYSHIDDEN_NO; + } else if (strcmp(name, "keyshidden") == 0) { + mask = ResTable_config::MASK_KEYSHIDDEN; + value = ResTable_config::KEYSHIDDEN_YES; + } else if (strcmp(name, "keyssoft") == 0) { + mask = ResTable_config::MASK_KEYSHIDDEN; + value = ResTable_config::KEYSHIDDEN_SOFT; + } + + if (mask != 0) { + if (out) out->inputFlags = (out->inputFlags & ~mask) | value; + return true; + } + + return false; +} + +static bool parseKeyboard(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->keyboard = out->KEYBOARD_ANY; + return true; + } else if (strcmp(name, "nokeys") == 0) { + if (out) out->keyboard = out->KEYBOARD_NOKEYS; + return true; + } else if (strcmp(name, "qwerty") == 0) { + if (out) out->keyboard = out->KEYBOARD_QWERTY; + return true; + } else if (strcmp(name, "12key") == 0) { + if (out) out->keyboard = out->KEYBOARD_12KEY; + return true; + } + + return false; +} + +static bool parseNavHidden(const char* name, ResTable_config* out) { + uint8_t mask = 0; + uint8_t value = 0; + if (strcmp(name, kWildcardName) == 0) { + mask = ResTable_config::MASK_NAVHIDDEN; + value = ResTable_config::NAVHIDDEN_ANY; + } else if (strcmp(name, "navexposed") == 0) { + mask = ResTable_config::MASK_NAVHIDDEN; + value = ResTable_config::NAVHIDDEN_NO; + } else if (strcmp(name, "navhidden") == 0) { + mask = ResTable_config::MASK_NAVHIDDEN; + value = ResTable_config::NAVHIDDEN_YES; + } + + if (mask != 0) { + if (out) out->inputFlags = (out->inputFlags & ~mask) | value; + return true; + } + + return false; +} + +static bool parseNavigation(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->navigation = out->NAVIGATION_ANY; + return true; + } else if (strcmp(name, "nonav") == 0) { + if (out) out->navigation = out->NAVIGATION_NONAV; + return true; + } else if (strcmp(name, "dpad") == 0) { + if (out) out->navigation = out->NAVIGATION_DPAD; + return true; + } else if (strcmp(name, "trackball") == 0) { + if (out) out->navigation = out->NAVIGATION_TRACKBALL; + return true; + } else if (strcmp(name, "wheel") == 0) { + if (out) out->navigation = out->NAVIGATION_WHEEL; + return true; + } + + return false; +} + +static bool parseScreenSize(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) { + out->screenWidth = out->SCREENWIDTH_ANY; + out->screenHeight = out->SCREENHEIGHT_ANY; + } + return true; + } + + const char* x = name; + while (*x >= '0' && *x <= '9') x++; + if (x == name || *x != 'x') return false; + std::string xName(name, x - name); + x++; + + const char* y = x; + while (*y >= '0' && *y <= '9') y++; + if (y == name || *y != 0) return false; + std::string yName(x, y - x); + + uint16_t w = (uint16_t)atoi(xName.c_str()); + uint16_t h = (uint16_t)atoi(yName.c_str()); + if (w < h) { + return false; + } + + if (out) { + out->screenWidth = w; + out->screenHeight = h; + } + + return true; +} + +static bool parseSmallestScreenWidthDp(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) { + out->smallestScreenWidthDp = out->SCREENWIDTH_ANY; + } + return true; + } + + if (*name != 's') return false; + name++; + if (*name != 'w') return false; + name++; + const char* x = name; + while (*x >= '0' && *x <= '9') x++; + if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; + std::string xName(name, x - name); + + if (out) { + out->smallestScreenWidthDp = (uint16_t)atoi(xName.c_str()); + } + + return true; +} + +static bool parseScreenWidthDp(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) { + out->screenWidthDp = out->SCREENWIDTH_ANY; + } + return true; + } + + if (*name != 'w') return false; + name++; + const char* x = name; + while (*x >= '0' && *x <= '9') x++; + if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; + std::string xName(name, x - name); + + if (out) { + out->screenWidthDp = (uint16_t)atoi(xName.c_str()); + } + + return true; +} + +static bool parseScreenHeightDp(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) { + out->screenHeightDp = out->SCREENWIDTH_ANY; + } + return true; + } + + if (*name != 'h') return false; + name++; + const char* x = name; + while (*x >= '0' && *x <= '9') x++; + if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; + std::string xName(name, x - name); + + if (out) { + out->screenHeightDp = (uint16_t)atoi(xName.c_str()); + } + + return true; +} + +static bool parseVersion(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) { + out->sdkVersion = out->SDKVERSION_ANY; + out->minorVersion = out->MINORVERSION_ANY; + } + return true; + } + + if (*name != 'v') { + return false; + } + + name++; + const char* s = name; + while (*s >= '0' && *s <= '9') s++; + if (s == name || *s != 0) return false; + std::string sdkName(name, s - name); + + if (out) { + out->sdkVersion = (uint16_t)atoi(sdkName.c_str()); + out->minorVersion = 0; + } + + return true; +} + +bool ConfigDescription::Parse(const StringPiece& str, ConfigDescription* out) { + std::vector parts = util::SplitAndLowercase(str, '-'); + + ConfigDescription config; + ssize_t parts_consumed = 0; + LocaleValue locale; + + const auto parts_end = parts.end(); + auto part_iter = parts.begin(); + + if (str.size() == 0) { + goto success; + } + + if (parseMcc(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseMnc(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + // Locale spans a few '-' separators, so we let it + // control the index. + parts_consumed = locale.InitFromParts(part_iter, parts_end); + if (parts_consumed < 0) { + return false; + } else { + locale.WriteTo(&config); + part_iter += parts_consumed; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseLayoutDirection(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseSmallestScreenWidthDp(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseScreenWidthDp(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseScreenHeightDp(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseScreenLayoutSize(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseScreenLayoutLong(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseScreenRound(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseWideColorGamut(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseHdr(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseOrientation(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseUiModeType(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseUiModeNight(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseDensity(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseTouchscreen(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseKeysHidden(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseKeyboard(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseNavHidden(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseNavigation(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseScreenSize(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + if (parseVersion(part_iter->c_str(), &config)) { + ++part_iter; + if (part_iter == parts_end) { + goto success; + } + } + + // Unrecognized. + return false; + +success: + if (out != NULL) { + ApplyVersionForCompatibility(&config); + *out = config; + } + return true; +} + +void ConfigDescription::ApplyVersionForCompatibility( + ConfigDescription* config) { + uint16_t 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 || + config->colorMode & ResTable_config::MASK_HDR) { + min_sdk = SDK_O; + } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) { + min_sdk = SDK_MARSHMALLOW; + } else if (config->density == ResTable_config::DENSITY_ANY) { + min_sdk = SDK_LOLLIPOP; + } else if (config->smallestScreenWidthDp != + ResTable_config::SCREENWIDTH_ANY || + config->screenWidthDp != ResTable_config::SCREENWIDTH_ANY || + config->screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) { + 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) { + 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) { + min_sdk = SDK_DONUT; + } + + if (min_sdk > config->sdkVersion) { + config->sdkVersion = min_sdk; + } +} + +ConfigDescription ConfigDescription::CopyWithoutSdkVersion() const { + ConfigDescription copy = *this; + copy.sdkVersion = 0; + return copy; +} + +std::string ConfigDescription::GetBcp47LanguageTag(bool canonicalize) const { + char locale[RESTABLE_MAX_LOCALE_LEN]; + getBcp47Locale(locale, canonicalize); + return std::string(locale); +} + +std::string ConfigDescription::to_string() const { + const String8 str = toString(); + return std::string(str.string(), str.size()); +} + +bool ConfigDescription::Dominates(const ConfigDescription& o) const { + if (*this == o) { + return true; + } + + // Locale de-duping is not-trivial, disable for now (b/62409213). + if (diff(o) & CONFIG_LOCALE) { + return false; + } + + if (*this == DefaultConfig()) { + return true; + } + return MatchWithDensity(o) && !o.MatchWithDensity(*this) && + !isMoreSpecificThan(o) && !o.HasHigherPrecedenceThan(*this); +} + +bool ConfigDescription::HasHigherPrecedenceThan( + const ConfigDescription& o) const { + // 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. + // The ordering should be the same as ResTable_config#isBetterThan. + if (mcc || o.mcc) return (!o.mcc); + if (mnc || o.mnc) return (!o.mnc); + if (language[0] || o.language[0]) return (!o.language[0]); + if (country[0] || o.country[0]) return (!o.country[0]); + // Script and variant require either a language or country, both of which + // have higher precedence. + if ((screenLayout | o.screenLayout) & MASK_LAYOUTDIR) { + return !(o.screenLayout & MASK_LAYOUTDIR); + } + if (smallestScreenWidthDp || o.smallestScreenWidthDp) + return (!o.smallestScreenWidthDp); + if (screenWidthDp || o.screenWidthDp) return (!o.screenWidthDp); + if (screenHeightDp || o.screenHeightDp) return (!o.screenHeightDp); + if ((screenLayout | o.screenLayout) & MASK_SCREENSIZE) { + return !(o.screenLayout & MASK_SCREENSIZE); + } + if ((screenLayout | o.screenLayout) & MASK_SCREENLONG) { + return !(o.screenLayout & MASK_SCREENLONG); + } + if ((screenLayout2 | o.screenLayout2) & MASK_SCREENROUND) { + return !(o.screenLayout2 & MASK_SCREENROUND); + } + if ((colorMode | o.colorMode) & MASK_HDR) { + return !(o.colorMode & MASK_HDR); + } + if ((colorMode | o.colorMode) & MASK_WIDE_COLOR_GAMUT) { + return !(o.colorMode & MASK_WIDE_COLOR_GAMUT); + } + if (orientation || o.orientation) return (!o.orientation); + if ((uiMode | o.uiMode) & MASK_UI_MODE_TYPE) { + return !(o.uiMode & MASK_UI_MODE_TYPE); + } + if ((uiMode | o.uiMode) & MASK_UI_MODE_NIGHT) { + return !(o.uiMode & MASK_UI_MODE_NIGHT); + } + if (density || o.density) return (!o.density); + if (touchscreen || o.touchscreen) return (!o.touchscreen); + if ((inputFlags | o.inputFlags) & MASK_KEYSHIDDEN) { + return !(o.inputFlags & MASK_KEYSHIDDEN); + } + if ((inputFlags | o.inputFlags) & MASK_NAVHIDDEN) { + return !(o.inputFlags & MASK_NAVHIDDEN); + } + if (keyboard || o.keyboard) return (!o.keyboard); + if (navigation || o.navigation) return (!o.navigation); + if (screenWidth || o.screenWidth) return (!o.screenWidth); + if (screenHeight || o.screenHeight) return (!o.screenHeight); + if (sdkVersion || o.sdkVersion) return (!o.sdkVersion); + if (minorVersion || o.minorVersion) return (!o.minorVersion); + // Both configurations have nothing defined except some possible future + // value. Returning the comparison of the two configurations is a + // "best effort" at this point to protect against incorrect dominations. + return *this != o; +} + +bool ConfigDescription::ConflictsWith(const ConfigDescription& o) const { + // This method should be updated as new configuration parameters are + // introduced (e.g. screenConfig2). + auto pred = [](const uint32_t a, const uint32_t b) -> bool { + return a == 0 || b == 0 || a == b; + }; + // The values here can be found in ResTable_config#match. Density and range + // values can't lead to conflicts, and are ignored. + return !pred(mcc, o.mcc) || !pred(mnc, o.mnc) || !pred(locale, o.locale) || + !pred(screenLayout & MASK_LAYOUTDIR, + o.screenLayout & MASK_LAYOUTDIR) || + !pred(screenLayout & MASK_SCREENLONG, + o.screenLayout & MASK_SCREENLONG) || + !pred(uiMode & MASK_UI_MODE_TYPE, o.uiMode & MASK_UI_MODE_TYPE) || + !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) || + !pred(screenLayout2 & MASK_SCREENROUND, + o.screenLayout2 & MASK_SCREENROUND) || + !pred(colorMode & MASK_HDR, o.colorMode & MASK_HDR) || + !pred(colorMode & MASK_WIDE_COLOR_GAMUT, + o.colorMode & MASK_WIDE_COLOR_GAMUT) || + !pred(orientation, o.orientation) || + !pred(touchscreen, o.touchscreen) || + !pred(inputFlags & MASK_KEYSHIDDEN, o.inputFlags & MASK_KEYSHIDDEN) || + !pred(inputFlags & MASK_NAVHIDDEN, o.inputFlags & MASK_NAVHIDDEN) || + !pred(keyboard, o.keyboard) || !pred(navigation, o.navigation); +} + +bool ConfigDescription::IsCompatibleWith(const ConfigDescription& o) const { + return !ConflictsWith(o) && !Dominates(o) && !o.Dominates(*this); +} + +} // namespace android diff --git a/libs/androidfw/Locale.cpp b/libs/androidfw/Locale.cpp new file mode 100644 index 000000000000..2870066ccbba --- /dev/null +++ b/libs/androidfw/Locale.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "androidfw/Locale.h" +#include "androidfw/Util.h" + +#include + +#include +#include +#include + +using ::android::ResTable_config; +using ::android::StringPiece; + +namespace android { + +void LocaleValue::set_language(const char* language_chars) { + size_t i = 0; + while ((*language_chars) != '\0') { + language[i++] = ::tolower(*language_chars); + language_chars++; + } +} + +void LocaleValue::set_region(const char* region_chars) { + size_t i = 0; + while ((*region_chars) != '\0') { + region[i++] = ::toupper(*region_chars); + region_chars++; + } +} + +void LocaleValue::set_script(const char* script_chars) { + size_t i = 0; + while ((*script_chars) != '\0') { + if (i == 0) { + script[i++] = ::toupper(*script_chars); + } else { + script[i++] = ::tolower(*script_chars); + } + script_chars++; + } +} + +void LocaleValue::set_variant(const char* variant_chars) { + size_t i = 0; + while ((*variant_chars) != '\0') { + variant[i++] = *variant_chars; + variant_chars++; + } +} + +static inline bool is_alpha(const std::string& str) { + return std::all_of(std::begin(str), std::end(str), ::isalpha); +} + +static inline bool is_number(const std::string& str) { + return std::all_of(std::begin(str), std::end(str), ::isdigit); +} + +bool LocaleValue::InitFromFilterString(const StringPiece& str) { + // A locale (as specified in the filter) is an underscore separated name such + // as "en_US", "en_Latn_US", or "en_US_POSIX". + std::vector parts = util::SplitAndLowercase(str, '_'); + + const int num_tags = parts.size(); + bool valid = false; + if (num_tags >= 1) { + const std::string& lang = parts[0]; + if (is_alpha(lang) && (lang.length() == 2 || lang.length() == 3)) { + set_language(lang.c_str()); + valid = true; + } + } + + if (!valid || num_tags == 1) { + return valid; + } + + // At this point, valid == true && numTags > 1. + const std::string& part2 = parts[1]; + if ((part2.length() == 2 && is_alpha(part2)) || + (part2.length() == 3 && is_number(part2))) { + set_region(part2.c_str()); + } else if (part2.length() == 4 && is_alpha(part2)) { + set_script(part2.c_str()); + } else if (part2.length() >= 4 && part2.length() <= 8) { + set_variant(part2.c_str()); + } else { + valid = false; + } + + if (!valid || num_tags == 2) { + return valid; + } + + // At this point, valid == true && numTags > 1. + const std::string& part3 = parts[2]; + if (((part3.length() == 2 && is_alpha(part3)) || + (part3.length() == 3 && is_number(part3))) && + script[0]) { + set_region(part3.c_str()); + } else if (part3.length() >= 4 && part3.length() <= 8) { + set_variant(part3.c_str()); + } else { + valid = false; + } + + if (!valid || num_tags == 3) { + return valid; + } + + const std::string& part4 = parts[3]; + if (part4.length() >= 4 && part4.length() <= 8) { + set_variant(part4.c_str()); + } else { + valid = false; + } + + if (!valid || num_tags > 4) { + return false; + } + + return true; +} + +bool LocaleValue::InitFromBcp47Tag(const StringPiece& bcp47tag) { + return InitFromBcp47TagImpl(bcp47tag, '-'); +} + +bool LocaleValue::InitFromBcp47TagImpl(const StringPiece& bcp47tag, const char separator) { + std::vector subtags = util::SplitAndLowercase(bcp47tag, separator); + if (subtags.size() == 1) { + set_language(subtags[0].c_str()); + } else if (subtags.size() == 2) { + set_language(subtags[0].c_str()); + + // The second tag can either be a region, a variant or a script. + switch (subtags[1].size()) { + case 2: + case 3: + set_region(subtags[1].c_str()); + break; + case 4: + if ('0' <= subtags[1][0] && subtags[1][0] <= '9') { + // This is a variant: fall through + } else { + set_script(subtags[1].c_str()); + break; + } + case 5: + case 6: + case 7: + case 8: + set_variant(subtags[1].c_str()); + break; + default: + return false; + } + } else if (subtags.size() == 3) { + // The language is always the first subtag. + set_language(subtags[0].c_str()); + + // The second subtag can either be a script or a region code. + // If its size is 4, it's a script code, else it's a region code. + if (subtags[1].size() == 4) { + set_script(subtags[1].c_str()); + } else if (subtags[1].size() == 2 || subtags[1].size() == 3) { + set_region(subtags[1].c_str()); + } else { + return false; + } + + // The third tag can either be a region code (if the second tag was + // a script), else a variant code. + if (subtags[2].size() >= 4) { + set_variant(subtags[2].c_str()); + } else { + set_region(subtags[2].c_str()); + } + } else if (subtags.size() == 4) { + set_language(subtags[0].c_str()); + set_script(subtags[1].c_str()); + set_region(subtags[2].c_str()); + set_variant(subtags[3].c_str()); + } else { + return false; + } + return true; +} + +ssize_t LocaleValue::InitFromParts(std::vector::iterator iter, + std::vector::iterator end) { + const std::vector::iterator start_iter = iter; + + std::string& part = *iter; + if (part[0] == 'b' && part[1] == '+') { + // This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags, + // except that the separator is "+" and not "-". Skip the prefix 'b+'. + if (!InitFromBcp47TagImpl(StringPiece(part).substr(2), '+')) { + return -1; + } + ++iter; + } else { + if ((part.length() == 2 || part.length() == 3) && is_alpha(part) && part != "car") { + set_language(part.c_str()); + ++iter; + + if (iter != end) { + const std::string& region_part = *iter; + if (region_part.c_str()[0] == 'r' && region_part.length() == 3) { + set_region(region_part.c_str() + 1); + ++iter; + } + } + } + } + return static_cast(iter - start_iter); +} + +void LocaleValue::InitFromResTable(const ResTable_config& config) { + config.unpackLanguage(language); + config.unpackRegion(region); + if (config.localeScript[0] && !config.localeScriptWasComputed) { + memcpy(script, config.localeScript, sizeof(config.localeScript)); + } + + if (config.localeVariant[0]) { + memcpy(variant, config.localeVariant, sizeof(config.localeVariant)); + } +} + +void LocaleValue::WriteTo(ResTable_config* out) const { + out->packLanguage(language); + out->packRegion(region); + + if (script[0]) { + memcpy(out->localeScript, script, sizeof(out->localeScript)); + } + + if (variant[0]) { + memcpy(out->localeVariant, variant, sizeof(out->localeVariant)); + } +} + +} // namespace android diff --git a/libs/androidfw/Util.cpp b/libs/androidfw/Util.cpp index 575cd18a36dd..59c9d640bb91 100644 --- a/libs/androidfw/Util.cpp +++ b/libs/androidfw/Util.cpp @@ -16,6 +16,7 @@ #include "androidfw/Util.h" +#include #include #include "utils/ByteOrder.h" @@ -67,5 +68,28 @@ std::string Utf16ToUtf8(const StringPiece16& utf16) { return utf8; } +static std::vector SplitAndTransform( + const StringPiece& str, char sep, const std::function& f) { + std::vector parts; + const StringPiece::const_iterator end = std::end(str); + StringPiece::const_iterator start = std::begin(str); + StringPiece::const_iterator current; + do { + current = std::find(start, end, sep); + parts.emplace_back(str.substr(start, current).to_string()); + if (f) { + std::string& part = parts.back(); + std::transform(part.begin(), part.end(), part.begin(), f); + } + start = current + 1; + } while (current != end); + return parts; +} + +std::vector SplitAndLowercase(const StringPiece& str, char sep) { + return SplitAndTransform(str, sep, ::tolower); +} + + } // namespace util } // namespace android diff --git a/libs/androidfw/include/androidfw/ConfigDescription.h b/libs/androidfw/include/androidfw/ConfigDescription.h new file mode 100644 index 000000000000..29424c4462aa --- /dev/null +++ b/libs/androidfw/include/androidfw/ConfigDescription.h @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROIDFW_CONFIG_DESCRIPTION_H +#define ANDROIDFW_CONFIG_DESCRIPTION_H + +#include + +#include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" + +namespace android { + +using ApiVersion = int; + +enum : ApiVersion { + SDK_CUPCAKE = 3, + SDK_DONUT = 4, + SDK_ECLAIR = 5, + SDK_ECLAIR_0_1 = 6, + SDK_ECLAIR_MR1 = 7, + SDK_FROYO = 8, + SDK_GINGERBREAD = 9, + SDK_GINGERBREAD_MR1 = 10, + SDK_HONEYCOMB = 11, + SDK_HONEYCOMB_MR1 = 12, + SDK_HONEYCOMB_MR2 = 13, + SDK_ICE_CREAM_SANDWICH = 14, + SDK_ICE_CREAM_SANDWICH_MR1 = 15, + SDK_JELLY_BEAN = 16, + SDK_JELLY_BEAN_MR1 = 17, + SDK_JELLY_BEAN_MR2 = 18, + SDK_KITKAT = 19, + SDK_KITKAT_WATCH = 20, + SDK_LOLLIPOP = 21, + SDK_LOLLIPOP_MR1 = 22, + SDK_MARSHMALLOW = 23, + SDK_NOUGAT = 24, + SDK_NOUGAT_MR1 = 25, + SDK_O = 26, + SDK_O_MR1 = 27, + SDK_P = 28, +}; + +/* + * Subclass of ResTable_config that adds convenient + * initialization and comparison methods. + */ +struct ConfigDescription : public ResTable_config { + /** + * Returns an immutable default config. + */ + static const ConfigDescription& DefaultConfig(); + + /* + * Parse a string of the form 'fr-sw600dp-land' and fill in the + * given ResTable_config with resulting configuration parameters. + * + * The resulting configuration has the appropriate sdkVersion defined + * for backwards compatibility. + */ + static bool Parse(const android::StringPiece& str, ConfigDescription* out = nullptr); + + /** + * If the configuration uses an axis that was added after + * the original Android release, make sure the SDK version + * is set accordingly. + */ + static void ApplyVersionForCompatibility(ConfigDescription* config); + + ConfigDescription(); + ConfigDescription(const android::ResTable_config& o); // NOLINT(implicit) + ConfigDescription(const ConfigDescription& o); + ConfigDescription(ConfigDescription&& o) noexcept; + + ConfigDescription& operator=(const android::ResTable_config& o); + ConfigDescription& operator=(const ConfigDescription& o); + ConfigDescription& operator=(ConfigDescription&& o) noexcept; + + ConfigDescription CopyWithoutSdkVersion() const; + + // Returns the BCP-47 language tag of this configuration's locale. + std::string GetBcp47LanguageTag(bool canonicalize = false) const; + + std::string to_string() const; + + /** + * A configuration X dominates another configuration Y, if X has at least the + * precedence of Y and X is strictly more general than Y: for any type defined + * by X, the same type is defined by Y with a value equal to or, in the case + * of ranges, more specific than that of X. + * + * For example, the configuration 'en-w800dp' dominates 'en-rGB-w1024dp'. It + * does not dominate 'fr', 'en-w720dp', or 'mcc001-en-w800dp'. + */ + bool Dominates(const ConfigDescription& o) const; + + /** + * Returns true if this configuration defines a more important configuration + * parameter than o. For example, "en" has higher precedence than "v23", + * whereas "en" has the same precedence as "en-v23". + */ + bool HasHigherPrecedenceThan(const ConfigDescription& o) const; + + /** + * A configuration conflicts with another configuration if both + * configurations define an incompatible configuration parameter. An + * incompatible configuration parameter is a non-range, non-density parameter + * that is defined in both configurations as a different, non-default value. + */ + bool ConflictsWith(const ConfigDescription& o) const; + + /** + * A configuration is compatible with another configuration if both + * configurations can match a common concrete device configuration and are + * unrelated by domination. For example, land-v11 conflicts with port-v21 + * but is compatible with v21 (both land-v11 and v21 would match en-land-v23). + */ + bool IsCompatibleWith(const ConfigDescription& o) const; + + bool MatchWithDensity(const ConfigDescription& o) const; + + bool operator<(const ConfigDescription& o) const; + bool operator<=(const ConfigDescription& o) const; + bool operator==(const ConfigDescription& o) const; + bool operator!=(const ConfigDescription& o) const; + bool operator>=(const ConfigDescription& o) const; + bool operator>(const ConfigDescription& o) const; +}; + +inline ConfigDescription::ConfigDescription() { + memset(this, 0, sizeof(*this)); + size = sizeof(android::ResTable_config); +} + +inline ConfigDescription::ConfigDescription(const android::ResTable_config& o) { + *static_cast(this) = o; + size = sizeof(android::ResTable_config); +} + +inline ConfigDescription::ConfigDescription(const ConfigDescription& o) { + *static_cast(this) = o; +} + +inline ConfigDescription::ConfigDescription(ConfigDescription&& o) noexcept { + *this = o; +} + +inline ConfigDescription& ConfigDescription::operator=( + const android::ResTable_config& o) { + *static_cast(this) = o; + size = sizeof(android::ResTable_config); + return *this; +} + +inline ConfigDescription& ConfigDescription::operator=( + const ConfigDescription& o) { + *static_cast(this) = o; + return *this; +} + +inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) noexcept { + *this = o; + return *this; +} + +inline bool ConfigDescription::MatchWithDensity( + const ConfigDescription& o) const { + return match(o) && (density == 0 || density == o.density); +} + +inline bool ConfigDescription::operator<(const ConfigDescription& o) const { + return compare(o) < 0; +} + +inline bool ConfigDescription::operator<=(const ConfigDescription& o) const { + return compare(o) <= 0; +} + +inline bool ConfigDescription::operator==(const ConfigDescription& o) const { + return compare(o) == 0; +} + +inline bool ConfigDescription::operator!=(const ConfigDescription& o) const { + return compare(o) != 0; +} + +inline bool ConfigDescription::operator>=(const ConfigDescription& o) const { + return compare(o) >= 0; +} + +inline bool ConfigDescription::operator>(const ConfigDescription& o) const { + return compare(o) > 0; +} + +inline ::std::ostream& operator<<(::std::ostream& out, + const ConfigDescription& o) { + return out << o.toString().string(); +} + +} // namespace android + +#endif // ANDROIDFW_CONFIG_DESCRIPTION_H diff --git a/libs/androidfw/include/androidfw/Locale.h b/libs/androidfw/include/androidfw/Locale.h new file mode 100644 index 000000000000..484ed79a8efd --- /dev/null +++ b/libs/androidfw/include/androidfw/Locale.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROIDFW_LOCALE_VALUE_H +#define ANDROIDFW_LOCALE_VALUE_H + +#include +#include + +#include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" + +namespace android { + +/** + * A convenience class to build and parse locales. + */ +struct LocaleValue { + char language[4]; + char region[4]; + char script[4]; + char variant[8]; + + inline LocaleValue(); + + /** + * Initialize this LocaleValue from a config string. + */ + bool InitFromFilterString(const android::StringPiece& config); + + // Initializes this LocaleValue from a BCP-47 locale tag. + bool InitFromBcp47Tag(const android::StringPiece& bcp47tag); + + /** + * Initialize this LocaleValue from parts of a vector. + */ + ssize_t InitFromParts(std::vector::iterator iter, + std::vector::iterator end); + + /** + * Initialize this LocaleValue from a ResTable_config. + */ + void InitFromResTable(const android::ResTable_config& config); + + /** + * Set the locale in a ResTable_config from this LocaleValue. + */ + void WriteTo(android::ResTable_config* out) const; + + inline int compare(const LocaleValue& other) const; + + inline bool operator<(const LocaleValue& o) const; + inline bool operator<=(const LocaleValue& o) const; + inline bool operator==(const LocaleValue& o) const; + inline bool operator!=(const LocaleValue& o) const; + inline bool operator>=(const LocaleValue& o) const; + inline bool operator>(const LocaleValue& o) const; + + private: + bool InitFromBcp47TagImpl(const android::StringPiece& bcp47tag, const char separator); + + void set_language(const char* language); + void set_region(const char* language); + void set_script(const char* script); + void set_variant(const char* variant); +}; + +// +// Implementation +// + +LocaleValue::LocaleValue() { memset(this, 0, sizeof(LocaleValue)); } + +int LocaleValue::compare(const LocaleValue& other) const { + return memcmp(this, &other, sizeof(LocaleValue)); +} + +bool LocaleValue::operator<(const LocaleValue& o) const { + return compare(o) < 0; +} + +bool LocaleValue::operator<=(const LocaleValue& o) const { + return compare(o) <= 0; +} + +bool LocaleValue::operator==(const LocaleValue& o) const { + return compare(o) == 0; +} + +bool LocaleValue::operator!=(const LocaleValue& o) const { + return compare(o) != 0; +} + +bool LocaleValue::operator>=(const LocaleValue& o) const { + return compare(o) >= 0; +} + +bool LocaleValue::operator>(const LocaleValue& o) const { + return compare(o) > 0; +} + +} // namespace android + +#endif // ANDROIDFW_LOCALE_VALUE_H diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h index 6c9eee0b8835..10d088e02829 100644 --- a/libs/androidfw/include/androidfw/Util.h +++ b/libs/androidfw/include/androidfw/Util.h @@ -19,6 +19,7 @@ #include #include +#include #include "android-base/macros.h" @@ -116,6 +117,8 @@ std::u16string Utf8ToUtf16(const StringPiece& utf8); // Converts a UTF-16 string to a UTF-8 string. std::string Utf16ToUtf8(const StringPiece16& utf16); +std::vector SplitAndLowercase(const android::StringPiece& str, char sep); + } // namespace util } // namespace android diff --git a/libs/androidfw/tests/ConfigDescription_test.cpp b/libs/androidfw/tests/ConfigDescription_test.cpp new file mode 100644 index 000000000000..ce7f8054e2ca --- /dev/null +++ b/libs/androidfw/tests/ConfigDescription_test.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "androidfw/ConfigDescription.h" +#include "androidfw/StringPiece.h" + +#include "android-base/logging.h" + +#include "gtest/gtest.h" + +#include + +namespace android { + +static ::testing::AssertionResult TestParse( + const StringPiece& input, ConfigDescription* config = nullptr) { + if (ConfigDescription::Parse(input, config)) { + return ::testing::AssertionSuccess() << input << " was successfully parsed"; + } + return ::testing::AssertionFailure() << input << " could not be parsed"; +} + +TEST(ConfigDescriptionTest, ParseFailWhenQualifiersAreOutOfOrder) { + EXPECT_FALSE(TestParse("en-sw600dp-ldrtl")); + EXPECT_FALSE(TestParse("land-en")); + EXPECT_FALSE(TestParse("hdpi-320dpi")); +} + +TEST(ConfigDescriptionTest, ParseFailWhenQualifiersAreNotMatched) { + EXPECT_FALSE(TestParse("en-sw600dp-ILLEGAL")); +} + +TEST(ConfigDescriptionTest, ParseFailWhenQualifiersHaveTrailingDash) { + EXPECT_FALSE(TestParse("en-sw600dp-land-")); +} + +TEST(ConfigDescriptionTest, ParseBasicQualifiers) { + ConfigDescription config; + EXPECT_TRUE(TestParse("", &config)); + EXPECT_EQ(std::string(""), config.toString().string()); + + EXPECT_TRUE(TestParse("fr-land", &config)); + EXPECT_EQ(std::string("fr-land"), config.toString().string()); + + EXPECT_TRUE( + TestParse("mcc310-pl-sw720dp-normal-long-port-night-" + "xhdpi-keyssoft-qwerty-navexposed-nonav", + &config)); + EXPECT_EQ(std::string("mcc310-pl-sw720dp-normal-long-port-night-" + "xhdpi-keyssoft-qwerty-navexposed-nonav-v13"), + config.toString().string()); +} + +TEST(ConfigDescriptionTest, ParseLocales) { + ConfigDescription config; + EXPECT_TRUE(TestParse("en-rUS", &config)); + EXPECT_EQ(std::string("en-rUS"), config.toString().string()); +} + +TEST(ConfigDescriptionTest, ParseQualifierAddedInApi13) { + ConfigDescription config; + EXPECT_TRUE(TestParse("sw600dp", &config)); + EXPECT_EQ(std::string("sw600dp-v13"), config.toString().string()); + + EXPECT_TRUE(TestParse("sw600dp-v8", &config)); + EXPECT_EQ(std::string("sw600dp-v13"), config.toString().string()); +} + +TEST(ConfigDescriptionTest, ParseCarAttribute) { + ConfigDescription config; + EXPECT_TRUE(TestParse("car", &config)); + EXPECT_EQ(android::ResTable_config::UI_MODE_TYPE_CAR, config.uiMode); +} + +TEST(ConfigDescriptionTest, TestParsingRoundQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("round", &config)); + EXPECT_EQ(android::ResTable_config::SCREENROUND_YES, + config.screenLayout2 & android::ResTable_config::MASK_SCREENROUND); + EXPECT_EQ(SDK_MARSHMALLOW, config.sdkVersion); + EXPECT_EQ(std::string("round-v23"), config.toString().string()); + + EXPECT_TRUE(TestParse("notround", &config)); + EXPECT_EQ(android::ResTable_config::SCREENROUND_NO, + config.screenLayout2 & android::ResTable_config::MASK_SCREENROUND); + EXPECT_EQ(SDK_MARSHMALLOW, config.sdkVersion); + EXPECT_EQ(std::string("notround-v23"), config.toString().string()); +} + +TEST(ConfigDescriptionTest, TestWideColorGamutQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("widecg", &config)); + EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES, + config.colorMode & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("widecg-v26"), config.toString().string()); + + EXPECT_TRUE(TestParse("nowidecg", &config)); + EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO, + config.colorMode & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("nowidecg-v26"), config.toString().string()); +} + +TEST(ConfigDescriptionTest, TestHdrQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("highdr", &config)); + EXPECT_EQ(android::ResTable_config::HDR_YES, + config.colorMode & android::ResTable_config::MASK_HDR); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("highdr-v26"), config.toString().string()); + + EXPECT_TRUE(TestParse("lowdr", &config)); + EXPECT_EQ(android::ResTable_config::HDR_NO, + config.colorMode & android::ResTable_config::MASK_HDR); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("lowdr-v26"), config.toString().string()); +} + +TEST(ConfigDescriptionTest, ParseVrAttribute) { + ConfigDescription config; + EXPECT_TRUE(TestParse("vrheadset", &config)); + EXPECT_EQ(android::ResTable_config::UI_MODE_TYPE_VR_HEADSET, config.uiMode); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(std::string("vrheadset-v26"), config.toString().string()); +} + +static inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) { + ConfigDescription config; + CHECK(ConfigDescription::Parse(str, &config)) << "invalid configuration: " << str; + return config; +} + +TEST(ConfigDescriptionTest, RangeQualifiersDoNotConflict) { + EXPECT_FALSE(ParseConfigOrDie("large").ConflictsWith(ParseConfigOrDie("normal-land"))); + EXPECT_FALSE(ParseConfigOrDie("long-hdpi").ConflictsWith(ParseConfigOrDie("xhdpi"))); + EXPECT_FALSE(ParseConfigOrDie("sw600dp").ConflictsWith(ParseConfigOrDie("sw700dp"))); + EXPECT_FALSE(ParseConfigOrDie("v11").ConflictsWith(ParseConfigOrDie("v21"))); + EXPECT_FALSE(ParseConfigOrDie("h600dp").ConflictsWith(ParseConfigOrDie("h300dp"))); + EXPECT_FALSE(ParseConfigOrDie("w400dp").ConflictsWith(ParseConfigOrDie("w300dp"))); + EXPECT_FALSE(ParseConfigOrDie("600x400").ConflictsWith(ParseConfigOrDie("300x200"))); +} + +} // namespace android diff --git a/libs/androidfw/tests/Locale_test.cpp b/libs/androidfw/tests/Locale_test.cpp new file mode 100644 index 000000000000..6b2ef5f6a381 --- /dev/null +++ b/libs/androidfw/tests/Locale_test.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "androidfw/Locale.h" +#include "androidfw/Util.h" + +#include + +#include "gtest/gtest.h" + +namespace android { + +static ::testing::AssertionResult TestLanguage(const char* input, + const char* lang) { + std::vector parts = util::SplitAndLowercase(input, '-'); + LocaleValue lv; + ssize_t count = lv.InitFromParts(std::begin(parts), std::end(parts)); + if (count < 0) { + return ::testing::AssertionFailure() << " failed to parse '" << input + << "'."; + } + + if (count != 1) { + return ::testing::AssertionFailure() + << count << " parts were consumed parsing '" << input + << "' but expected 1."; + } + + if (memcmp(lv.language, lang, std::min(strlen(lang), sizeof(lv.language))) != + 0) { + return ::testing::AssertionFailure() + << "expected " << lang << " but got " + << std::string(lv.language, sizeof(lv.language)) << "."; + } + + return ::testing::AssertionSuccess(); +} + +static ::testing::AssertionResult TestLanguageRegion(const char* input, + const char* lang, + const char* region) { + std::vector parts = util::SplitAndLowercase(input, '-'); + LocaleValue lv; + ssize_t count = lv.InitFromParts(std::begin(parts), std::end(parts)); + if (count < 0) { + return ::testing::AssertionFailure() << " failed to parse '" << input + << "'."; + } + + if (count != 2) { + return ::testing::AssertionFailure() + << count << " parts were consumed parsing '" << input + << "' but expected 2."; + } + + if (memcmp(lv.language, lang, std::min(strlen(lang), sizeof(lv.language))) != + 0) { + return ::testing::AssertionFailure() + << "expected " << input << " but got " + << std::string(lv.language, sizeof(lv.language)) << "."; + } + + if (memcmp(lv.region, region, std::min(strlen(region), sizeof(lv.region))) != + 0) { + return ::testing::AssertionFailure() + << "expected " << region << " but got " + << std::string(lv.region, sizeof(lv.region)) << "."; + } + + return ::testing::AssertionSuccess(); +} + +TEST(ConfigDescriptionTest, ParseLanguage) { + EXPECT_TRUE(TestLanguage("en", "en")); + EXPECT_TRUE(TestLanguage("fr", "fr")); + EXPECT_FALSE(TestLanguage("land", "")); + EXPECT_TRUE(TestLanguage("fr-land", "fr")); + + EXPECT_TRUE(TestLanguageRegion("fr-rCA", "fr", "CA")); +} + +} // namespace android diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index c02ca211a194..ba498e19f837 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -123,7 +123,6 @@ cc_library_host_static { "util/BigBuffer.cpp", "util/Files.cpp", "util/Util.cpp", - "ConfigDescription.cpp", "Debug.cpp", "DominatorTree.cpp", "java/AnnotationProcessor.cpp", @@ -132,7 +131,6 @@ cc_library_host_static { "java/ManifestClassGenerator.cpp", "java/ProguardRules.cpp", "LoadedApk.cpp", - "Locale.cpp", "Resource.cpp", "ResourceParser.cpp", "ResourceTable.cpp", diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp deleted file mode 100644 index f621660cb8ad..000000000000 --- a/tools/aapt2/ConfigDescription.cpp +++ /dev/null @@ -1,999 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ConfigDescription.h" - -#include -#include - -#include "androidfw/ResourceTypes.h" -#include "androidfw/StringPiece.h" - -#include "Locale.h" -#include "SdkConstants.h" -#include "util/Util.h" - -using android::ResTable_config; -using android::StringPiece; - -namespace aapt { - -static const char* kWildcardName = "any"; - -const ConfigDescription& ConfigDescription::DefaultConfig() { - static ConfigDescription config = {}; - return config; -} - -static bool parseMcc(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) out->mcc = 0; - return true; - } - const char* c = name; - if (tolower(*c) != 'm') return false; - c++; - if (tolower(*c) != 'c') return false; - c++; - if (tolower(*c) != 'c') return false; - c++; - - const char* val = c; - - while (*c >= '0' && *c <= '9') { - c++; - } - if (*c != 0) return false; - if (c - val != 3) return false; - - int d = atoi(val); - if (d != 0) { - if (out) out->mcc = d; - return true; - } - - return false; -} - -static bool parseMnc(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) out->mnc = 0; - return true; - } - const char* c = name; - if (tolower(*c) != 'm') return false; - c++; - if (tolower(*c) != 'n') return false; - c++; - if (tolower(*c) != 'c') return false; - c++; - - const char* val = c; - - while (*c >= '0' && *c <= '9') { - c++; - } - if (*c != 0) return false; - if (c - val == 0 || c - val > 3) return false; - - if (out) { - out->mnc = atoi(val); - if (out->mnc == 0) { - out->mnc = ACONFIGURATION_MNC_ZERO; - } - } - - return true; -} - -static bool parseLayoutDirection(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) | - ResTable_config::LAYOUTDIR_ANY; - return true; - } else if (strcmp(name, "ldltr") == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) | - ResTable_config::LAYOUTDIR_LTR; - return true; - } else if (strcmp(name, "ldrtl") == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) | - ResTable_config::LAYOUTDIR_RTL; - return true; - } - - return false; -} - -static bool parseScreenLayoutSize(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | - ResTable_config::SCREENSIZE_ANY; - return true; - } else if (strcmp(name, "small") == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | - ResTable_config::SCREENSIZE_SMALL; - return true; - } else if (strcmp(name, "normal") == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | - ResTable_config::SCREENSIZE_NORMAL; - return true; - } else if (strcmp(name, "large") == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | - ResTable_config::SCREENSIZE_LARGE; - return true; - } else if (strcmp(name, "xlarge") == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) | - ResTable_config::SCREENSIZE_XLARGE; - return true; - } - - return false; -} - -static bool parseScreenLayoutLong(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) | - ResTable_config::SCREENLONG_ANY; - return true; - } else if (strcmp(name, "long") == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) | - ResTable_config::SCREENLONG_YES; - return true; - } else if (strcmp(name, "notlong") == 0) { - if (out) - out->screenLayout = - (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) | - ResTable_config::SCREENLONG_NO; - return true; - } - - return false; -} - -static bool parseScreenRound(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) - out->screenLayout2 = - (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) | - ResTable_config::SCREENROUND_ANY; - return true; - } else if (strcmp(name, "round") == 0) { - if (out) - out->screenLayout2 = - (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) | - ResTable_config::SCREENROUND_YES; - return true; - } else if (strcmp(name, "notround") == 0) { - if (out) - out->screenLayout2 = - (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) | - ResTable_config::SCREENROUND_NO; - return true; - } - return false; -} - -static bool parseWideColorGamut(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) - out->colorMode = - (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | - ResTable_config::WIDE_COLOR_GAMUT_ANY; - return true; - } else if (strcmp(name, "widecg") == 0) { - if (out) - out->colorMode = - (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | - ResTable_config::WIDE_COLOR_GAMUT_YES; - return true; - } else if (strcmp(name, "nowidecg") == 0) { - if (out) - out->colorMode = - (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | - ResTable_config::WIDE_COLOR_GAMUT_NO; - return true; - } - return false; -} - -static bool parseHdr(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) - out->colorMode = - (out->colorMode & ~ResTable_config::MASK_HDR) | - ResTable_config::HDR_ANY; - return true; - } else if (strcmp(name, "highdr") == 0) { - if (out) - out->colorMode = - (out->colorMode & ~ResTable_config::MASK_HDR) | - ResTable_config::HDR_YES; - return true; - } else if (strcmp(name, "lowdr") == 0) { - if (out) - out->colorMode = - (out->colorMode & ~ResTable_config::MASK_HDR) | - ResTable_config::HDR_NO; - return true; - } - return false; -} - -static bool parseOrientation(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) out->orientation = out->ORIENTATION_ANY; - return true; - } else if (strcmp(name, "port") == 0) { - if (out) out->orientation = out->ORIENTATION_PORT; - return true; - } else if (strcmp(name, "land") == 0) { - if (out) out->orientation = out->ORIENTATION_LAND; - return true; - } else if (strcmp(name, "square") == 0) { - if (out) out->orientation = out->ORIENTATION_SQUARE; - return true; - } - - return false; -} - -static bool parseUiModeType(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | - ResTable_config::UI_MODE_TYPE_ANY; - return true; - } else if (strcmp(name, "desk") == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | - ResTable_config::UI_MODE_TYPE_DESK; - return true; - } else if (strcmp(name, "car") == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | - ResTable_config::UI_MODE_TYPE_CAR; - return true; - } else if (strcmp(name, "television") == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | - ResTable_config::UI_MODE_TYPE_TELEVISION; - return true; - } else if (strcmp(name, "appliance") == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | - ResTable_config::UI_MODE_TYPE_APPLIANCE; - return true; - } else if (strcmp(name, "watch") == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | - ResTable_config::UI_MODE_TYPE_WATCH; - return true; - } else if (strcmp(name, "vrheadset") == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) | - ResTable_config::UI_MODE_TYPE_VR_HEADSET; - return true; - } - - return false; -} - -static bool parseUiModeNight(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) | - ResTable_config::UI_MODE_NIGHT_ANY; - return true; - } else if (strcmp(name, "night") == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) | - ResTable_config::UI_MODE_NIGHT_YES; - return true; - } else if (strcmp(name, "notnight") == 0) { - if (out) - out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) | - ResTable_config::UI_MODE_NIGHT_NO; - return true; - } - - return false; -} - -static bool parseDensity(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) out->density = ResTable_config::DENSITY_DEFAULT; - return true; - } - - if (strcmp(name, "anydpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_ANY; - return true; - } - - if (strcmp(name, "nodpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_NONE; - return true; - } - - if (strcmp(name, "ldpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_LOW; - return true; - } - - if (strcmp(name, "mdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_MEDIUM; - return true; - } - - if (strcmp(name, "tvdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_TV; - return true; - } - - if (strcmp(name, "hdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_HIGH; - return true; - } - - if (strcmp(name, "xhdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_XHIGH; - return true; - } - - if (strcmp(name, "xxhdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_XXHIGH; - return true; - } - - if (strcmp(name, "xxxhdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_XXXHIGH; - return true; - } - - char* c = (char*)name; - while (*c >= '0' && *c <= '9') { - c++; - } - - // check that we have 'dpi' after the last digit. - if (toupper(c[0]) != 'D' || toupper(c[1]) != 'P' || toupper(c[2]) != 'I' || - c[3] != 0) { - return false; - } - - // temporarily replace the first letter with \0 to - // use atoi. - char tmp = c[0]; - c[0] = '\0'; - - int d = atoi(name); - c[0] = tmp; - - if (d != 0) { - if (out) out->density = d; - return true; - } - - return false; -} - -static bool parseTouchscreen(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) out->touchscreen = out->TOUCHSCREEN_ANY; - return true; - } else if (strcmp(name, "notouch") == 0) { - if (out) out->touchscreen = out->TOUCHSCREEN_NOTOUCH; - return true; - } else if (strcmp(name, "stylus") == 0) { - if (out) out->touchscreen = out->TOUCHSCREEN_STYLUS; - return true; - } else if (strcmp(name, "finger") == 0) { - if (out) out->touchscreen = out->TOUCHSCREEN_FINGER; - return true; - } - - return false; -} - -static bool parseKeysHidden(const char* name, ResTable_config* out) { - uint8_t mask = 0; - uint8_t value = 0; - if (strcmp(name, kWildcardName) == 0) { - mask = ResTable_config::MASK_KEYSHIDDEN; - value = ResTable_config::KEYSHIDDEN_ANY; - } else if (strcmp(name, "keysexposed") == 0) { - mask = ResTable_config::MASK_KEYSHIDDEN; - value = ResTable_config::KEYSHIDDEN_NO; - } else if (strcmp(name, "keyshidden") == 0) { - mask = ResTable_config::MASK_KEYSHIDDEN; - value = ResTable_config::KEYSHIDDEN_YES; - } else if (strcmp(name, "keyssoft") == 0) { - mask = ResTable_config::MASK_KEYSHIDDEN; - value = ResTable_config::KEYSHIDDEN_SOFT; - } - - if (mask != 0) { - if (out) out->inputFlags = (out->inputFlags & ~mask) | value; - return true; - } - - return false; -} - -static bool parseKeyboard(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) out->keyboard = out->KEYBOARD_ANY; - return true; - } else if (strcmp(name, "nokeys") == 0) { - if (out) out->keyboard = out->KEYBOARD_NOKEYS; - return true; - } else if (strcmp(name, "qwerty") == 0) { - if (out) out->keyboard = out->KEYBOARD_QWERTY; - return true; - } else if (strcmp(name, "12key") == 0) { - if (out) out->keyboard = out->KEYBOARD_12KEY; - return true; - } - - return false; -} - -static bool parseNavHidden(const char* name, ResTable_config* out) { - uint8_t mask = 0; - uint8_t value = 0; - if (strcmp(name, kWildcardName) == 0) { - mask = ResTable_config::MASK_NAVHIDDEN; - value = ResTable_config::NAVHIDDEN_ANY; - } else if (strcmp(name, "navexposed") == 0) { - mask = ResTable_config::MASK_NAVHIDDEN; - value = ResTable_config::NAVHIDDEN_NO; - } else if (strcmp(name, "navhidden") == 0) { - mask = ResTable_config::MASK_NAVHIDDEN; - value = ResTable_config::NAVHIDDEN_YES; - } - - if (mask != 0) { - if (out) out->inputFlags = (out->inputFlags & ~mask) | value; - return true; - } - - return false; -} - -static bool parseNavigation(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) out->navigation = out->NAVIGATION_ANY; - return true; - } else if (strcmp(name, "nonav") == 0) { - if (out) out->navigation = out->NAVIGATION_NONAV; - return true; - } else if (strcmp(name, "dpad") == 0) { - if (out) out->navigation = out->NAVIGATION_DPAD; - return true; - } else if (strcmp(name, "trackball") == 0) { - if (out) out->navigation = out->NAVIGATION_TRACKBALL; - return true; - } else if (strcmp(name, "wheel") == 0) { - if (out) out->navigation = out->NAVIGATION_WHEEL; - return true; - } - - return false; -} - -static bool parseScreenSize(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->screenWidth = out->SCREENWIDTH_ANY; - out->screenHeight = out->SCREENHEIGHT_ANY; - } - return true; - } - - const char* x = name; - while (*x >= '0' && *x <= '9') x++; - if (x == name || *x != 'x') return false; - std::string xName(name, x - name); - x++; - - const char* y = x; - while (*y >= '0' && *y <= '9') y++; - if (y == name || *y != 0) return false; - std::string yName(x, y - x); - - uint16_t w = (uint16_t)atoi(xName.c_str()); - uint16_t h = (uint16_t)atoi(yName.c_str()); - if (w < h) { - return false; - } - - if (out) { - out->screenWidth = w; - out->screenHeight = h; - } - - return true; -} - -static bool parseSmallestScreenWidthDp(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->smallestScreenWidthDp = out->SCREENWIDTH_ANY; - } - return true; - } - - if (*name != 's') return false; - name++; - if (*name != 'w') return false; - name++; - const char* x = name; - while (*x >= '0' && *x <= '9') x++; - if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; - std::string xName(name, x - name); - - if (out) { - out->smallestScreenWidthDp = (uint16_t)atoi(xName.c_str()); - } - - return true; -} - -static bool parseScreenWidthDp(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->screenWidthDp = out->SCREENWIDTH_ANY; - } - return true; - } - - if (*name != 'w') return false; - name++; - const char* x = name; - while (*x >= '0' && *x <= '9') x++; - if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; - std::string xName(name, x - name); - - if (out) { - out->screenWidthDp = (uint16_t)atoi(xName.c_str()); - } - - return true; -} - -static bool parseScreenHeightDp(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->screenHeightDp = out->SCREENWIDTH_ANY; - } - return true; - } - - if (*name != 'h') return false; - name++; - const char* x = name; - while (*x >= '0' && *x <= '9') x++; - if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; - std::string xName(name, x - name); - - if (out) { - out->screenHeightDp = (uint16_t)atoi(xName.c_str()); - } - - return true; -} - -static bool parseVersion(const char* name, ResTable_config* out) { - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->sdkVersion = out->SDKVERSION_ANY; - out->minorVersion = out->MINORVERSION_ANY; - } - return true; - } - - if (*name != 'v') { - return false; - } - - name++; - const char* s = name; - while (*s >= '0' && *s <= '9') s++; - if (s == name || *s != 0) return false; - std::string sdkName(name, s - name); - - if (out) { - out->sdkVersion = (uint16_t)atoi(sdkName.c_str()); - out->minorVersion = 0; - } - - return true; -} - -bool ConfigDescription::Parse(const StringPiece& str, ConfigDescription* out) { - std::vector parts = util::SplitAndLowercase(str, '-'); - - ConfigDescription config; - ssize_t parts_consumed = 0; - LocaleValue locale; - - const auto parts_end = parts.end(); - auto part_iter = parts.begin(); - - if (str.size() == 0) { - goto success; - } - - if (parseMcc(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseMnc(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - // Locale spans a few '-' separators, so we let it - // control the index. - parts_consumed = locale.InitFromParts(part_iter, parts_end); - if (parts_consumed < 0) { - return false; - } else { - locale.WriteTo(&config); - part_iter += parts_consumed; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseLayoutDirection(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseSmallestScreenWidthDp(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseScreenWidthDp(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseScreenHeightDp(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseScreenLayoutSize(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseScreenLayoutLong(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseScreenRound(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseWideColorGamut(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseHdr(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseOrientation(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseUiModeType(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseUiModeNight(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseDensity(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseTouchscreen(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseKeysHidden(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseKeyboard(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseNavHidden(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseNavigation(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseScreenSize(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - if (parseVersion(part_iter->c_str(), &config)) { - ++part_iter; - if (part_iter == parts_end) { - goto success; - } - } - - // Unrecognized. - return false; - -success: - if (out != NULL) { - ApplyVersionForCompatibility(&config); - *out = config; - } - return true; -} - -void ConfigDescription::ApplyVersionForCompatibility( - ConfigDescription* config) { - uint16_t 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 || - config->colorMode & ResTable_config::MASK_HDR) { - min_sdk = SDK_O; - } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) { - min_sdk = SDK_MARSHMALLOW; - } else if (config->density == ResTable_config::DENSITY_ANY) { - min_sdk = SDK_LOLLIPOP; - } else if (config->smallestScreenWidthDp != - ResTable_config::SCREENWIDTH_ANY || - config->screenWidthDp != ResTable_config::SCREENWIDTH_ANY || - config->screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) { - 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) { - 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) { - min_sdk = SDK_DONUT; - } - - if (min_sdk > config->sdkVersion) { - config->sdkVersion = min_sdk; - } -} - -ConfigDescription ConfigDescription::CopyWithoutSdkVersion() const { - ConfigDescription copy = *this; - copy.sdkVersion = 0; - return copy; -} - -std::string ConfigDescription::GetBcp47LanguageTag(bool canonicalize) const { - char locale[RESTABLE_MAX_LOCALE_LEN]; - getBcp47Locale(locale, canonicalize); - return std::string(locale); -} - -std::string ConfigDescription::to_string() const { - const android::String8 str = toString(); - return std::string(str.string(), str.size()); -} - -bool ConfigDescription::Dominates(const ConfigDescription& o) const { - if (*this == o) { - return true; - } - - // Locale de-duping is not-trivial, disable for now (b/62409213). - if (diff(o) & CONFIG_LOCALE) { - return false; - } - - if (*this == DefaultConfig()) { - return true; - } - return MatchWithDensity(o) && !o.MatchWithDensity(*this) && - !isMoreSpecificThan(o) && !o.HasHigherPrecedenceThan(*this); -} - -bool ConfigDescription::HasHigherPrecedenceThan( - const ConfigDescription& o) const { - // 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. - // The ordering should be the same as ResTable_config#isBetterThan. - if (mcc || o.mcc) return (!o.mcc); - if (mnc || o.mnc) return (!o.mnc); - if (language[0] || o.language[0]) return (!o.language[0]); - if (country[0] || o.country[0]) return (!o.country[0]); - // Script and variant require either a language or country, both of which - // have higher precedence. - if ((screenLayout | o.screenLayout) & MASK_LAYOUTDIR) { - return !(o.screenLayout & MASK_LAYOUTDIR); - } - if (smallestScreenWidthDp || o.smallestScreenWidthDp) - return (!o.smallestScreenWidthDp); - if (screenWidthDp || o.screenWidthDp) return (!o.screenWidthDp); - if (screenHeightDp || o.screenHeightDp) return (!o.screenHeightDp); - if ((screenLayout | o.screenLayout) & MASK_SCREENSIZE) { - return !(o.screenLayout & MASK_SCREENSIZE); - } - if ((screenLayout | o.screenLayout) & MASK_SCREENLONG) { - return !(o.screenLayout & MASK_SCREENLONG); - } - if ((screenLayout2 | o.screenLayout2) & MASK_SCREENROUND) { - return !(o.screenLayout2 & MASK_SCREENROUND); - } - if ((colorMode | o.colorMode) & MASK_HDR) { - return !(o.colorMode & MASK_HDR); - } - if ((colorMode | o.colorMode) & MASK_WIDE_COLOR_GAMUT) { - return !(o.colorMode & MASK_WIDE_COLOR_GAMUT); - } - if (orientation || o.orientation) return (!o.orientation); - if ((uiMode | o.uiMode) & MASK_UI_MODE_TYPE) { - return !(o.uiMode & MASK_UI_MODE_TYPE); - } - if ((uiMode | o.uiMode) & MASK_UI_MODE_NIGHT) { - return !(o.uiMode & MASK_UI_MODE_NIGHT); - } - if (density || o.density) return (!o.density); - if (touchscreen || o.touchscreen) return (!o.touchscreen); - if ((inputFlags | o.inputFlags) & MASK_KEYSHIDDEN) { - return !(o.inputFlags & MASK_KEYSHIDDEN); - } - if ((inputFlags | o.inputFlags) & MASK_NAVHIDDEN) { - return !(o.inputFlags & MASK_NAVHIDDEN); - } - if (keyboard || o.keyboard) return (!o.keyboard); - if (navigation || o.navigation) return (!o.navigation); - if (screenWidth || o.screenWidth) return (!o.screenWidth); - if (screenHeight || o.screenHeight) return (!o.screenHeight); - if (sdkVersion || o.sdkVersion) return (!o.sdkVersion); - if (minorVersion || o.minorVersion) return (!o.minorVersion); - // Both configurations have nothing defined except some possible future - // value. Returning the comparison of the two configurations is a - // "best effort" at this point to protect against incorrect dominations. - return *this != o; -} - -bool ConfigDescription::ConflictsWith(const ConfigDescription& o) const { - // This method should be updated as new configuration parameters are - // introduced (e.g. screenConfig2). - auto pred = [](const uint32_t a, const uint32_t b) -> bool { - return a == 0 || b == 0 || a == b; - }; - // The values here can be found in ResTable_config#match. Density and range - // values can't lead to conflicts, and are ignored. - return !pred(mcc, o.mcc) || !pred(mnc, o.mnc) || !pred(locale, o.locale) || - !pred(screenLayout & MASK_LAYOUTDIR, - o.screenLayout & MASK_LAYOUTDIR) || - !pred(screenLayout & MASK_SCREENLONG, - o.screenLayout & MASK_SCREENLONG) || - !pred(uiMode & MASK_UI_MODE_TYPE, o.uiMode & MASK_UI_MODE_TYPE) || - !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) || - !pred(screenLayout2 & MASK_SCREENROUND, - o.screenLayout2 & MASK_SCREENROUND) || - !pred(colorMode & MASK_HDR, o.colorMode & MASK_HDR) || - !pred(colorMode & MASK_WIDE_COLOR_GAMUT, - o.colorMode & MASK_WIDE_COLOR_GAMUT) || - !pred(orientation, o.orientation) || - !pred(touchscreen, o.touchscreen) || - !pred(inputFlags & MASK_KEYSHIDDEN, o.inputFlags & MASK_KEYSHIDDEN) || - !pred(inputFlags & MASK_NAVHIDDEN, o.inputFlags & MASK_NAVHIDDEN) || - !pred(keyboard, o.keyboard) || !pred(navigation, o.navigation); -} - -bool ConfigDescription::IsCompatibleWith(const ConfigDescription& o) const { - return !ConflictsWith(o) && !Dominates(o) && !o.Dominates(*this); -} - -} // namespace aapt diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h deleted file mode 100644 index b46a50398217..000000000000 --- a/tools/aapt2/ConfigDescription.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef AAPT_CONFIG_DESCRIPTION_H -#define AAPT_CONFIG_DESCRIPTION_H - -#include - -#include "androidfw/ResourceTypes.h" -#include "androidfw/StringPiece.h" - -namespace aapt { - -/* - * Subclass of ResTable_config that adds convenient - * initialization and comparison methods. - */ -struct ConfigDescription : public android::ResTable_config { - /** - * Returns an immutable default config. - */ - static const ConfigDescription& DefaultConfig(); - - /* - * Parse a string of the form 'fr-sw600dp-land' and fill in the - * given ResTable_config with resulting configuration parameters. - * - * The resulting configuration has the appropriate sdkVersion defined - * for backwards compatibility. - */ - static bool Parse(const android::StringPiece& str, ConfigDescription* out = nullptr); - - /** - * If the configuration uses an axis that was added after - * the original Android release, make sure the SDK version - * is set accordingly. - */ - static void ApplyVersionForCompatibility(ConfigDescription* config); - - ConfigDescription(); - ConfigDescription(const android::ResTable_config& o); // NOLINT(implicit) - ConfigDescription(const ConfigDescription& o); - ConfigDescription(ConfigDescription&& o) noexcept; - - ConfigDescription& operator=(const android::ResTable_config& o); - ConfigDescription& operator=(const ConfigDescription& o); - ConfigDescription& operator=(ConfigDescription&& o) noexcept; - - ConfigDescription CopyWithoutSdkVersion() const; - - // Returns the BCP-47 language tag of this configuration's locale. - std::string GetBcp47LanguageTag(bool canonicalize = false) const; - - std::string to_string() const; - - /** - * A configuration X dominates another configuration Y, if X has at least the - * precedence of Y and X is strictly more general than Y: for any type defined - * by X, the same type is defined by Y with a value equal to or, in the case - * of ranges, more specific than that of X. - * - * For example, the configuration 'en-w800dp' dominates 'en-rGB-w1024dp'. It - * does not dominate 'fr', 'en-w720dp', or 'mcc001-en-w800dp'. - */ - bool Dominates(const ConfigDescription& o) const; - - /** - * Returns true if this configuration defines a more important configuration - * parameter than o. For example, "en" has higher precedence than "v23", - * whereas "en" has the same precedence as "en-v23". - */ - bool HasHigherPrecedenceThan(const ConfigDescription& o) const; - - /** - * A configuration conflicts with another configuration if both - * configurations define an incompatible configuration parameter. An - * incompatible configuration parameter is a non-range, non-density parameter - * that is defined in both configurations as a different, non-default value. - */ - bool ConflictsWith(const ConfigDescription& o) const; - - /** - * A configuration is compatible with another configuration if both - * configurations can match a common concrete device configuration and are - * unrelated by domination. For example, land-v11 conflicts with port-v21 - * but is compatible with v21 (both land-v11 and v21 would match en-land-v23). - */ - bool IsCompatibleWith(const ConfigDescription& o) const; - - bool MatchWithDensity(const ConfigDescription& o) const; - - bool operator<(const ConfigDescription& o) const; - bool operator<=(const ConfigDescription& o) const; - bool operator==(const ConfigDescription& o) const; - bool operator!=(const ConfigDescription& o) const; - bool operator>=(const ConfigDescription& o) const; - bool operator>(const ConfigDescription& o) const; -}; - -inline ConfigDescription::ConfigDescription() { - memset(this, 0, sizeof(*this)); - size = sizeof(android::ResTable_config); -} - -inline ConfigDescription::ConfigDescription(const android::ResTable_config& o) { - *static_cast(this) = o; - size = sizeof(android::ResTable_config); -} - -inline ConfigDescription::ConfigDescription(const ConfigDescription& o) { - *static_cast(this) = o; -} - -inline ConfigDescription::ConfigDescription(ConfigDescription&& o) noexcept { - *this = o; -} - -inline ConfigDescription& ConfigDescription::operator=( - const android::ResTable_config& o) { - *static_cast(this) = o; - size = sizeof(android::ResTable_config); - return *this; -} - -inline ConfigDescription& ConfigDescription::operator=( - const ConfigDescription& o) { - *static_cast(this) = o; - return *this; -} - -inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) noexcept { - *this = o; - return *this; -} - -inline bool ConfigDescription::MatchWithDensity( - const ConfigDescription& o) const { - return match(o) && (density == 0 || density == o.density); -} - -inline bool ConfigDescription::operator<(const ConfigDescription& o) const { - return compare(o) < 0; -} - -inline bool ConfigDescription::operator<=(const ConfigDescription& o) const { - return compare(o) <= 0; -} - -inline bool ConfigDescription::operator==(const ConfigDescription& o) const { - return compare(o) == 0; -} - -inline bool ConfigDescription::operator!=(const ConfigDescription& o) const { - return compare(o) != 0; -} - -inline bool ConfigDescription::operator>=(const ConfigDescription& o) const { - return compare(o) >= 0; -} - -inline bool ConfigDescription::operator>(const ConfigDescription& o) const { - return compare(o) > 0; -} - -inline ::std::ostream& operator<<(::std::ostream& out, - const ConfigDescription& o) { - return out << o.toString().string(); -} - -} // namespace aapt - -#endif // AAPT_CONFIG_DESCRIPTION_H diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp deleted file mode 100644 index 1f351bf7481d..000000000000 --- a/tools/aapt2/ConfigDescription_test.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ConfigDescription.h" - -#include - -#include "androidfw/StringPiece.h" - -#include "SdkConstants.h" -#include "test/Test.h" - -using android::StringPiece; - -namespace aapt { - -static ::testing::AssertionResult TestParse( - const StringPiece& input, ConfigDescription* config = nullptr) { - if (ConfigDescription::Parse(input, config)) { - return ::testing::AssertionSuccess() << input << " was successfully parsed"; - } - return ::testing::AssertionFailure() << input << " could not be parsed"; -} - -TEST(ConfigDescriptionTest, ParseFailWhenQualifiersAreOutOfOrder) { - EXPECT_FALSE(TestParse("en-sw600dp-ldrtl")); - EXPECT_FALSE(TestParse("land-en")); - EXPECT_FALSE(TestParse("hdpi-320dpi")); -} - -TEST(ConfigDescriptionTest, ParseFailWhenQualifiersAreNotMatched) { - EXPECT_FALSE(TestParse("en-sw600dp-ILLEGAL")); -} - -TEST(ConfigDescriptionTest, ParseFailWhenQualifiersHaveTrailingDash) { - EXPECT_FALSE(TestParse("en-sw600dp-land-")); -} - -TEST(ConfigDescriptionTest, ParseBasicQualifiers) { - ConfigDescription config; - EXPECT_TRUE(TestParse("", &config)); - EXPECT_EQ(std::string(""), config.toString().string()); - - EXPECT_TRUE(TestParse("fr-land", &config)); - EXPECT_EQ(std::string("fr-land"), config.toString().string()); - - EXPECT_TRUE( - TestParse("mcc310-pl-sw720dp-normal-long-port-night-" - "xhdpi-keyssoft-qwerty-navexposed-nonav", - &config)); - EXPECT_EQ(std::string("mcc310-pl-sw720dp-normal-long-port-night-" - "xhdpi-keyssoft-qwerty-navexposed-nonav-v13"), - config.toString().string()); -} - -TEST(ConfigDescriptionTest, ParseLocales) { - ConfigDescription config; - EXPECT_TRUE(TestParse("en-rUS", &config)); - EXPECT_EQ(std::string("en-rUS"), config.toString().string()); -} - -TEST(ConfigDescriptionTest, ParseQualifierAddedInApi13) { - ConfigDescription config; - EXPECT_TRUE(TestParse("sw600dp", &config)); - EXPECT_EQ(std::string("sw600dp-v13"), config.toString().string()); - - EXPECT_TRUE(TestParse("sw600dp-v8", &config)); - EXPECT_EQ(std::string("sw600dp-v13"), config.toString().string()); -} - -TEST(ConfigDescriptionTest, ParseCarAttribute) { - ConfigDescription config; - EXPECT_TRUE(TestParse("car", &config)); - EXPECT_EQ(android::ResTable_config::UI_MODE_TYPE_CAR, config.uiMode); -} - -TEST(ConfigDescriptionTest, TestParsingRoundQualifier) { - ConfigDescription config; - EXPECT_TRUE(TestParse("round", &config)); - EXPECT_EQ(android::ResTable_config::SCREENROUND_YES, - config.screenLayout2 & android::ResTable_config::MASK_SCREENROUND); - EXPECT_EQ(SDK_MARSHMALLOW, config.sdkVersion); - EXPECT_EQ(std::string("round-v23"), config.toString().string()); - - EXPECT_TRUE(TestParse("notround", &config)); - EXPECT_EQ(android::ResTable_config::SCREENROUND_NO, - config.screenLayout2 & android::ResTable_config::MASK_SCREENROUND); - EXPECT_EQ(SDK_MARSHMALLOW, config.sdkVersion); - EXPECT_EQ(std::string("notround-v23"), config.toString().string()); -} - -TEST(ConfigDescriptionTest, TestWideColorGamutQualifier) { - ConfigDescription config; - EXPECT_TRUE(TestParse("widecg", &config)); - EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES, - config.colorMode & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); - EXPECT_EQ(SDK_O, config.sdkVersion); - EXPECT_EQ(std::string("widecg-v26"), config.toString().string()); - - EXPECT_TRUE(TestParse("nowidecg", &config)); - EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO, - config.colorMode & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); - EXPECT_EQ(SDK_O, config.sdkVersion); - EXPECT_EQ(std::string("nowidecg-v26"), config.toString().string()); -} - -TEST(ConfigDescriptionTest, TestHdrQualifier) { - ConfigDescription config; - EXPECT_TRUE(TestParse("highdr", &config)); - EXPECT_EQ(android::ResTable_config::HDR_YES, - config.colorMode & android::ResTable_config::MASK_HDR); - EXPECT_EQ(SDK_O, config.sdkVersion); - EXPECT_EQ(std::string("highdr-v26"), config.toString().string()); - - EXPECT_TRUE(TestParse("lowdr", &config)); - EXPECT_EQ(android::ResTable_config::HDR_NO, - config.colorMode & android::ResTable_config::MASK_HDR); - EXPECT_EQ(SDK_O, config.sdkVersion); - EXPECT_EQ(std::string("lowdr-v26"), config.toString().string()); -} - -TEST(ConfigDescriptionTest, ParseVrAttribute) { - ConfigDescription config; - EXPECT_TRUE(TestParse("vrheadset", &config)); - EXPECT_EQ(android::ResTable_config::UI_MODE_TYPE_VR_HEADSET, config.uiMode); - EXPECT_EQ(SDK_O, config.sdkVersion); - EXPECT_EQ(std::string("vrheadset-v26"), config.toString().string()); -} - -TEST(ConfigDescriptionTest, RangeQualifiersDoNotConflict) { - using test::ParseConfigOrDie; - - EXPECT_FALSE(ParseConfigOrDie("large").ConflictsWith(ParseConfigOrDie("normal-land"))); - EXPECT_FALSE(ParseConfigOrDie("long-hdpi").ConflictsWith(ParseConfigOrDie("xhdpi"))); - EXPECT_FALSE(ParseConfigOrDie("sw600dp").ConflictsWith(ParseConfigOrDie("sw700dp"))); - EXPECT_FALSE(ParseConfigOrDie("v11").ConflictsWith(ParseConfigOrDie("v21"))); - EXPECT_FALSE(ParseConfigOrDie("h600dp").ConflictsWith(ParseConfigOrDie("h300dp"))); - EXPECT_FALSE(ParseConfigOrDie("w400dp").ConflictsWith(ParseConfigOrDie("w300dp"))); - EXPECT_FALSE(ParseConfigOrDie("600x400").ConflictsWith(ParseConfigOrDie("300x200"))); -} - -} // namespace aapt diff --git a/tools/aapt2/DominatorTree.cpp b/tools/aapt2/DominatorTree.cpp index 118a385e2253..ff18033c641a 100644 --- a/tools/aapt2/DominatorTree.cpp +++ b/tools/aapt2/DominatorTree.cpp @@ -19,8 +19,9 @@ #include #include "android-base/logging.h" +#include "androidfw/ConfigDescription.h" -#include "ConfigDescription.h" +using ::android::ConfigDescription; namespace aapt { diff --git a/tools/aapt2/DominatorTree_test.cpp b/tools/aapt2/DominatorTree_test.cpp index efc523fcf59b..fe4f951a5cd0 100644 --- a/tools/aapt2/DominatorTree_test.cpp +++ b/tools/aapt2/DominatorTree_test.cpp @@ -23,6 +23,8 @@ #include "test/Test.h" #include "util/Util.h" +using ::android::ConfigDescription; + namespace aapt { namespace { diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp deleted file mode 100644 index d81921f23904..000000000000 --- a/tools/aapt2/Locale.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Locale.h" - -#include - -#include -#include -#include - -#include "util/Util.h" - -using ::android::ResTable_config; -using ::android::StringPiece; - -namespace aapt { - -void LocaleValue::set_language(const char* language_chars) { - size_t i = 0; - while ((*language_chars) != '\0') { - language[i++] = ::tolower(*language_chars); - language_chars++; - } -} - -void LocaleValue::set_region(const char* region_chars) { - size_t i = 0; - while ((*region_chars) != '\0') { - region[i++] = ::toupper(*region_chars); - region_chars++; - } -} - -void LocaleValue::set_script(const char* script_chars) { - size_t i = 0; - while ((*script_chars) != '\0') { - if (i == 0) { - script[i++] = ::toupper(*script_chars); - } else { - script[i++] = ::tolower(*script_chars); - } - script_chars++; - } -} - -void LocaleValue::set_variant(const char* variant_chars) { - size_t i = 0; - while ((*variant_chars) != '\0') { - variant[i++] = *variant_chars; - variant_chars++; - } -} - -static inline bool is_alpha(const std::string& str) { - return std::all_of(std::begin(str), std::end(str), ::isalpha); -} - -static inline bool is_number(const std::string& str) { - return std::all_of(std::begin(str), std::end(str), ::isdigit); -} - -bool LocaleValue::InitFromFilterString(const StringPiece& str) { - // A locale (as specified in the filter) is an underscore separated name such - // as "en_US", "en_Latn_US", or "en_US_POSIX". - std::vector parts = util::SplitAndLowercase(str, '_'); - - const int num_tags = parts.size(); - bool valid = false; - if (num_tags >= 1) { - const std::string& lang = parts[0]; - if (is_alpha(lang) && (lang.length() == 2 || lang.length() == 3)) { - set_language(lang.c_str()); - valid = true; - } - } - - if (!valid || num_tags == 1) { - return valid; - } - - // At this point, valid == true && numTags > 1. - const std::string& part2 = parts[1]; - if ((part2.length() == 2 && is_alpha(part2)) || - (part2.length() == 3 && is_number(part2))) { - set_region(part2.c_str()); - } else if (part2.length() == 4 && is_alpha(part2)) { - set_script(part2.c_str()); - } else if (part2.length() >= 4 && part2.length() <= 8) { - set_variant(part2.c_str()); - } else { - valid = false; - } - - if (!valid || num_tags == 2) { - return valid; - } - - // At this point, valid == true && numTags > 1. - const std::string& part3 = parts[2]; - if (((part3.length() == 2 && is_alpha(part3)) || - (part3.length() == 3 && is_number(part3))) && - script[0]) { - set_region(part3.c_str()); - } else if (part3.length() >= 4 && part3.length() <= 8) { - set_variant(part3.c_str()); - } else { - valid = false; - } - - if (!valid || num_tags == 3) { - return valid; - } - - const std::string& part4 = parts[3]; - if (part4.length() >= 4 && part4.length() <= 8) { - set_variant(part4.c_str()); - } else { - valid = false; - } - - if (!valid || num_tags > 4) { - return false; - } - - return true; -} - -bool LocaleValue::InitFromBcp47Tag(const StringPiece& bcp47tag) { - return InitFromBcp47TagImpl(bcp47tag, '-'); -} - -bool LocaleValue::InitFromBcp47TagImpl(const StringPiece& bcp47tag, const char separator) { - std::vector subtags = util::SplitAndLowercase(bcp47tag, separator); - if (subtags.size() == 1) { - set_language(subtags[0].c_str()); - } else if (subtags.size() == 2) { - set_language(subtags[0].c_str()); - - // The second tag can either be a region, a variant or a script. - switch (subtags[1].size()) { - case 2: - case 3: - set_region(subtags[1].c_str()); - break; - case 4: - if ('0' <= subtags[1][0] && subtags[1][0] <= '9') { - // This is a variant: fall through - } else { - set_script(subtags[1].c_str()); - break; - } - case 5: - case 6: - case 7: - case 8: - set_variant(subtags[1].c_str()); - break; - default: - return false; - } - } else if (subtags.size() == 3) { - // The language is always the first subtag. - set_language(subtags[0].c_str()); - - // The second subtag can either be a script or a region code. - // If its size is 4, it's a script code, else it's a region code. - if (subtags[1].size() == 4) { - set_script(subtags[1].c_str()); - } else if (subtags[1].size() == 2 || subtags[1].size() == 3) { - set_region(subtags[1].c_str()); - } else { - return false; - } - - // The third tag can either be a region code (if the second tag was - // a script), else a variant code. - if (subtags[2].size() >= 4) { - set_variant(subtags[2].c_str()); - } else { - set_region(subtags[2].c_str()); - } - } else if (subtags.size() == 4) { - set_language(subtags[0].c_str()); - set_script(subtags[1].c_str()); - set_region(subtags[2].c_str()); - set_variant(subtags[3].c_str()); - } else { - return false; - } - return true; -} - -ssize_t LocaleValue::InitFromParts(std::vector::iterator iter, - std::vector::iterator end) { - const std::vector::iterator start_iter = iter; - - std::string& part = *iter; - if (part[0] == 'b' && part[1] == '+') { - // This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags, - // except that the separator is "+" and not "-". Skip the prefix 'b+'. - if (!InitFromBcp47TagImpl(StringPiece(part).substr(2), '+')) { - return -1; - } - ++iter; - } else { - if ((part.length() == 2 || part.length() == 3) && is_alpha(part) && part != "car") { - set_language(part.c_str()); - ++iter; - - if (iter != end) { - const std::string& region_part = *iter; - if (region_part.c_str()[0] == 'r' && region_part.length() == 3) { - set_region(region_part.c_str() + 1); - ++iter; - } - } - } - } - return static_cast(iter - start_iter); -} - -void LocaleValue::InitFromResTable(const ResTable_config& config) { - config.unpackLanguage(language); - config.unpackRegion(region); - if (config.localeScript[0] && !config.localeScriptWasComputed) { - memcpy(script, config.localeScript, sizeof(config.localeScript)); - } - - if (config.localeVariant[0]) { - memcpy(variant, config.localeVariant, sizeof(config.localeVariant)); - } -} - -void LocaleValue::WriteTo(ResTable_config* out) const { - out->packLanguage(language); - out->packRegion(region); - - if (script[0]) { - memcpy(out->localeScript, script, sizeof(out->localeScript)); - } - - if (variant[0]) { - memcpy(out->localeVariant, variant, sizeof(out->localeVariant)); - } -} - -} // namespace aapt diff --git a/tools/aapt2/Locale.h b/tools/aapt2/Locale.h deleted file mode 100644 index 6d8b598415cc..000000000000 --- a/tools/aapt2/Locale.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef AAPT_LOCALE_VALUE_H -#define AAPT_LOCALE_VALUE_H - -#include -#include - -#include "androidfw/ResourceTypes.h" -#include "androidfw/StringPiece.h" - -namespace aapt { - -/** - * A convenience class to build and parse locales. - */ -struct LocaleValue { - char language[4]; - char region[4]; - char script[4]; - char variant[8]; - - inline LocaleValue(); - - /** - * Initialize this LocaleValue from a config string. - */ - bool InitFromFilterString(const android::StringPiece& config); - - // Initializes this LocaleValue from a BCP-47 locale tag. - bool InitFromBcp47Tag(const android::StringPiece& bcp47tag); - - /** - * Initialize this LocaleValue from parts of a vector. - */ - ssize_t InitFromParts(std::vector::iterator iter, - std::vector::iterator end); - - /** - * Initialize this LocaleValue from a ResTable_config. - */ - void InitFromResTable(const android::ResTable_config& config); - - /** - * Set the locale in a ResTable_config from this LocaleValue. - */ - void WriteTo(android::ResTable_config* out) const; - - inline int compare(const LocaleValue& other) const; - - inline bool operator<(const LocaleValue& o) const; - inline bool operator<=(const LocaleValue& o) const; - inline bool operator==(const LocaleValue& o) const; - inline bool operator!=(const LocaleValue& o) const; - inline bool operator>=(const LocaleValue& o) const; - inline bool operator>(const LocaleValue& o) const; - - private: - bool InitFromBcp47TagImpl(const android::StringPiece& bcp47tag, const char separator); - - void set_language(const char* language); - void set_region(const char* language); - void set_script(const char* script); - void set_variant(const char* variant); -}; - -// -// Implementation -// - -LocaleValue::LocaleValue() { memset(this, 0, sizeof(LocaleValue)); } - -int LocaleValue::compare(const LocaleValue& other) const { - return memcmp(this, &other, sizeof(LocaleValue)); -} - -bool LocaleValue::operator<(const LocaleValue& o) const { - return compare(o) < 0; -} - -bool LocaleValue::operator<=(const LocaleValue& o) const { - return compare(o) <= 0; -} - -bool LocaleValue::operator==(const LocaleValue& o) const { - return compare(o) == 0; -} - -bool LocaleValue::operator!=(const LocaleValue& o) const { - return compare(o) != 0; -} - -bool LocaleValue::operator>=(const LocaleValue& o) const { - return compare(o) >= 0; -} - -bool LocaleValue::operator>(const LocaleValue& o) const { - return compare(o) > 0; -} - -} // namespace aapt - -#endif // AAPT_LOCALE_VALUE_H diff --git a/tools/aapt2/Locale_test.cpp b/tools/aapt2/Locale_test.cpp deleted file mode 100644 index 68b4cae44e15..000000000000 --- a/tools/aapt2/Locale_test.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Locale.h" - -#include - -#include "gtest/gtest.h" - -#include "util/Util.h" - -namespace aapt { - -static ::testing::AssertionResult TestLanguage(const char* input, - const char* lang) { - std::vector parts = util::SplitAndLowercase(input, '-'); - LocaleValue lv; - ssize_t count = lv.InitFromParts(std::begin(parts), std::end(parts)); - if (count < 0) { - return ::testing::AssertionFailure() << " failed to parse '" << input - << "'."; - } - - if (count != 1) { - return ::testing::AssertionFailure() - << count << " parts were consumed parsing '" << input - << "' but expected 1."; - } - - if (memcmp(lv.language, lang, std::min(strlen(lang), sizeof(lv.language))) != - 0) { - return ::testing::AssertionFailure() - << "expected " << lang << " but got " - << std::string(lv.language, sizeof(lv.language)) << "."; - } - - return ::testing::AssertionSuccess(); -} - -static ::testing::AssertionResult TestLanguageRegion(const char* input, - const char* lang, - const char* region) { - std::vector parts = util::SplitAndLowercase(input, '-'); - LocaleValue lv; - ssize_t count = lv.InitFromParts(std::begin(parts), std::end(parts)); - if (count < 0) { - return ::testing::AssertionFailure() << " failed to parse '" << input - << "'."; - } - - if (count != 2) { - return ::testing::AssertionFailure() - << count << " parts were consumed parsing '" << input - << "' but expected 2."; - } - - if (memcmp(lv.language, lang, std::min(strlen(lang), sizeof(lv.language))) != - 0) { - return ::testing::AssertionFailure() - << "expected " << input << " but got " - << std::string(lv.language, sizeof(lv.language)) << "."; - } - - if (memcmp(lv.region, region, std::min(strlen(region), sizeof(lv.region))) != - 0) { - return ::testing::AssertionFailure() - << "expected " << region << " but got " - << std::string(lv.region, sizeof(lv.region)) << "."; - } - - return ::testing::AssertionSuccess(); -} - -TEST(ConfigDescriptionTest, ParseLanguage) { - EXPECT_TRUE(TestLanguage("en", "en")); - EXPECT_TRUE(TestLanguage("fr", "fr")); - EXPECT_FALSE(TestLanguage("land", "")); - EXPECT_TRUE(TestLanguage("fr-land", "fr")); - - EXPECT_TRUE(TestLanguageRegion("fr-rCA", "fr", "CA")); -} - -} // namespace aapt diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h index 879d0bd8d94e..dd5c751967b8 100644 --- a/tools/aapt2/Resource.h +++ b/tools/aapt2/Resource.h @@ -24,10 +24,10 @@ #include #include +#include "androidfw/ConfigDescription.h" #include "androidfw/StringPiece.h" #include "utils/JenkinsHash.h" -#include "ConfigDescription.h" #include "Source.h" namespace aapt { @@ -176,7 +176,7 @@ struct ResourceFile { ResourceName name; // Configuration - ConfigDescription config; + android::ConfigDescription config; // Type Type type; @@ -194,7 +194,7 @@ struct ResourceFile { */ struct ResourceKey { ResourceName name; - ConfigDescription config; + android::ConfigDescription config; }; bool operator<(const ResourceKey& a, const ResourceKey& b); @@ -206,16 +206,16 @@ bool operator<(const ResourceKey& a, const ResourceKey& b); */ struct ResourceKeyRef { ResourceNameRef name; - ConfigDescription config; + android::ConfigDescription config; ResourceKeyRef() = default; - ResourceKeyRef(const ResourceNameRef& n, const ConfigDescription& c) + ResourceKeyRef(const ResourceNameRef& n, const android::ConfigDescription& c) : name(n), config(c) {} /** * Prevent taking a reference to a temporary. This is bad. */ - ResourceKeyRef(ResourceName&& n, const ConfigDescription& c) = delete; + ResourceKeyRef(ResourceName&& n, const android::ConfigDescription& c) = delete; }; bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b); diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 8719a233d774..9a3f14c8e08e 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -34,6 +34,7 @@ using ::aapt::ResourceUtils::StringBuilder; using ::aapt::text::Utf8Iterator; +using ::android::ConfigDescription; using ::android::StringPiece; namespace aapt { diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h index 68130c2512d3..06bb0c9cf264 100644 --- a/tools/aapt2/ResourceParser.h +++ b/tools/aapt2/ResourceParser.h @@ -20,9 +20,9 @@ #include #include "android-base/macros.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/StringPiece.h" -#include "ConfigDescription.h" #include "Diagnostics.h" #include "ResourceTable.h" #include "ResourceValues.h" @@ -57,7 +57,7 @@ struct ResourceParserOptions { class ResourceParser { public: ResourceParser(IDiagnostics* diag, ResourceTable* table, const Source& source, - const ConfigDescription& config, + const android::ConfigDescription& config, const ResourceParserOptions& options = {}); bool Parse(xml::XmlPullParser* parser); @@ -114,7 +114,7 @@ class ResourceParser { IDiagnostics* diag_; ResourceTable* table_; Source source_; - ConfigDescription config_; + android::ConfigDescription config_; ResourceParserOptions options_; }; diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index ee496d501113..0dff66430532 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -29,6 +29,7 @@ using ::aapt::io::StringInputStream; using ::aapt::test::StrValueEq; using ::aapt::test::ValueEq; +using ::android::ConfigDescription; using ::android::Res_value; using ::android::ResTable_map; using ::android::StringPiece; diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 23322ab277bf..056a27bf011d 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -23,9 +23,9 @@ #include "android-base/logging.h" #include "android-base/stringprintf.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/ResourceTypes.h" -#include "ConfigDescription.h" #include "Debug.h" #include "NameMangler.h" #include "ResourceValues.h" @@ -34,6 +34,7 @@ #include "util/Util.h" using ::aapt::text::IsValidResourceEntryName; +using ::android::ConfigDescription; using ::android::StringPiece; using ::android::base::StringPrintf; diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index 5a43a2d86cfe..1917d7e78c4f 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -17,7 +17,6 @@ #ifndef AAPT_RESOURCE_TABLE_H #define AAPT_RESOURCE_TABLE_H -#include "ConfigDescription.h" #include "Diagnostics.h" #include "Resource.h" #include "ResourceValues.h" @@ -26,6 +25,7 @@ #include "io/File.h" #include "android-base/macros.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/StringPiece.h" #include @@ -66,7 +66,7 @@ struct Overlayable { class ResourceConfigValue { public: // The configuration for which this value is defined. - const ConfigDescription config; + const android::ConfigDescription config; // The product for which this value is defined. const std::string product; @@ -74,7 +74,7 @@ class ResourceConfigValue { // The actual Value. std::unique_ptr value; - ResourceConfigValue(const ConfigDescription& config, const android::StringPiece& product) + ResourceConfigValue(const android::ConfigDescription& config, const android::StringPiece& product) : config(config), product(product.to_string()) {} private: @@ -103,14 +103,14 @@ class ResourceEntry { explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {} - ResourceConfigValue* FindValue(const ConfigDescription& config); + ResourceConfigValue* FindValue(const android::ConfigDescription& config); - ResourceConfigValue* FindValue(const ConfigDescription& config, + ResourceConfigValue* FindValue(const android::ConfigDescription& config, const android::StringPiece& product); - ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config, + ResourceConfigValue* FindOrCreateValue(const android::ConfigDescription& config, const android::StringPiece& product); - std::vector FindAllValues(const ConfigDescription& config); + std::vector FindAllValues(const android::ConfigDescription& config); template std::vector FindValuesIf(Func f) { @@ -189,29 +189,30 @@ class ResourceTable { // When a collision of resources occurs, this method keeps both values static CollisionResult IgnoreCollision(Value* existing, Value* incoming); - bool AddResource(const ResourceNameRef& name, const ConfigDescription& config, + bool AddResource(const ResourceNameRef& name, const android::ConfigDescription& config, const android::StringPiece& product, std::unique_ptr value, IDiagnostics* diag); bool AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id, - const ConfigDescription& config, const android::StringPiece& product, - std::unique_ptr value, IDiagnostics* diag); + const android::ConfigDescription& config, + const android::StringPiece& product, std::unique_ptr value, + IDiagnostics* diag); - bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config, + bool AddFileReference(const ResourceNameRef& name, const android::ConfigDescription& config, const Source& source, const android::StringPiece& path, IDiagnostics* diag); - bool AddFileReferenceMangled(const ResourceNameRef& name, const ConfigDescription& config, + bool AddFileReferenceMangled(const ResourceNameRef& name, const android::ConfigDescription& config, const Source& source, const android::StringPiece& path, io::IFile* file, IDiagnostics* diag); // Same as AddResource, but doesn't verify the validity of the name. This is used // when loading resources from an existing binary resource table that may have mangled names. - bool AddResourceMangled(const ResourceNameRef& name, const ConfigDescription& config, + bool AddResourceMangled(const ResourceNameRef& name, const android::ConfigDescription& config, const android::StringPiece& product, std::unique_ptr value, IDiagnostics* diag); bool AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id, - const ConfigDescription& config, + const android::ConfigDescription& config, const android::StringPiece& product, std::unique_ptr value, IDiagnostics* diag); @@ -286,11 +287,12 @@ class ResourceTable { IDiagnostics* diag); bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id, - const ConfigDescription& config, const android::StringPiece& product, - std::unique_ptr value, NameValidator name_validator, - const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag); + const android::ConfigDescription& config, + const android::StringPiece& product, std::unique_ptr value, + NameValidator name_validator, const CollisionResolverFunc& conflict_resolver, + IDiagnostics* diag); - bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config, + bool AddFileReferenceImpl(const ResourceNameRef& name, const android::ConfigDescription& config, const Source& source, const android::StringPiece& path, io::IFile* file, NameValidator name_validator, IDiagnostics* diag); diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp index 1aa97511dd37..05c6f1531d34 100644 --- a/tools/aapt2/ResourceTable_test.cpp +++ b/tools/aapt2/ResourceTable_test.cpp @@ -24,6 +24,7 @@ #include #include +using ::android::ConfigDescription; using ::android::StringPiece; using ::testing::Eq; using ::testing::NotNull; diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index de00fcaea07b..dbe5ac5adb98 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -31,6 +31,7 @@ #include "util/Util.h" using ::aapt::text::Utf8Iterator; +using ::android::ConfigDescription; using ::android::StringPiece; using ::android::StringPiece16; using ::android::base::StringPrintf; diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h index 410ef28ce78a..e282fd58d261 100644 --- a/tools/aapt2/ResourceUtils.h +++ b/tools/aapt2/ResourceUtils.h @@ -20,6 +20,7 @@ #include #include +#include "androidfw/ConfigDescription.h" #include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" @@ -219,7 +220,8 @@ std::string BuildResourceFileName(const ResourceFile& res_file, // Parses the binary form of a resource value. `type` is used as a hint to know when a value is // an ID versus a False boolean value, etc. `config` is for sorting strings in the string pool. -std::unique_ptr ParseBinaryResValue(const ResourceType& type, const ConfigDescription& config, +std::unique_ptr ParseBinaryResValue(const ResourceType& type, + const android::ConfigDescription& config, const android::ResStringPool& src_pool, const android::Res_value& res_value, StringPool* dst_pool); diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h index f5b464de2ea5..1006ca970dc5 100644 --- a/tools/aapt2/StringPool.h +++ b/tools/aapt2/StringPool.h @@ -24,9 +24,9 @@ #include #include "android-base/macros.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/StringPiece.h" -#include "ConfigDescription.h" #include "Diagnostics.h" #include "util/BigBuffer.h" @@ -60,12 +60,12 @@ class StringPool { kLowPriority = 0xffffffffu, }; uint32_t priority = kNormalPriority; - ConfigDescription config; + android::ConfigDescription config; Context() = default; - Context(uint32_t p, const ConfigDescription& c) : priority(p), config(c) {} + Context(uint32_t p, const android::ConfigDescription& c) : priority(p), config(c) {} explicit Context(uint32_t p) : priority(p) {} - explicit Context(const ConfigDescription& c) : priority(kNormalPriority), config(c) { + explicit Context(const android::ConfigDescription& c) : priority(kNormalPriority), config(c) { } }; diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 8060a8de4629..fc9514a691d2 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -22,11 +22,11 @@ #include "android-base/errors.h" #include "android-base/file.h" #include "android-base/utf8.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/StringPiece.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" -#include "ConfigDescription.h" #include "Diagnostics.h" #include "ResourceParser.h" #include "ResourceTable.h" @@ -53,6 +53,7 @@ using ::aapt::io::FileInputStream; using ::aapt::text::Printer; +using ::android::ConfigDescription; using ::android::StringPiece; using ::android::base::SystemErrorCodeToString; using ::google::protobuf::io::CopyingOutputStreamAdaptor; diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp index 91e39771e490..d80b5ea38bbd 100644 --- a/tools/aapt2/cmd/Dump.cpp +++ b/tools/aapt2/cmd/Dump.cpp @@ -20,6 +20,7 @@ #include #include "android-base/stringprintf.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/StringPiece.h" #include "Debug.h" @@ -233,12 +234,12 @@ int DumpConfigsCommand::Action(const std::vector& args) { Printer printer(&fout); // Comparison function used to order configurations - auto compare = [](ConfigDescription c1, ConfigDescription c2) -> bool { + auto compare = [](android::ConfigDescription c1, android::ConfigDescription c2) -> bool { return c1.compare(c2) < 0; }; // Insert the configurations into a set in order to keep every configuarion seen - std::set configs(compare); + std::set configs(compare); for (auto& package : table->packages) { for (auto& type : package->types) { for (auto& entry : type->entries) { diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 20ea3cb6ffac..186f8a159fe7 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -27,12 +27,12 @@ #include "android-base/errors.h" #include "android-base/file.h" #include "android-base/stringprintf.h" +#include "androidfw/Locale.h" #include "androidfw/StringPiece.h" #include "AppInfo.h" #include "Debug.h" #include "LoadedApk.h" -#include "Locale.h" #include "NameMangler.h" #include "ResourceUtils.h" #include "ResourceValues.h" @@ -70,6 +70,7 @@ #include "xml/XmlDom.h" using ::aapt::io::FileInputStream; +using ::android::ConfigDescription; using ::android::StringPiece; using ::android::base::StringPrintf; diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index 47288ec092de..328b0beda372 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -22,6 +22,7 @@ #include "android-base/file.h" #include "android-base/stringprintf.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" @@ -47,6 +48,7 @@ using ::aapt::configuration::Abi; using ::aapt::configuration::OutputArtifact; +using ::android::ConfigDescription; using ::android::ResTable_config; using ::android::StringPiece; using ::android::base::ReadFileToString; diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp index 5862d31e3f94..792120e449ae 100644 --- a/tools/aapt2/cmd/Util.cpp +++ b/tools/aapt2/cmd/Util.cpp @@ -19,15 +19,17 @@ #include #include "android-base/logging.h" +#include "androidfw/ConfigDescription.h" +#include "androidfw/Locale.h" -#include "ConfigDescription.h" -#include "Locale.h" #include "ResourceUtils.h" #include "ValueVisitor.h" #include "split/TableSplitter.h" #include "util/Maybe.h" #include "util/Util.h" +using ::android::ConfigDescription; +using ::android::LocaleValue; using ::android::StringPiece; using ::android::base::StringPrintf; diff --git a/tools/aapt2/cmd/Util_test.cpp b/tools/aapt2/cmd/Util_test.cpp index 6aeff08e618e..f92f1e3c4c7e 100644 --- a/tools/aapt2/cmd/Util_test.cpp +++ b/tools/aapt2/cmd/Util_test.cpp @@ -24,6 +24,8 @@ #include "test/Test.h" #include "util/Files.h" +using ::android::ConfigDescription; + namespace aapt { #ifdef _WIN32 diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp index 36c24bc4a0fd..c5de9e058907 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator.cpp +++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp @@ -24,6 +24,7 @@ #include "compile/Pseudolocalizer.h" #include "util/Util.h" +using ::android::ConfigDescription; using ::android::StringPiece; using ::android::StringPiece16; diff --git a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp index 711558aa51c1..31358020ab60 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp +++ b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp @@ -19,6 +19,8 @@ #include "test/Test.h" #include "util/Util.h" +using ::android::ConfigDescription; + namespace aapt { TEST(PseudolocaleGeneratorTest, PseudolocalizeStyledString) { diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp index 902334b98d00..dd06b38f6c01 100644 --- a/tools/aapt2/configuration/ConfigurationParser.cpp +++ b/tools/aapt2/configuration/ConfigurationParser.cpp @@ -25,8 +25,8 @@ #include "android-base/file.h" #include "android-base/logging.h" +#include "androidfw/ConfigDescription.h" -#include "ConfigDescription.h" #include "Diagnostics.h" #include "ResourceUtils.h" #include "configuration/ConfigurationParser.internal.h" @@ -40,6 +40,8 @@ #include "xml/XmlDom.h" #include "xml/XmlUtil.h" +using ::android::ConfigDescription; + namespace aapt { namespace { diff --git a/tools/aapt2/configuration/ConfigurationParser.h b/tools/aapt2/configuration/ConfigurationParser.h index 7f1d4453f9b3..b9e3be9393c9 100644 --- a/tools/aapt2/configuration/ConfigurationParser.h +++ b/tools/aapt2/configuration/ConfigurationParser.h @@ -22,7 +22,8 @@ #include #include -#include "ConfigDescription.h" +#include "androidfw/ConfigDescription.h" + #include "Diagnostics.h" #include "util/Maybe.h" @@ -109,8 +110,8 @@ struct OutputArtifact { std::string name; int version; std::vector abis; - std::vector screen_densities; - std::vector locales; + std::vector screen_densities; + std::vector locales; Maybe android_sdk; std::vector features; std::vector textures; diff --git a/tools/aapt2/configuration/ConfigurationParser.internal.h b/tools/aapt2/configuration/ConfigurationParser.internal.h index f071a69fc9e3..c541688bc018 100644 --- a/tools/aapt2/configuration/ConfigurationParser.internal.h +++ b/tools/aapt2/configuration/ConfigurationParser.internal.h @@ -17,6 +17,8 @@ #ifndef AAPT2_CONFIGURATIONPARSER_INTERNAL_H #define AAPT2_CONFIGURATIONPARSER_INTERNAL_H +#include "androidfw/ConfigDescription.h" + #include "configuration/ConfigurationParser.h" #include @@ -148,8 +150,8 @@ struct PostProcessingConfiguration { Maybe artifact_format; Group abi_groups; - Group screen_density_groups; - Group locale_groups; + Group screen_density_groups; + Group locale_groups; Group device_feature_groups; Group gl_texture_groups; Entry android_sdks; diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp index ccaea4e2a771..3a71e836aa38 100644 --- a/tools/aapt2/configuration/ConfigurationParser_test.cpp +++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp @@ -26,6 +26,8 @@ #include "test/Test.h" #include "xml/XmlDom.h" +using ::android::ConfigDescription; + namespace aapt { namespace configuration { diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp index 2c356d1491d5..e547e47d6322 100644 --- a/tools/aapt2/dump/DumpManifest.cpp +++ b/tools/aapt2/dump/DumpManifest.cpp @@ -24,7 +24,10 @@ #include "process/IResourceTableConsumer.h" #include "xml/XmlDom.h" +#include "androidfw/ConfigDescription.h" + using ::android::base::StringPrintf; +using ::android::ConfigDescription; namespace aapt { @@ -2194,4 +2197,4 @@ int DumpPermissionsCommand::Action(const std::vector& args) { return 0; } -} // namespace aapt \ No newline at end of file +} // namespace aapt diff --git a/tools/aapt2/filter/ConfigFilter.cpp b/tools/aapt2/filter/ConfigFilter.cpp index 5fbe77e98144..9d10d595882a 100644 --- a/tools/aapt2/filter/ConfigFilter.cpp +++ b/tools/aapt2/filter/ConfigFilter.cpp @@ -16,9 +16,10 @@ #include "filter/ConfigFilter.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/ResourceTypes.h" -#include "ConfigDescription.h" +using ::android::ConfigDescription; namespace aapt { diff --git a/tools/aapt2/filter/ConfigFilter.h b/tools/aapt2/filter/ConfigFilter.h index ebb81519dceb..c4b7e4356df9 100644 --- a/tools/aapt2/filter/ConfigFilter.h +++ b/tools/aapt2/filter/ConfigFilter.h @@ -20,7 +20,7 @@ #include #include -#include "ConfigDescription.h" +#include "androidfw/ConfigDescription.h" namespace aapt { @@ -34,7 +34,7 @@ class IConfigFilter { /** * Returns true if the filter matches the configuration, false otherwise. */ - virtual bool Match(const ConfigDescription& config) const = 0; + virtual bool Match(const android::ConfigDescription& config) const = 0; }; /** @@ -46,12 +46,12 @@ class IConfigFilter { */ class AxisConfigFilter : public IConfigFilter { public: - void AddConfig(ConfigDescription config); + void AddConfig(android::ConfigDescription config); - bool Match(const ConfigDescription& config) const override; + bool Match(const android::ConfigDescription& config) const override; private: - std::set> configs_; + std::set> configs_; uint32_t config_mask_ = 0; }; diff --git a/tools/aapt2/format/binary/BinaryResourceParser.h b/tools/aapt2/format/binary/BinaryResourceParser.h index a1f9f83edfb6..2bdc051f4e29 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.h +++ b/tools/aapt2/format/binary/BinaryResourceParser.h @@ -20,6 +20,7 @@ #include #include "android-base/macros.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/ResourceTypes.h" #include "ResourceTable.h" @@ -54,22 +55,28 @@ class BinaryResourceParser { bool ParseType(const ResourceTablePackage* package, const android::ResChunk_header* chunk); bool ParseLibrary(const android::ResChunk_header* chunk); - std::unique_ptr ParseValue(const ResourceNameRef& name, const ConfigDescription& config, + std::unique_ptr ParseValue(const ResourceNameRef& name, + const android::ConfigDescription& config, const android::Res_value& value); - std::unique_ptr ParseMapEntry(const ResourceNameRef& name, const ConfigDescription& config, + std::unique_ptr ParseMapEntry(const ResourceNameRef& name, + const android::ConfigDescription& config, const android::ResTable_map_entry* map); - std::unique_ptr