diff options
Diffstat (limited to 'tools')
125 files changed, 2587 insertions, 1984 deletions
diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp index 565d2f0a0549..d0026a28ba16 100644 --- a/tools/aapt/AaptConfig.cpp +++ b/tools/aapt/AaptConfig.cpp @@ -131,6 +131,22 @@ bool parse(const String8& str, ConfigDescription* out) { part = parts[index].string(); } + if (parseWideColorGamut(part, &config)) { + index++; + if (index == N) { + goto success; + } + part = parts[index].string(); + } + + if (parseHdr(part, &config)) { + index++; + if (index == N) { + goto success; + } + part = parts[index].string(); + } + if (parseOrientation(part, &config)) { index++; if (index == N) { @@ -250,7 +266,9 @@ void applyVersionForCompatibility(ConfigDescription* config) { uint16_t minSdk = 0; if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE) - == ResTable_config::UI_MODE_TYPE_VR_HEADSET) { + == ResTable_config::UI_MODE_TYPE_VR_HEADSET + || config->colorimetry & ResTable_config::MASK_WIDE_COLOR_GAMUT + || config->colorimetry & ResTable_config::MASK_HDR) { minSdk = SDK_O; } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) { minSdk = SDK_MNC; @@ -431,6 +449,46 @@ bool parseScreenRound(const char* name, ResTable_config* out) { return false; } +bool parseWideColorGamut(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT) + | ResTable_config::WIDE_COLOR_GAMUT_ANY; + return true; + } else if (strcmp(name, "widecg") == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT) + | ResTable_config::WIDE_COLOR_GAMUT_YES; + return true; + } else if (strcmp(name, "nowidecg") == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT) + | ResTable_config::WIDE_COLOR_GAMUT_NO; + return true; + } + return false; +} + +bool parseHdr(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_HDR) + | ResTable_config::HDR_ANY; + return true; + } else if (strcmp(name, "highdr") == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_HDR) + | ResTable_config::HDR_YES; + return true; + } else if (strcmp(name, "lowdr") == 0) { + if (out) out->colorimetry = + (out->colorimetry&~ResTable_config::MASK_HDR) + | ResTable_config::HDR_NO; + return true; + } + return false; +} + bool parseOrientation(const char* name, ResTable_config* out) { if (strcmp(name, kWildcardName) == 0) { if (out) out->orientation = out->ORIENTATION_ANY; diff --git a/tools/aapt/AaptConfig.h b/tools/aapt/AaptConfig.h index 04c763f20d31..a6dd252281f5 100644 --- a/tools/aapt/AaptConfig.h +++ b/tools/aapt/AaptConfig.h @@ -61,6 +61,8 @@ bool parseScreenHeightDp(const char* str, android::ResTable_config* out = NULL); bool parseScreenLayoutSize(const char* str, android::ResTable_config* out = NULL); bool parseScreenLayoutLong(const char* str, android::ResTable_config* out = NULL); bool parseScreenRound(const char* name, android::ResTable_config* out = NULL); +bool parseWideColorGamut(const char* name, android::ResTable_config* out = NULL); +bool parseHdr(const char* name, android::ResTable_config* out = NULL); bool parseOrientation(const char* str, android::ResTable_config* out = NULL); bool parseUiModeType(const char* str, android::ResTable_config* out = NULL); bool parseUiModeNight(const char* str, android::ResTable_config* out = NULL); diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 75a316092a02..045d68c3bbae 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -211,7 +211,7 @@ private: bool isValidResourceType(const String8& type) { return type == "anim" || type == "animator" || type == "interpolator" - || type == "transition" + || type == "transition" || type == "font" || type == "drawable" || type == "layout" || type == "values" || type == "xml" || type == "raw" || type == "color" || type == "menu" || type == "mipmap"; diff --git a/tools/aapt/tests/AaptConfig_test.cpp b/tools/aapt/tests/AaptConfig_test.cpp index 8bb38bac6d42..23f61e9e4b70 100644 --- a/tools/aapt/tests/AaptConfig_test.cpp +++ b/tools/aapt/tests/AaptConfig_test.cpp @@ -98,3 +98,33 @@ TEST(AaptConfigTest, TestParsingRoundQualifier) { EXPECT_EQ(SDK_MNC, config.sdkVersion); EXPECT_EQ(String8("notround-v23"), config.toString()); } + +TEST(AaptConfigTest, WideColorGamutQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("widecg", &config)); + EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES, + config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(String8("widecg-v26"), config.toString()); + + EXPECT_TRUE(TestParse("nowidecg", &config)); + EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO, + config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(String8("nowidecg-v26"), config.toString()); +} + +TEST(AaptConfigTest, HdrQualifier) { + ConfigDescription config; + EXPECT_TRUE(TestParse("highdr", &config)); + EXPECT_EQ(android::ResTable_config::HDR_YES, + config.colorimetry & android::ResTable_config::MASK_HDR); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(String8("highdr-v26"), config.toString()); + + EXPECT_TRUE(TestParse("lowdr", &config)); + EXPECT_EQ(android::ResTable_config::HDR_NO, + config.colorimetry & android::ResTable_config::MASK_HDR); + EXPECT_EQ(SDK_O, config.sdkVersion); + EXPECT_EQ(String8("lowdr-v26"), config.toString()); +}
\ No newline at end of file diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp new file mode 100644 index 000000000000..20439cc498e6 --- /dev/null +++ b/tools/aapt2/Android.bp @@ -0,0 +1,170 @@ +// +// 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. +// + +toolSources = [ + "compile/Compile.cpp", + "diff/Diff.cpp", + "dump/Dump.cpp", + "link/Link.cpp", +] + +cc_defaults { + name: "aapt_defaults", + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + ], + cppflags: [ + "-Wno-missing-field-initializers", + "-fno-exceptions", + "-fno-rtti", + ], + target: { + windows: { + enabled: true, + cflags: ["-Wno-maybe-uninitialized"], + static_libs: ["libz"], + }, + darwin: { + cflags: ["-D_DARWIN_UNLIMITED_STREAMS"], + host_ldlibs: ["-lz"], + }, + linux: { + host_ldlibs: ["-lz"], + }, + }, + static_libs: [ + "libandroidfw", + "libutils", + "liblog", + "libcutils", + "libexpat", + "libziparchive", + "libpng", + "libbase", + "libprotobuf-cpp-lite", + ], + group_static_libs: true, +} + +// ========================================================== +// NOTE: Do not add any shared libraries. +// AAPT2 is built to run on many environments +// that may not have the required dependencies. +// ========================================================== + +// ========================================================== +// Build the host static library: aapt2 +// ========================================================== +cc_library_host_static { + name: "libaapt2", + srcs: [ + "compile/IdAssigner.cpp", + "compile/InlineXmlFormatParser.cpp", + "compile/NinePatch.cpp", + "compile/Png.cpp", + "compile/PngChunkFilter.cpp", + "compile/PngCrunch.cpp", + "compile/PseudolocaleGenerator.cpp", + "compile/Pseudolocalizer.cpp", + "compile/XmlIdCollector.cpp", + "filter/ConfigFilter.cpp", + "flatten/Archive.cpp", + "flatten/TableFlattener.cpp", + "flatten/XmlFlattener.cpp", + "io/File.cpp", + "io/FileSystem.cpp", + "io/Io.cpp", + "io/ZipArchive.cpp", + "link/AutoVersioner.cpp", + "link/ManifestFixer.cpp", + "link/ProductFilter.cpp", + "link/PrivateAttributeMover.cpp", + "link/ReferenceLinker.cpp", + "link/ResourceDeduper.cpp", + "link/TableMerger.cpp", + "link/VersionCollapser.cpp", + "link/XmlNamespaceRemover.cpp", + "link/XmlReferenceLinker.cpp", + "process/SymbolTable.cpp", + "proto/ProtoHelpers.cpp", + "proto/TableProtoDeserializer.cpp", + "proto/TableProtoSerializer.cpp", + "split/TableSplitter.cpp", + "unflatten/BinaryResourceParser.cpp", + "unflatten/ResChunkPullParser.cpp", + "util/BigBuffer.cpp", + "util/Files.cpp", + "util/Util.cpp", + "ConfigDescription.cpp", + "Debug.cpp", + "DominatorTree.cpp", + "Flags.cpp", + "java/AnnotationProcessor.cpp", + "java/ClassDefinition.cpp", + "java/JavaClassGenerator.cpp", + "java/ManifestClassGenerator.cpp", + "java/ProguardRules.cpp", + "Locale.cpp", + "Resource.cpp", + "ResourceParser.cpp", + "ResourceTable.cpp", + "ResourceUtils.cpp", + "ResourceValues.cpp", + "SdkConstants.cpp", + "StringPool.cpp", + "xml/XmlActionExecutor.cpp", + "xml/XmlDom.cpp", + "xml/XmlPullParser.cpp", + "xml/XmlUtil.cpp", + "Format.proto", + ], + proto: { + export_proto_headers: true, + }, + defaults: ["aapt_defaults"], +} + +// ========================================================== +// Build the host shared library: aapt2_jni +// ========================================================== +cc_library_host_shared { + name: "libaapt2_jni", + srcs: toolSources + ["jni/aapt2_jni.cpp"], + static_libs: ["libaapt2"], + defaults: ["aapt_defaults"], +} + +// ========================================================== +// Build the host tests: aapt2_tests +// ========================================================== +cc_test_host { + name: "aapt2_tests", + srcs: ["**/*_test.cpp"], + static_libs: ["libaapt2"], + defaults: ["aapt_defaults"], +} + +// ========================================================== +// Build the host executable: aapt2 +// ========================================================== +cc_binary_host { + name: "aapt2", + srcs: ["Main.cpp"] + toolSources, + static_libs: ["libaapt2"], + defaults: ["aapt_defaults"], +} diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk deleted file mode 100644 index 1efd2ed6446c..000000000000 --- a/tools/aapt2/Android.mk +++ /dev/null @@ -1,253 +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. -# -LOCAL_PATH:= $(call my-dir) - -# ========================================================== -# Setup some common variables for the different build -# targets here. -# ========================================================== - -main := Main.cpp -sources := \ - compile/IdAssigner.cpp \ - compile/InlineXmlFormatParser.cpp \ - compile/NinePatch.cpp \ - compile/Png.cpp \ - compile/PngChunkFilter.cpp \ - compile/PngCrunch.cpp \ - compile/PseudolocaleGenerator.cpp \ - compile/Pseudolocalizer.cpp \ - compile/XmlIdCollector.cpp \ - filter/ConfigFilter.cpp \ - flatten/Archive.cpp \ - flatten/TableFlattener.cpp \ - flatten/XmlFlattener.cpp \ - io/File.cpp \ - io/FileSystem.cpp \ - io/Io.cpp \ - io/ZipArchive.cpp \ - link/AutoVersioner.cpp \ - link/ManifestFixer.cpp \ - link/ProductFilter.cpp \ - link/PrivateAttributeMover.cpp \ - link/ReferenceLinker.cpp \ - link/ResourceDeduper.cpp \ - link/TableMerger.cpp \ - link/VersionCollapser.cpp \ - link/XmlNamespaceRemover.cpp \ - link/XmlReferenceLinker.cpp \ - process/SymbolTable.cpp \ - proto/ProtoHelpers.cpp \ - proto/TableProtoDeserializer.cpp \ - proto/TableProtoSerializer.cpp \ - split/TableSplitter.cpp \ - unflatten/BinaryResourceParser.cpp \ - unflatten/ResChunkPullParser.cpp \ - util/BigBuffer.cpp \ - util/Files.cpp \ - util/Util.cpp \ - ConfigDescription.cpp \ - Debug.cpp \ - DominatorTree.cpp \ - Flags.cpp \ - java/AnnotationProcessor.cpp \ - java/ClassDefinition.cpp \ - java/JavaClassGenerator.cpp \ - java/ManifestClassGenerator.cpp \ - java/ProguardRules.cpp \ - Locale.cpp \ - Resource.cpp \ - ResourceParser.cpp \ - ResourceTable.cpp \ - ResourceUtils.cpp \ - ResourceValues.cpp \ - SdkConstants.cpp \ - StringPool.cpp \ - xml/XmlActionExecutor.cpp \ - xml/XmlDom.cpp \ - xml/XmlPullParser.cpp \ - xml/XmlUtil.cpp - -sources += Format.proto - -sourcesJni := jni/aapt2_jni.cpp - -testSources := \ - compile/IdAssigner_test.cpp \ - compile/InlineXmlFormatParser_test.cpp \ - compile/NinePatch_test.cpp \ - compile/PseudolocaleGenerator_test.cpp \ - compile/Pseudolocalizer_test.cpp \ - compile/XmlIdCollector_test.cpp \ - filter/ConfigFilter_test.cpp \ - flatten/TableFlattener_test.cpp \ - flatten/XmlFlattener_test.cpp \ - link/AutoVersioner_test.cpp \ - link/ManifestFixer_test.cpp \ - link/PrivateAttributeMover_test.cpp \ - link/ProductFilter_test.cpp \ - link/ReferenceLinker_test.cpp \ - link/ResourceDeduper_test.cpp \ - link/TableMerger_test.cpp \ - link/VersionCollapser_test.cpp \ - link/XmlNamespaceRemover_test.cpp \ - link/XmlReferenceLinker_test.cpp \ - process/SymbolTable_test.cpp \ - proto/TableProtoSerializer_test.cpp \ - split/TableSplitter_test.cpp \ - util/BigBuffer_test.cpp \ - util/Files_test.cpp \ - util/Maybe_test.cpp \ - util/StringPiece_test.cpp \ - util/Util_test.cpp \ - ConfigDescription_test.cpp \ - DominatorTree_test.cpp \ - java/AnnotationProcessor_test.cpp \ - java/JavaClassGenerator_test.cpp \ - java/ManifestClassGenerator_test.cpp \ - Locale_test.cpp \ - NameMangler_test.cpp \ - Resource_test.cpp \ - ResourceParser_test.cpp \ - ResourceTable_test.cpp \ - ResourceUtils_test.cpp \ - SdkConstants_test.cpp \ - StringPool_test.cpp \ - ValueVisitor_test.cpp \ - xml/XmlActionExecutor_test.cpp \ - xml/XmlDom_test.cpp \ - xml/XmlPullParser_test.cpp \ - xml/XmlUtil_test.cpp - -toolSources := \ - compile/Compile.cpp \ - diff/Diff.cpp \ - dump/Dump.cpp \ - link/Link.cpp - -hostLdLibs := - -hostStaticLibs := \ - libandroidfw \ - libutils \ - liblog \ - libcutils \ - libexpat \ - libziparchive \ - libpng \ - libbase \ - libprotobuf-cpp-lite - - -# Statically link libz for MinGW (Win SDK under Linux), -# and dynamically link for all others. -hostStaticLibs_windows := libz -hostLdLibs_linux := -lz -hostLdLibs_darwin := -lz - -cFlags := -Wall -Werror -Wno-unused-parameter -cFlags_darwin := -D_DARWIN_UNLIMITED_STREAMS -cFlags_windows := -Wno-maybe-uninitialized # Incorrectly marking use of Maybe.value() as error. -cppFlags := -Wno-missing-field-initializers -fno-exceptions -fno-rtti -protoIncludes := $(call generated-sources-dir-for,STATIC_LIBRARIES,libaapt2,HOST) - -# ========================================================== -# NOTE: Do not add any shared libraries. -# AAPT2 is built to run on many environments -# that may not have the required dependencies. -# ========================================================== - -# ========================================================== -# Build the host static library: libaapt2 -# ========================================================== -include $(CLEAR_VARS) -LOCAL_MODULE := libaapt2 -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -LOCAL_MODULE_HOST_OS := darwin linux windows -LOCAL_CFLAGS := $(cFlags) -LOCAL_CFLAGS_darwin := $(cFlags_darwin) -LOCAL_CFLAGS_windows := $(cFlags_windows) -LOCAL_CPPFLAGS := $(cppFlags) -LOCAL_C_INCLUDES := $(protoIncludes) -LOCAL_SRC_FILES := $(sources) -LOCAL_STATIC_LIBRARIES := $(hostStaticLibs) -LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows) -include $(BUILD_HOST_STATIC_LIBRARY) - - -# ========================================================== -# Build the host shared library: libaapt2_jni -# ========================================================== -include $(CLEAR_VARS) -LOCAL_MODULE := libaapt2_jni -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_MODULE_HOST_OS := darwin linux windows -LOCAL_CFLAGS := $(cFlags) -LOCAL_CFLAGS_darwin := $(cFlags_darwin) -LOCAL_CFLAGS_windows := $(cFlags_windows) -LOCAL_CPPFLAGS := $(cppFlags) -LOCAL_C_INCLUDES := $(protoIncludes) -LOCAL_SRC_FILES := $(toolSources) $(sourcesJni) -LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs) -LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows) -LOCAL_LDLIBS := $(hostLdLibs) -LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin) -LOCAL_LDLIBS_linux := $(hostLdLibs_linux) -include $(BUILD_HOST_SHARED_LIBRARY) - - -# ========================================================== -# Build the host tests: libaapt2_tests -# ========================================================== -include $(CLEAR_VARS) -LOCAL_MODULE := libaapt2_tests -LOCAL_MODULE_TAGS := tests -LOCAL_MODULE_HOST_OS := darwin linux windows -LOCAL_CFLAGS := $(cFlags) -LOCAL_CFLAGS_darwin := $(cFlags_darwin) -LOCAL_CFLAGS_windows := $(cFlags_windows) -LOCAL_CPPFLAGS := $(cppFlags) -LOCAL_C_INCLUDES := $(protoIncludes) -LOCAL_SRC_FILES := $(testSources) -LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs) -LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows) -LOCAL_LDLIBS := $(hostLdLibs) -LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin) -LOCAL_LDLIBS_linux := $(hostLdLibs_linux) -include $(BUILD_HOST_NATIVE_TEST) - -# ========================================================== -# Build the host executable: aapt2 -# ========================================================== -include $(CLEAR_VARS) -LOCAL_MODULE := aapt2 -LOCAL_MODULE_HOST_OS := darwin linux windows -LOCAL_CFLAGS := $(cFlags) -LOCAL_CFLAGS_darwin := $(cFlags_darwin) -LOCAL_CFLAGS_windows := $(cFlags_windows) -LOCAL_CPPFLAGS := $(cppFlags) -LOCAL_C_INCLUDES := $(protoIncludes) -LOCAL_SRC_FILES := $(main) $(toolSources) -LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs) -LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows) -LOCAL_LDLIBS := $(hostLdLibs) -LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin) -LOCAL_LDLIBS_linux := $(hostLdLibs_linux) -include $(BUILD_HOST_EXECUTABLE) - -ifeq ($(ONE_SHOT_MAKEFILE),) -include $(call all-makefiles-under,$(LOCAL_PATH)) -endif diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp index b1bd4012c1df..5bea3ad1bbad 100644 --- a/tools/aapt2/ConfigDescription.cpp +++ b/tools/aapt2/ConfigDescription.cpp @@ -20,15 +20,16 @@ #include <vector> #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" #include "Locale.h" #include "SdkConstants.h" -#include "util/StringPiece.h" #include "util/Util.h" -namespace aapt { - using android::ResTable_config; +using android::StringPiece; + +namespace aapt { static const char* kWildcardName = "any"; @@ -205,6 +206,52 @@ static bool parseScreenRound(const char* name, ResTable_config* out) { return false; } +static bool parseWideColorGamut(const char* name, ResTable_config* out) { + if (strcmp(name, kWildcardName) == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | + ResTable_config::WIDE_COLOR_GAMUT_ANY; + return true; + } else if (strcmp(name, "widecg") == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) | + ResTable_config::WIDE_COLOR_GAMUT_YES; + return true; + } else if (strcmp(name, "nowidecg") == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~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->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_HDR) | + ResTable_config::HDR_ANY; + return true; + } else if (strcmp(name, "highdr") == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~ResTable_config::MASK_HDR) | + ResTable_config::HDR_YES; + return true; + } else if (strcmp(name, "lowdr") == 0) { + if (out) + out->colorimetry = + (out->colorimetry & ~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; @@ -686,6 +733,20 @@ bool ConfigDescription::Parse(const StringPiece& str, ConfigDescription* out) { } } + 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) { @@ -778,7 +839,9 @@ 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) { + == ResTable_config::UI_MODE_TYPE_VR_HEADSET || + config->colorimetry & ResTable_config::MASK_WIDE_COLOR_GAMUT || + config->colorimetry & ResTable_config::MASK_HDR) { min_sdk = SDK_O; } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) { min_sdk = SDK_MARSHMALLOW; @@ -849,6 +912,12 @@ bool ConfigDescription::HasHigherPrecedenceThan( if ((screenLayout2 | o.screenLayout2) & MASK_SCREENROUND) { return !(o.screenLayout2 & MASK_SCREENROUND); } + if ((colorimetry | o.colorimetry) & MASK_HDR) { + return !(o.colorimetry & MASK_HDR); + } + if ((colorimetry | o.colorimetry) & MASK_WIDE_COLOR_GAMUT) { + return !(o.colorimetry & 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); @@ -895,6 +964,9 @@ bool ConfigDescription::ConflictsWith(const ConfigDescription& o) const { !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) || !pred(screenLayout2 & MASK_SCREENROUND, o.screenLayout2 & MASK_SCREENROUND) || + !pred(colorimetry & MASK_HDR, o.colorimetry & MASK_HDR) || + !pred(colorimetry & MASK_WIDE_COLOR_GAMUT, + o.colorimetry & MASK_WIDE_COLOR_GAMUT) || !pred(orientation, o.orientation) || !pred(touchscreen, o.touchscreen) || !pred(inputFlags & MASK_KEYSHIDDEN, o.inputFlags & MASK_KEYSHIDDEN) || diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h index 97d0f38a5af1..65c96175091c 100644 --- a/tools/aapt2/ConfigDescription.h +++ b/tools/aapt2/ConfigDescription.h @@ -20,8 +20,7 @@ #include <ostream> #include "androidfw/ResourceTypes.h" - -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" namespace aapt { @@ -42,7 +41,7 @@ struct ConfigDescription : public android::ResTable_config { * The resulting configuration has the appropriate sdkVersion defined * for backwards compatibility. */ - static bool Parse(const StringPiece& str, ConfigDescription* out = nullptr); + static bool Parse(const android::StringPiece& str, ConfigDescription* out = nullptr); /** * If the configuration uses an axis that was added after diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp index 1d22ce03ef1c..b88838ae26f5 100644 --- a/tools/aapt2/ConfigDescription_test.cpp +++ b/tools/aapt2/ConfigDescription_test.cpp @@ -18,9 +18,12 @@ #include <string> +#include "androidfw/StringPiece.h" + #include "SdkConstants.h" #include "test/Test.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { @@ -99,6 +102,36 @@ TEST(ConfigDescriptionTest, TestParsingRoundQualifier) { 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.colorimetry & 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.colorimetry & 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.colorimetry & 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.colorimetry & 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)); diff --git a/tools/aapt2/Diagnostics.h b/tools/aapt2/Diagnostics.h index 5bc86a9fdbaf..50e8b33ab9b1 100644 --- a/tools/aapt2/Diagnostics.h +++ b/tools/aapt2/Diagnostics.h @@ -22,9 +22,9 @@ #include <string> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "Source.h" -#include "util/StringPiece.h" #include "util/Util.h" namespace aapt { @@ -38,7 +38,7 @@ struct DiagMessage { public: DiagMessage() = default; - explicit DiagMessage(const StringPiece& src) : source_(src) {} + explicit DiagMessage(const android::StringPiece& src) : source_(src) {} explicit DiagMessage(const Source& src) : source_(src) {} @@ -59,6 +59,12 @@ struct DiagMessage { std::stringstream message_; }; +template <> +inline DiagMessage& DiagMessage::operator<<(const ::std::u16string& value) { + message_ << android::StringPiece16(value); + return *this; +} + struct IDiagnostics { virtual ~IDiagnostics() = default; diff --git a/tools/aapt2/Flags.cpp b/tools/aapt2/Flags.cpp index c98cd374602f..84977ab424cc 100644 --- a/tools/aapt2/Flags.cpp +++ b/tools/aapt2/Flags.cpp @@ -21,20 +21,22 @@ #include <string> #include <vector> -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" + #include "util/Util.h" +using android::StringPiece; + namespace aapt { Flags& Flags::RequiredFlag(const StringPiece& name, const StringPiece& description, std::string* value) { auto func = [value](const StringPiece& arg) -> bool { - *value = arg.ToString(); + *value = arg.to_string(); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, true, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false}); return *this; } @@ -42,12 +44,11 @@ Flags& Flags::RequiredFlagList(const StringPiece& name, const StringPiece& description, std::vector<std::string>* value) { auto func = [value](const StringPiece& arg) -> bool { - value->push_back(arg.ToString()); + value->push_back(arg.to_string()); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, true, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false}); return *this; } @@ -55,12 +56,11 @@ Flags& Flags::OptionalFlag(const StringPiece& name, const StringPiece& description, Maybe<std::string>* value) { auto func = [value](const StringPiece& arg) -> bool { - *value = arg.ToString(); + *value = arg.to_string(); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, false, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false}); return *this; } @@ -68,12 +68,11 @@ Flags& Flags::OptionalFlagList(const StringPiece& name, const StringPiece& description, std::vector<std::string>* value) { auto func = [value](const StringPiece& arg) -> bool { - value->push_back(arg.ToString()); + value->push_back(arg.to_string()); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, false, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false}); return *this; } @@ -81,12 +80,11 @@ Flags& Flags::OptionalFlagList(const StringPiece& name, const StringPiece& description, std::unordered_set<std::string>* value) { auto func = [value](const StringPiece& arg) -> bool { - value->insert(arg.ToString()); + value->insert(arg.to_string()); return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, false, 1, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false}); return *this; } @@ -97,8 +95,7 @@ Flags& Flags::OptionalSwitch(const StringPiece& name, return true; }; - flags_.push_back( - Flag{name.ToString(), description.ToString(), func, false, 0, false}); + flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 0, false}); return *this; } @@ -141,7 +138,7 @@ bool Flags::Parse(const StringPiece& command, for (size_t i = 0; i < args.size(); i++) { StringPiece arg = args[i]; if (*(arg.data()) != '-') { - args_.push_back(arg.ToString()); + args_.push_back(arg.to_string()); continue; } diff --git a/tools/aapt2/Flags.h b/tools/aapt2/Flags.h index 9feff6b4faca..3b3ae710dc7b 100644 --- a/tools/aapt2/Flags.h +++ b/tools/aapt2/Flags.h @@ -23,32 +23,30 @@ #include <unordered_set> #include <vector> +#include "androidfw/StringPiece.h" + #include "util/Maybe.h" -#include "util/StringPiece.h" namespace aapt { class Flags { public: - Flags& RequiredFlag(const StringPiece& name, const StringPiece& description, + Flags& RequiredFlag(const android::StringPiece& name, const android::StringPiece& description, std::string* value); - Flags& RequiredFlagList(const StringPiece& name, - const StringPiece& description, + Flags& RequiredFlagList(const android::StringPiece& name, const android::StringPiece& description, std::vector<std::string>* value); - Flags& OptionalFlag(const StringPiece& name, const StringPiece& description, + Flags& OptionalFlag(const android::StringPiece& name, const android::StringPiece& description, Maybe<std::string>* value); - Flags& OptionalFlagList(const StringPiece& name, - const StringPiece& description, + Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description, std::vector<std::string>* value); - Flags& OptionalFlagList(const StringPiece& name, - const StringPiece& description, + Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description, std::unordered_set<std::string>* value); - Flags& OptionalSwitch(const StringPiece& name, const StringPiece& description, + Flags& OptionalSwitch(const android::StringPiece& name, const android::StringPiece& description, bool* value); - void Usage(const StringPiece& command, std::ostream* out); + void Usage(const android::StringPiece& command, std::ostream* out); - bool Parse(const StringPiece& command, const std::vector<StringPiece>& args, + bool Parse(const android::StringPiece& command, const std::vector<android::StringPiece>& args, std::ostream* outError); const std::vector<std::string>& GetArgs(); @@ -57,7 +55,7 @@ class Flags { struct Flag { std::string name; std::string description; - std::function<bool(const StringPiece& value)> action; + std::function<bool(const android::StringPiece& value)> action; bool required; size_t num_args; diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp index 78f56c7a5b93..7664fac44be1 100644 --- a/tools/aapt2/Locale.cpp +++ b/tools/aapt2/Locale.cpp @@ -72,7 +72,7 @@ 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) { +bool LocaleValue::InitFromFilterString(const android::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<std::string> parts = util::SplitAndLowercase(str, '_'); diff --git a/tools/aapt2/Locale.h b/tools/aapt2/Locale.h index fc6c448ac1dc..3d73b2eb17bf 100644 --- a/tools/aapt2/Locale.h +++ b/tools/aapt2/Locale.h @@ -21,8 +21,7 @@ #include <vector> #include "androidfw/ResourceTypes.h" - -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" namespace aapt { @@ -40,7 +39,7 @@ struct LocaleValue { /** * Initialize this LocaleValue from a config string. */ - bool InitFromFilterString(const StringPiece& config); + bool InitFromFilterString(const android::StringPiece& config); /** * Initialize this LocaleValue from parts of a vector. diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp index a2b216d01b11..74d40194e955 100644 --- a/tools/aapt2/Main.cpp +++ b/tools/aapt2/Main.cpp @@ -17,7 +17,7 @@ #include <iostream> #include <vector> -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" namespace aapt { @@ -33,10 +33,10 @@ int PrintVersion() { return 0; } -extern int Compile(const std::vector<StringPiece>& args); -extern int Link(const std::vector<StringPiece>& args); -extern int Dump(const std::vector<StringPiece>& args); -extern int Diff(const std::vector<StringPiece>& args); +extern int Compile(const std::vector<android::StringPiece>& args); +extern int Link(const std::vector<android::StringPiece>& args); +extern int Dump(const std::vector<android::StringPiece>& args); +extern int Diff(const std::vector<android::StringPiece>& args); } // namespace aapt @@ -45,12 +45,12 @@ int main(int argc, char** argv) { argv += 1; argc -= 1; - std::vector<aapt::StringPiece> args; + std::vector<android::StringPiece> args; for (int i = 1; i < argc; i++) { args.push_back(argv[i]); } - aapt::StringPiece command(argv[0]); + android::StringPiece command(argv[0]); if (command == "compile" || command == "c") { return aapt::Compile(args); } else if (command == "link" || command == "l") { diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp index 3eef7aa71a92..fdabce17433c 100644 --- a/tools/aapt2/Resource.cpp +++ b/tools/aapt2/Resource.cpp @@ -19,6 +19,8 @@ #include <map> #include <string> +using android::StringPiece; + namespace aapt { StringPiece ToString(ResourceType type) { diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h index 13330b548d2c..1950ea35a652 100644 --- a/tools/aapt2/Resource.h +++ b/tools/aapt2/Resource.h @@ -24,11 +24,11 @@ #include <tuple> #include <vector> +#include "androidfw/StringPiece.h" #include "utils/JenkinsHash.h" #include "ConfigDescription.h" #include "Source.h" -#include "util/StringPiece.h" namespace aapt { @@ -63,13 +63,13 @@ enum class ResourceType { kXml, }; -StringPiece ToString(ResourceType type); +android::StringPiece ToString(ResourceType type); /** * Returns a pointer to a valid ResourceType, or nullptr if * the string was invalid. */ -const ResourceType* ParseResourceType(const StringPiece& str); +const ResourceType* ParseResourceType(const android::StringPiece& str); /** * A resource's name. This can uniquely identify @@ -81,7 +81,7 @@ struct ResourceName { std::string entry; ResourceName() = default; - ResourceName(const StringPiece& p, ResourceType t, const StringPiece& e); + ResourceName(const android::StringPiece& p, ResourceType t, const android::StringPiece& e); int compare(const ResourceName& other) const; @@ -96,15 +96,15 @@ struct ResourceName { * of the original string. */ struct ResourceNameRef { - StringPiece package; + android::StringPiece package; ResourceType type = ResourceType::kRaw; - StringPiece entry; + android::StringPiece entry; ResourceNameRef() = default; ResourceNameRef(const ResourceNameRef&) = default; ResourceNameRef(ResourceNameRef&&) = default; ResourceNameRef(const ResourceName& rhs); // NOLINT(implicit) - ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e); + ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e); ResourceNameRef& operator=(const ResourceNameRef& rhs) = default; ResourceNameRef& operator=(ResourceNameRef&& rhs) = default; ResourceNameRef& operator=(const ResourceName& rhs); @@ -258,9 +258,9 @@ inline ::std::ostream& operator<<(::std::ostream& out, // ResourceName implementation. // -inline ResourceName::ResourceName(const StringPiece& p, ResourceType t, - const StringPiece& e) - : package(p.ToString()), type(t), entry(e.ToString()) {} +inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t, + const android::StringPiece& e) + : package(p.to_string()), type(t), entry(e.to_string()) {} inline int ResourceName::compare(const ResourceName& other) const { int cmp = package.compare(other.package); @@ -311,8 +311,8 @@ inline std::string ResourceName::ToString() const { inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs) : package(rhs.package), type(rhs.type), entry(rhs.entry) {} -inline ResourceNameRef::ResourceNameRef(const StringPiece& p, ResourceType t, - const StringPiece& e) +inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t, + const android::StringPiece& e) : package(p), type(t), entry(e) {} inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) { diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index b16def4025ff..79379fe4b5ee 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -29,6 +29,8 @@ #include "util/Util.h" #include "xml/XmlPullParser.h" +using android::StringPiece; + namespace aapt { constexpr const char* sXliffNamespaceUri = @@ -101,7 +103,7 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, StringPiece trimmed_comment = util::TrimWhitespace(res->comment); if (trimmed_comment.size() != res->comment.size()) { // Only if there was a change do we re-assign. - res->comment = trimmed_comment.ToString(); + res->comment = trimmed_comment.to_string(); } if (res->symbol_state) { @@ -297,7 +299,7 @@ bool ResourceParser::ParseResources(xml::XmlPullParser* parser) { // Extract the product name if it exists. if (Maybe<StringPiece> maybe_product = xml::FindNonEmptyAttribute(parser, "product")) { - parsed_resource.product = maybe_product.value().ToString(); + parsed_resource.product = maybe_product.value().to_string(); } // Parse the resource regardless of product. @@ -383,7 +385,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, // Items have their type encoded in the type attribute. if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) { - resource_type = maybe_type.value().ToString(); + resource_type = maybe_type.value().to_string(); } else { diag_->Error(DiagMessage(source_.WithLine(parser->line_number())) << "<item> must have a 'type' attribute"); @@ -419,7 +421,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, } out_resource->name.type = ResourceType::kId; - out_resource->name.entry = maybe_name.value().ToString(); + out_resource->name.entry = maybe_name.value().to_string(); out_resource->value = util::make_unique<Id>(); return true; } @@ -436,7 +438,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, } out_resource->name.type = item_iter->second.type; - out_resource->name.entry = maybe_name.value().ToString(); + out_resource->name.entry = maybe_name.value().to_string(); // Only use the implicit format for this type if it wasn't overridden. if (!resource_format) { @@ -461,7 +463,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, return false; } - out_resource->name.entry = maybe_name.value().ToString(); + out_resource->name.entry = maybe_name.value().to_string(); } // Call the associated parse method. The type will be filled in by the @@ -484,7 +486,7 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, } out_resource->name.type = *parsed_type; - out_resource->name.entry = maybe_name.value().ToString(); + out_resource->name.entry = maybe_name.value().to_string(); out_resource->value = ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString); if (!out_resource->value) { @@ -718,7 +720,7 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, const size_t depth = parser->depth(); while (xml::XmlPullParser::NextChildNode(parser, depth)) { if (parser->event() == xml::XmlPullParser::Event::kComment) { - comment = util::TrimWhitespace(parser->comment()).ToString(); + comment = util::TrimWhitespace(parser->comment()).to_string(); continue; } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) { // Skip text. @@ -754,7 +756,7 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource child_resource; child_resource.name.type = *parsed_type; - child_resource.name.entry = maybe_name.value().ToString(); + child_resource.name.entry = maybe_name.value().to_string(); child_resource.id = next_id; child_resource.comment = std::move(comment); child_resource.source = item_source; @@ -899,7 +901,7 @@ bool ResourceParser::ParseAttrImpl(xml::XmlPullParser* parser, const size_t depth = parser->depth(); while (xml::XmlPullParser::NextChildNode(parser, depth)) { if (parser->event() == xml::XmlPullParser::Event::kComment) { - comment = util::TrimWhitespace(parser->comment()).ToString(); + comment = util::TrimWhitespace(parser->comment()).to_string(); continue; } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) { // Skip text. @@ -1288,7 +1290,7 @@ bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser, const size_t depth = parser->depth(); while (xml::XmlPullParser::NextChildNode(parser, depth)) { if (parser->event() == xml::XmlPullParser::Event::kComment) { - comment = util::TrimWhitespace(parser->comment()).ToString(); + comment = util::TrimWhitespace(parser->comment()).to_string(); continue; } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) { // Ignore text. diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h index 11b1e5b787ca..c12dacf1c707 100644 --- a/tools/aapt2/ResourceParser.h +++ b/tools/aapt2/ResourceParser.h @@ -20,6 +20,7 @@ #include <memory> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "ConfigDescription.h" #include "Diagnostics.h" @@ -27,7 +28,6 @@ #include "ResourceValues.h" #include "StringPool.h" #include "util/Maybe.h" -#include "util/StringPiece.h" #include "xml/XmlPullParser.h" namespace aapt { @@ -101,7 +101,7 @@ class ResourceParser { bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, bool weak); Maybe<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser, - const StringPiece& tag); + const android::StringPiece& tag); bool ParseStyle(xml::XmlPullParser* parser, ParsedResource* out_resource); bool ParseStyleItem(xml::XmlPullParser* parser, Style* style); bool ParseDeclareStyleable(xml::XmlPullParser* parser, diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index 2463911445e7..5762fb035a81 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -25,6 +25,8 @@ #include "test/Test.h" #include "xml/XmlPullParser.h" +using android::StringPiece; + namespace aapt { constexpr const char* kXmlPreamble = diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 4e6a50ae149b..dd78750db290 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -28,6 +28,8 @@ #include <string> #include <tuple> +using android::StringPiece; + namespace aapt { static bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs, @@ -87,7 +89,7 @@ ResourceTablePackage* ResourceTable::FindOrCreatePackage( std::unique_ptr<ResourceTablePackage> new_package = util::make_unique<ResourceTablePackage>(); - new_package->name = name.ToString(); + new_package->name = name.to_string(); return packages.emplace(iter, std::move(new_package))->get(); } diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index a0c3217df610..0fe966c5089b 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -25,7 +25,9 @@ #include "StringPool.h" #include "io/File.h" -#include <android-base/macros.h> +#include "android-base/macros.h" +#include "androidfw/StringPiece.h" + #include <functional> #include <map> #include <memory> @@ -68,9 +70,8 @@ class ResourceConfigValue { */ std::unique_ptr<Value> value; - ResourceConfigValue(const ConfigDescription& config, - const StringPiece& product) - : config(config), product(product.ToString()) {} + ResourceConfigValue(const ConfigDescription& config, const android::StringPiece& product) + : config(config), product(product.to_string()) {} private: DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue); @@ -105,13 +106,13 @@ class ResourceEntry { */ std::vector<std::unique_ptr<ResourceConfigValue>> values; - explicit ResourceEntry(const StringPiece& name) : name(name.ToString()) {} + explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {} ResourceConfigValue* FindValue(const ConfigDescription& config); ResourceConfigValue* FindValue(const ConfigDescription& config, - const StringPiece& product); + const android::StringPiece& product); ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config, - const StringPiece& product); + const android::StringPiece& product); std::vector<ResourceConfigValue*> findAllValues( const ConfigDescription& config); std::vector<ResourceConfigValue*> FindValuesIf( @@ -150,8 +151,8 @@ class ResourceTableType { explicit ResourceTableType(const ResourceType type) : type(type) {} - ResourceEntry* FindEntry(const StringPiece& name); - ResourceEntry* FindOrCreateEntry(const StringPiece& name); + ResourceEntry* FindEntry(const android::StringPiece& name); + ResourceEntry* FindOrCreateEntry(const android::StringPiece& name); private: DISALLOW_COPY_AND_ASSIGN(ResourceTableType); @@ -195,22 +196,19 @@ class ResourceTable { Value* incoming); bool AddResource(const ResourceNameRef& name, const ConfigDescription& config, - const StringPiece& product, std::unique_ptr<Value> value, + const android::StringPiece& product, std::unique_ptr<Value> value, IDiagnostics* diag); bool AddResource(const ResourceNameRef& name, const ResourceId& res_id, - const ConfigDescription& config, const StringPiece& product, + const ConfigDescription& config, const android::StringPiece& product, std::unique_ptr<Value> value, IDiagnostics* diag); - bool AddFileReference(const ResourceNameRef& name, - const ConfigDescription& config, const Source& source, - const StringPiece& path, IDiagnostics* diag); + bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config, + const Source& source, const android::StringPiece& path, IDiagnostics* diag); - bool AddFileReferenceAllowMangled(const ResourceNameRef& name, - const ConfigDescription& config, - const Source& source, - const StringPiece& path, io::IFile* file, - IDiagnostics* diag); + bool AddFileReferenceAllowMangled(const ResourceNameRef& name, const 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 @@ -219,18 +217,13 @@ class ResourceTable { * mangled * names. */ - bool AddResourceAllowMangled(const ResourceNameRef& name, - const ConfigDescription& config, - const StringPiece& product, - std::unique_ptr<Value> value, + bool AddResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config, + const android::StringPiece& product, std::unique_ptr<Value> value, IDiagnostics* diag); - bool AddResourceAllowMangled(const ResourceNameRef& name, - const ResourceId& id, - const ConfigDescription& config, - const StringPiece& product, - std::unique_ptr<Value> value, - IDiagnostics* diag); + bool AddResourceAllowMangled(const ResourceNameRef& name, const ResourceId& id, + const ConfigDescription& config, const android::StringPiece& product, + std::unique_ptr<Value> value, IDiagnostics* diag); bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id, const Symbol& symbol, IDiagnostics* diag); @@ -273,28 +266,23 @@ class ResourceTable { * represent the * 'current' package before it is known to the ResourceTable. */ - ResourceTablePackage* FindPackage(const StringPiece& name); + ResourceTablePackage* FindPackage(const android::StringPiece& name); ResourceTablePackage* FindPackageById(uint8_t id); - ResourceTablePackage* CreatePackage(const StringPiece& name, - Maybe<uint8_t> id = {}); + ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {}); private: - ResourceTablePackage* FindOrCreatePackage(const StringPiece& name); + ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name); bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id, - const ConfigDescription& config, - const StringPiece& product, std::unique_ptr<Value> value, - const char* valid_chars, - const CollisionResolverFunc& conflict_resolver, - IDiagnostics* diag); - - bool AddFileReferenceImpl(const ResourceNameRef& name, - const ConfigDescription& config, - const Source& source, const StringPiece& path, - io::IFile* file, const char* valid_chars, - IDiagnostics* diag); + const ConfigDescription& config, const android::StringPiece& product, + std::unique_ptr<Value> value, const char* valid_chars, + const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag); + + bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config, + const Source& source, const android::StringPiece& path, io::IFile* file, + const char* valid_chars, IDiagnostics* diag); bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id, const Symbol& symbol, const char* valid_chars, diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index fce9b338d726..11239673272e 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -26,6 +26,9 @@ #include "util/Files.h" #include "util/Util.h" +using android::StringPiece; +using android::StringPiece16; + namespace aapt { namespace ResourceUtils { @@ -59,7 +62,7 @@ Maybe<ResourceName> ToResourceName( name_out.entry = util::Utf16ToUtf8(StringPiece16(name_in.name, name_in.nameLen)); } else if (name_in.name8) { - name_out.entry = StringPiece(name_in.name8, name_in.nameLen).ToString(); + name_out.entry.assign(name_in.name8, name_in.nameLen); } else { return {}; } @@ -303,9 +306,7 @@ Maybe<Reference> ParseXmlAttributeName(const StringPiece& str) { p++; } - ref.name = - ResourceName(package.ToString(), ResourceType::kAttr, - name.empty() ? trimmed_str.ToString() : name.ToString()); + ref.name = ResourceName(package, ResourceType::kAttr, name.empty() ? trimmed_str : name); return Maybe<Reference>(std::move(ref)); } diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h index 9766f6a7b2fa..bd3a8e3e0bc8 100644 --- a/tools/aapt2/ResourceUtils.h +++ b/tools/aapt2/ResourceUtils.h @@ -20,10 +20,11 @@ #include <functional> #include <memory> +#include "androidfw/StringPiece.h" + #include "NameMangler.h" #include "Resource.h" #include "ResourceValues.h" -#include "util/StringPiece.h" namespace aapt { namespace ResourceUtils { @@ -37,8 +38,8 @@ namespace ResourceUtils { * individual extracted piece to verify that the pieces are valid. * Returns false if there was no package but a ':' was present. */ -bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, - StringPiece* out_type, StringPiece* out_entry); +bool ExtractResourceName(const android::StringPiece& str, android::StringPiece* out_package, + android::StringPiece* out_type, android::StringPiece* out_entry); /** * Returns true if the string was parsed as a resource name @@ -46,7 +47,7 @@ bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, * `out_resource` set to the parsed resource name and `out_private` set to true * if a '*' prefix was present. */ -bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_resource, +bool ParseResourceName(const android::StringPiece& str, ResourceNameRef* out_resource, bool* out_private = nullptr); /* @@ -57,28 +58,27 @@ bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_resource, * If '+' was present in the reference, `out_create` is set to true. * If '*' was present in the reference, `out_private` is set to true. */ -bool ParseReference(const StringPiece& str, ResourceNameRef* out_reference, +bool ParseReference(const android::StringPiece& str, ResourceNameRef* out_reference, bool* out_create = nullptr, bool* out_private = nullptr); /* * Returns true if the string is in the form of a resource reference * (@[+][package:]type/name). */ -bool IsReference(const StringPiece& str); +bool IsReference(const android::StringPiece& str); /* * Returns true if the string was parsed as an attribute reference * (?[package:][type/]name), * with `out_reference` set to the parsed reference. */ -bool ParseAttributeReference(const StringPiece& str, - ResourceNameRef* out_reference); +bool ParseAttributeReference(const android::StringPiece& str, ResourceNameRef* out_reference); /** * Returns true if the string is in the form of an attribute * reference(?[package:][type/]name). */ -bool IsAttributeReference(const StringPiece& str); +bool IsAttributeReference(const android::StringPiece& str); /** * Convert an android::ResTable::resource_name to an aapt::ResourceName struct. @@ -90,22 +90,22 @@ Maybe<ResourceName> ToResourceName( * Returns a boolean value if the string is equal to TRUE, true, True, FALSE, * false, or False. */ -Maybe<bool> ParseBool(const StringPiece& str); +Maybe<bool> ParseBool(const android::StringPiece& str); /** * Returns a uint32_t if the string is an integer. */ -Maybe<uint32_t> ParseInt(const StringPiece& str); +Maybe<uint32_t> ParseInt(const android::StringPiece& str); /** * Returns an ID if it the string represented a valid ID. */ -Maybe<ResourceId> ParseResourceId(const StringPiece& str); +Maybe<ResourceId> ParseResourceId(const android::StringPiece& str); /** * Parses an SDK version, which can be an integer, or a letter from A-Z. */ -Maybe<int> ParseSdkVersion(const StringPiece& str); +Maybe<int> ParseSdkVersion(const android::StringPiece& str); /* * Returns a Reference, or None Maybe instance if the string `str` was parsed as @@ -118,8 +118,7 @@ Maybe<int> ParseSdkVersion(const StringPiece& str); * ?[package:]style/<entry> or * <package>:[style/]<entry> */ -Maybe<Reference> ParseStyleParentReference(const StringPiece& str, - std::string* out_error); +Maybe<Reference> ParseStyleParentReference(const android::StringPiece& str, std::string* out_error); /* * Returns a Reference if the string `str` was parsed as a valid XML attribute @@ -128,7 +127,7 @@ Maybe<Reference> ParseStyleParentReference(const StringPiece& str, * * package:entry */ -Maybe<Reference> ParseXmlAttributeName(const StringPiece& str); +Maybe<Reference> ParseXmlAttributeName(const android::StringPiece& str); /* * Returns a Reference object if the string was parsed as a resource or @@ -137,52 +136,52 @@ Maybe<Reference> ParseXmlAttributeName(const StringPiece& str); * if * the '+' was present in the string. */ -std::unique_ptr<Reference> TryParseReference(const StringPiece& str, +std::unique_ptr<Reference> TryParseReference(const android::StringPiece& str, bool* out_create = nullptr); /* * Returns a BinaryPrimitve object representing @null or @empty if the string * was parsed as one. */ -std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing a color if the string was parsed * as one. */ -std::unique_ptr<BinaryPrimitive> TryParseColor(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseColor(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing a boolean if the string was * parsed as one. */ -std::unique_ptr<BinaryPrimitive> TryParseBool(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseBool(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing an integer if the string was * parsed as one. */ -std::unique_ptr<BinaryPrimitive> TryParseInt(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseInt(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing a floating point number * (float, dimension, etc) if the string was parsed as one. */ -std::unique_ptr<BinaryPrimitive> TryParseFloat(const StringPiece& str); +std::unique_ptr<BinaryPrimitive> TryParseFloat(const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing an enum symbol if the string was * parsed as one. */ std::unique_ptr<BinaryPrimitive> TryParseEnumSymbol(const Attribute* enum_attr, - const StringPiece& str); + const android::StringPiece& str); /* * Returns a BinaryPrimitve object representing a flag symbol if the string was * parsed as one. */ std::unique_ptr<BinaryPrimitive> TryParseFlagSymbol(const Attribute* enum_attr, - const StringPiece& str); + const android::StringPiece& str); /* * Try to convert a string to an Item for the given attribute. The attribute * will @@ -191,11 +190,11 @@ std::unique_ptr<BinaryPrimitive> TryParseFlagSymbol(const Attribute* enum_attr, * reference to an ID that must be created (@+id/foo). */ std::unique_ptr<Item> TryParseItemForAttribute( - const StringPiece& value, const Attribute* attr, + const android::StringPiece& value, const Attribute* attr, const std::function<void(const ResourceName&)>& on_create_reference = {}); std::unique_ptr<Item> TryParseItemForAttribute( - const StringPiece& value, uint32_t type_mask, + const android::StringPiece& value, uint32_t type_mask, const std::function<void(const ResourceName&)>& on_create_reference = {}); uint32_t AndroidTypeToAttributeTypeMask(uint16_t type); diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp index f9c500b42c13..048c69252e47 100644 --- a/tools/aapt2/ResourceUtils_test.cpp +++ b/tools/aapt2/ResourceUtils_test.cpp @@ -48,8 +48,7 @@ TEST(ResourceUtilsTest, ParseResourceName) { EXPECT_EQ(ResourceNameRef("android", ResourceType::kColor, "foo"), actual); EXPECT_TRUE(actual_priv); - EXPECT_FALSE( - ResourceUtils::ParseResourceName(StringPiece(), &actual, &actual_priv)); + EXPECT_FALSE(ResourceUtils::ParseResourceName(android::StringPiece(), &actual, &actual_priv)); } TEST(ResourceUtilsTest, ParseReferenceWithNoPackage) { diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h index ea73615e372a..d380f8d0583d 100644 --- a/tools/aapt2/ResourceValues.h +++ b/tools/aapt2/ResourceValues.h @@ -22,6 +22,7 @@ #include <vector> #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" #include "Diagnostics.h" #include "Resource.h" @@ -73,7 +74,7 @@ struct Value { */ const std::string& GetComment() const { return comment_; } - void SetComment(const StringPiece& str) { comment_ = str.ToString(); } + void SetComment(const android::StringPiece& str) { comment_ = str.to_string(); } void SetComment(std::string&& str) { comment_ = std::move(str); } diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp index c7f920ac6c58..e8067143dc75 100644 --- a/tools/aapt2/SdkConstants.cpp +++ b/tools/aapt2/SdkConstants.cpp @@ -21,6 +21,8 @@ #include <unordered_map> #include <vector> +using android::StringPiece; + namespace aapt { static const char* sDevelopmentSdkCodeName = "O"; diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h index 5352b5398544..98ba94badfed 100644 --- a/tools/aapt2/SdkConstants.h +++ b/tools/aapt2/SdkConstants.h @@ -19,6 +19,8 @@ #include <utility> +#include "androidfw/StringPiece.h" + #include "Resource.h" namespace aapt { @@ -52,7 +54,7 @@ enum { size_t FindAttributeSdkLevel(const ResourceId& id); size_t FindAttributeSdkLevel(const ResourceName& name); -std::pair<StringPiece, int> GetDevelopmentSdkCodeNameAndVersion(); +std::pair<android::StringPiece, int> GetDevelopmentSdkCodeNameAndVersion(); } // namespace aapt diff --git a/tools/aapt2/Source.h b/tools/aapt2/Source.h index 459a8e603b6b..d7f2a668477c 100644 --- a/tools/aapt2/Source.h +++ b/tools/aapt2/Source.h @@ -20,8 +20,9 @@ #include <ostream> #include <string> +#include "androidfw/StringPiece.h" + #include "util/Maybe.h" -#include "util/StringPiece.h" namespace aapt { @@ -35,12 +36,11 @@ struct Source { Source() = default; - inline Source(const StringPiece& path) - : path(path.ToString()) { // NOLINT(implicit) + inline Source(const android::StringPiece& path) : path(path.to_string()) { // NOLINT(implicit) } - inline Source(const StringPiece& path, size_t line) - : path(path.ToString()), line(line) {} + inline Source(const android::StringPiece& path, size_t line) + : path(path.to_string()), line(line) {} inline Source WithLine(size_t line) const { return Source(path, line); } }; diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp index 30328299bb84..d968d73c44ee 100644 --- a/tools/aapt2/StringPool.cpp +++ b/tools/aapt2/StringPool.cpp @@ -22,11 +22,13 @@ #include "android-base/logging.h" #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" #include "util/BigBuffer.h" -#include "util/StringPiece.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { StringPool::Ref::Ref() : entry_(nullptr) {} @@ -140,7 +142,7 @@ StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str, } Entry* entry = new Entry(); - entry->value = str.ToString(); + entry->value = str.to_string(); entry->context = context; entry->index = strings_.size(); entry->ref_ = 0; diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h index a4f556ca52e4..d0ce489dae26 100644 --- a/tools/aapt2/StringPool.h +++ b/tools/aapt2/StringPool.h @@ -23,9 +23,10 @@ #include <unordered_map> #include <vector> +#include "androidfw/StringPiece.h" + #include "ConfigDescription.h" #include "util/BigBuffer.h" -#include "util/StringPiece.h" namespace aapt { @@ -149,14 +150,14 @@ class StringPool { * Adds a string to the pool, unless it already exists. Returns * a reference to the string in the pool. */ - Ref MakeRef(const StringPiece& str); + Ref MakeRef(const android::StringPiece& str); /** * Adds a string to the pool, unless it already exists, with a context * object that can be used when sorting the string pool. Returns * a reference to the string in the pool. */ - Ref MakeRef(const StringPiece& str, const Context& context); + Ref MakeRef(const android::StringPiece& str, const Context& context); /** * Adds a style to the string pool and returns a reference to it. @@ -208,11 +209,11 @@ class StringPool { static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8); - Ref MakeRefImpl(const StringPiece& str, const Context& context, bool unique); + Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique); std::vector<std::unique_ptr<Entry>> strings_; std::vector<std::unique_ptr<StyleEntry>> styles_; - std::unordered_multimap<StringPiece, Entry*> indexed_strings_; + std::unordered_multimap<android::StringPiece, Entry*> indexed_strings_; }; // diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp index e1394fc0221f..f64a8cf20928 100644 --- a/tools/aapt2/StringPool_test.cpp +++ b/tools/aapt2/StringPool_test.cpp @@ -18,9 +18,14 @@ #include <string> +#include "androidfw/StringPiece.h" + #include "test/Test.h" #include "util/Util.h" +using android::StringPiece; +using android::StringPiece16; + namespace aapt { TEST(StringPoolTest, InsertOneString) { @@ -236,8 +241,7 @@ TEST(StringPoolTest, Flatten) { EXPECT_EQ(StringPiece16(u"goodbye"), util::GetString16(test, 1)); EXPECT_EQ(StringPiece(sLongString), util::GetString(test, 2)); - EXPECT_EQ(util::Utf8ToUtf16(sLongString), - util::GetString16(test, 2).ToString()); + EXPECT_EQ(util::Utf8ToUtf16(sLongString), util::GetString16(test, 2).to_string()); size_t len; EXPECT_TRUE(test.stringAt(3, &len) != nullptr || diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp index f0b18e65cc1a..8027f4289169 100644 --- a/tools/aapt2/compile/Compile.cpp +++ b/tools/aapt2/compile/Compile.cpp @@ -19,6 +19,12 @@ #include <fstream> #include <string> +#include "android-base/errors.h" +#include "android-base/file.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 "Flags.h" @@ -38,11 +44,7 @@ #include "xml/XmlDom.h" #include "xml/XmlPullParser.h" -#include "android-base/errors.h" -#include "android-base/file.h" -#include "google/protobuf/io/coded_stream.h" -#include "google/protobuf/io/zero_copy_stream_impl_lite.h" - +using android::StringPiece; using google::protobuf::io::CopyingOutputStreamAdaptor; using google::protobuf::io::ZeroCopyOutputStream; @@ -103,9 +105,8 @@ static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path, name = name.substr(0, dot_pos); } - return ResourcePathData{Source(path), dir_str.ToString(), - name.ToString(), extension.ToString(), - config_str.ToString(), config}; + return ResourcePathData{Source(path), dir_str.to_string(), name.to_string(), + extension.to_string(), config_str.to_string(), config}; } struct CompileOptions { diff --git a/tools/aapt2/compile/IdAssigner.h b/tools/aapt2/compile/IdAssigner.h index 371ec01818cd..9640eb8c50ff 100644 --- a/tools/aapt2/compile/IdAssigner.h +++ b/tools/aapt2/compile/IdAssigner.h @@ -19,11 +19,11 @@ #include <unordered_map> +#include "android-base/macros.h" + #include "Resource.h" #include "process/IResourceTableConsumer.h" -#include "android-base/macros.h" - namespace aapt { /** @@ -40,8 +40,7 @@ class IdAssigner : public IResourceTableConsumer { bool Consume(IAaptContext* context, ResourceTable* table) override; private: - const std::unordered_map<ResourceName, ResourceId>* assigned_id_map_ = - nullptr; + const std::unordered_map<ResourceName, ResourceId>* assigned_id_map_ = nullptr; }; } // namespace aapt diff --git a/tools/aapt2/compile/NinePatch.cpp b/tools/aapt2/compile/NinePatch.cpp index eab5c97c437c..c931da48c889 100644 --- a/tools/aapt2/compile/NinePatch.cpp +++ b/tools/aapt2/compile/NinePatch.cpp @@ -21,10 +21,12 @@ #include <vector> #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" -#include "util/StringPiece.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { // Colors in the format 0xAARRGGBB (the way 9-patch expects it). diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp index 7ab05b58b8b9..5e15c88410ee 100644 --- a/tools/aapt2/compile/Png.cpp +++ b/tools/aapt2/compile/Png.cpp @@ -15,18 +15,21 @@ */ #include "Png.h" -#include "Source.h" -#include "util/BigBuffer.h" -#include "util/Util.h" -#include <androidfw/ResourceTypes.h> #include <png.h> #include <zlib.h> + #include <iostream> #include <sstream> #include <string> #include <vector> +#include "androidfw/ResourceTypes.h" + +#include "Source.h" +#include "util/BigBuffer.h" +#include "util/Util.h" + namespace aapt { constexpr bool kDebug = false; diff --git a/tools/aapt2/compile/Png.h b/tools/aapt2/compile/Png.h index aff1da3f05d2..a82005115850 100644 --- a/tools/aapt2/compile/Png.h +++ b/tools/aapt2/compile/Png.h @@ -56,7 +56,7 @@ class Png { */ class PngChunkFilter : public io::InputStream { public: - explicit PngChunkFilter(const StringPiece& data); + explicit PngChunkFilter(const android::StringPiece& data); bool Next(const void** buffer, int* len) override; void BackUp(int count) override; @@ -71,7 +71,7 @@ class PngChunkFilter : public io::InputStream { private: bool ConsumeWindow(const void** buffer, int* len); - StringPiece data_; + android::StringPiece data_; size_t window_start_ = 0; size_t window_end_ = 0; bool error_ = false; diff --git a/tools/aapt2/compile/PngChunkFilter.cpp b/tools/aapt2/compile/PngChunkFilter.cpp index 4cbefb9496ae..edec12317fdd 100644 --- a/tools/aapt2/compile/PngChunkFilter.cpp +++ b/tools/aapt2/compile/PngChunkFilter.cpp @@ -16,8 +16,11 @@ #include "compile/Png.h" +#include "androidfw/StringPiece.h" + #include "io/Io.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp index 055a725213b7..5035f816f0fa 100644 --- a/tools/aapt2/compile/PseudolocaleGenerator.cpp +++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp @@ -23,6 +23,8 @@ #include "ValueVisitor.h" #include "compile/Pseudolocalizer.h" +using android::StringPiece; + namespace aapt { std::unique_ptr<StyledString> PseudolocalizeStyledString( diff --git a/tools/aapt2/compile/Pseudolocalizer.cpp b/tools/aapt2/compile/Pseudolocalizer.cpp index f89288f73333..15a3d8c289e2 100644 --- a/tools/aapt2/compile/Pseudolocalizer.cpp +++ b/tools/aapt2/compile/Pseudolocalizer.cpp @@ -18,6 +18,8 @@ #include "util/Util.h" +using android::StringPiece; + namespace aapt { // String basis to generate expansion @@ -40,10 +42,8 @@ static const char kArgEnd = '}'; class PseudoMethodNone : public PseudoMethodImpl { public: - std::string Text(const StringPiece& text) override { return text.ToString(); } - std::string Placeholder(const StringPiece& text) override { - return text.ToString(); - } + std::string Text(const StringPiece& text) override { return text.to_string(); } + std::string Placeholder(const StringPiece& text) override { return text.to_string(); } }; class PseudoMethodBidi : public PseudoMethodImpl { @@ -116,7 +116,7 @@ std::string Pseudolocalizer::Text(const StringPiece& text) { } size_t size = nextpos - lastpos; if (size) { - std::string chunk = text.substr(lastpos, size).ToString(); + std::string chunk = text.substr(lastpos, size).to_string(); if (pseudo) { chunk = impl_->Text(chunk); } else if (str[lastpos] == kArgStart && str[nextpos - 1] == kArgEnd) { @@ -437,7 +437,7 @@ std::string PseudoMethodAccent::Text(const StringPiece& source) { std::string PseudoMethodAccent::Placeholder(const StringPiece& source) { // Surround a placeholder with brackets - return kPlaceholderOpen + source.ToString() + kPlaceholderClose; + return kPlaceholderOpen + source.to_string() + kPlaceholderClose; } std::string PseudoMethodBidi::Text(const StringPiece& source) { @@ -467,7 +467,7 @@ std::string PseudoMethodBidi::Text(const StringPiece& source) { std::string PseudoMethodBidi::Placeholder(const StringPiece& source) { // Surround a placeholder with directionality change sequence - return kRlm + kRlo + source.ToString() + kPdf + kRlm; + return kRlm + kRlo + source.to_string() + kPdf + kRlm; } } // namespace aapt diff --git a/tools/aapt2/compile/Pseudolocalizer.h b/tools/aapt2/compile/Pseudolocalizer.h index a6d2ad037d50..6cf003b24157 100644 --- a/tools/aapt2/compile/Pseudolocalizer.h +++ b/tools/aapt2/compile/Pseudolocalizer.h @@ -20,10 +20,10 @@ #include <memory> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "ResourceValues.h" #include "StringPool.h" -#include "util/StringPiece.h" namespace aapt { @@ -32,8 +32,8 @@ class PseudoMethodImpl { virtual ~PseudoMethodImpl() {} virtual std::string Start() { return {}; } virtual std::string End() { return {}; } - virtual std::string Text(const StringPiece& text) = 0; - virtual std::string Placeholder(const StringPiece& text) = 0; + virtual std::string Text(const android::StringPiece& text) = 0; + virtual std::string Placeholder(const android::StringPiece& text) = 0; }; class Pseudolocalizer { @@ -48,7 +48,7 @@ class Pseudolocalizer { void SetMethod(Method method); std::string Start() { return impl_->Start(); } std::string End() { return impl_->End(); } - std::string Text(const StringPiece& text); + std::string Text(const android::StringPiece& text); private: std::unique_ptr<PseudoMethodImpl> impl_; diff --git a/tools/aapt2/compile/Pseudolocalizer_test.cpp b/tools/aapt2/compile/Pseudolocalizer_test.cpp index 92eb3b58515f..d3b7b02d1abb 100644 --- a/tools/aapt2/compile/Pseudolocalizer_test.cpp +++ b/tools/aapt2/compile/Pseudolocalizer_test.cpp @@ -19,6 +19,8 @@ #include "test/Test.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { // In this context, 'Axis' represents a particular field in the configuration, diff --git a/tools/aapt2/diff/Diff.cpp b/tools/aapt2/diff/Diff.cpp index 593e7ab119f1..de0fe404b867 100644 --- a/tools/aapt2/diff/Diff.cpp +++ b/tools/aapt2/diff/Diff.cpp @@ -24,6 +24,8 @@ #include "process/SymbolTable.h" #include "unflatten/BinaryResourceParser.h" +using android::StringPiece; + namespace aapt { class DiffContext : public IAaptContext { diff --git a/tools/aapt2/dump/Dump.cpp b/tools/aapt2/dump/Dump.cpp index 2920c2abb57a..bcede72037b2 100644 --- a/tools/aapt2/dump/Dump.cpp +++ b/tools/aapt2/dump/Dump.cpp @@ -16,6 +16,8 @@ #include <vector> +#include "androidfw/StringPiece.h" + #include "Debug.h" #include "Diagnostics.h" #include "Flags.h" @@ -24,7 +26,8 @@ #include "proto/ProtoSerialize.h" #include "unflatten/BinaryResourceParser.h" #include "util/Files.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { diff --git a/tools/aapt2/flatten/Archive.cpp b/tools/aapt2/flatten/Archive.cpp index 47de0a3b8d6c..5c96a4dbd4e2 100644 --- a/tools/aapt2/flatten/Archive.cpp +++ b/tools/aapt2/flatten/Archive.cpp @@ -22,10 +22,12 @@ #include <vector> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "ziparchive/zip_writer.h" #include "util/Files.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { @@ -36,7 +38,7 @@ class DirectoryWriter : public IArchiveWriter { DirectoryWriter() = default; bool Open(IDiagnostics* diag, const StringPiece& out_dir) { - dir_ = out_dir.ToString(); + dir_ = out_dir.to_string(); file::FileType type = file::GetFileType(dir_); if (type == file::FileType::kNonexistant) { diag->Error(DiagMessage() << "directory " << dir_ << " does not exist"); diff --git a/tools/aapt2/flatten/Archive.h b/tools/aapt2/flatten/Archive.h index 4fcb3ffa2b78..f0681bdd1167 100644 --- a/tools/aapt2/flatten/Archive.h +++ b/tools/aapt2/flatten/Archive.h @@ -22,12 +22,12 @@ #include <string> #include <vector> +#include "androidfw/StringPiece.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "Diagnostics.h" #include "util/BigBuffer.h" #include "util/Files.h" -#include "util/StringPiece.h" namespace aapt { @@ -46,7 +46,7 @@ class IArchiveWriter : public google::protobuf::io::CopyingOutputStream { public: virtual ~IArchiveWriter() = default; - virtual bool StartEntry(const StringPiece& path, uint32_t flags) = 0; + virtual bool StartEntry(const android::StringPiece& path, uint32_t flags) = 0; virtual bool WriteEntry(const BigBuffer& buffer) = 0; virtual bool WriteEntry(const void* data, size_t len) = 0; virtual bool FinishEntry() = 0; @@ -57,11 +57,11 @@ class IArchiveWriter : public google::protobuf::io::CopyingOutputStream { } }; -std::unique_ptr<IArchiveWriter> CreateDirectoryArchiveWriter( - IDiagnostics* diag, const StringPiece& path); +std::unique_ptr<IArchiveWriter> CreateDirectoryArchiveWriter(IDiagnostics* diag, + const android::StringPiece& path); -std::unique_ptr<IArchiveWriter> CreateZipFileArchiveWriter( - IDiagnostics* diag, const StringPiece& path); +std::unique_ptr<IArchiveWriter> CreateZipFileArchiveWriter(IDiagnostics* diag, + const android::StringPiece& path); } // namespace aapt diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp index 2c83bb384cc5..ffc2de141860 100644 --- a/tools/aapt2/flatten/XmlFlattener_test.cpp +++ b/tools/aapt2/flatten/XmlFlattener_test.cpp @@ -23,6 +23,8 @@ #include "util/BigBuffer.h" #include "util/Util.h" +using android::StringPiece16; + namespace aapt { class XmlFlattenerTest : public ::testing::Test { diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h index 644f59f8f3ba..3d5b5b11707e 100644 --- a/tools/aapt2/io/File.h +++ b/tools/aapt2/io/File.h @@ -110,7 +110,7 @@ class IFileCollection { public: virtual ~IFileCollection() = default; - virtual IFile* FindFile(const StringPiece& path) = 0; + virtual IFile* FindFile(const android::StringPiece& path) = 0; virtual std::unique_ptr<IFileCollectionIterator> Iterator() = 0; }; diff --git a/tools/aapt2/io/FileSystem.cpp b/tools/aapt2/io/FileSystem.cpp index 828f34e9c883..027cbd041fa6 100644 --- a/tools/aapt2/io/FileSystem.cpp +++ b/tools/aapt2/io/FileSystem.cpp @@ -16,14 +16,16 @@ #include "io/FileSystem.h" +#include "androidfw/StringPiece.h" #include "utils/FileMap.h" #include "Source.h" #include "util/Files.h" #include "util/Maybe.h" -#include "util/StringPiece.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { namespace io { @@ -54,13 +56,11 @@ IFile* FileCollectionIterator::Next() { } IFile* FileCollection::InsertFile(const StringPiece& path) { - return (files_[path.ToString()] = - util::make_unique<RegularFile>(Source(path))) - .get(); + return (files_[path.to_string()] = util::make_unique<RegularFile>(Source(path))).get(); } IFile* FileCollection::FindFile(const StringPiece& path) { - auto iter = files_.find(path.ToString()); + auto iter = files_.find(path.to_string()); if (iter != files_.end()) { return iter->second.get(); } diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h index 84f851ff694b..dfd37172004b 100644 --- a/tools/aapt2/io/FileSystem.h +++ b/tools/aapt2/io/FileSystem.h @@ -59,8 +59,8 @@ class FileCollection : public IFileCollection { /** * Adds a file located at path. Returns the IFile representation of that file. */ - IFile* InsertFile(const StringPiece& path); - IFile* FindFile(const StringPiece& path) override; + IFile* InsertFile(const android::StringPiece& path); + IFile* FindFile(const android::StringPiece& path) override; std::unique_ptr<IFileCollectionIterator> Iterator() override; private: diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp index f4a128eca9d1..62b436fe4dc7 100644 --- a/tools/aapt2/io/ZipArchive.cpp +++ b/tools/aapt2/io/ZipArchive.cpp @@ -22,6 +22,8 @@ #include "Source.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { namespace io { @@ -107,7 +109,7 @@ std::unique_ptr<ZipFileCollection> ZipFileCollection::Create( std::string zip_entry_path = std::string(reinterpret_cast<const char*>(zip_entry_name.name), zip_entry_name.name_length); - std::string nested_path = path.ToString() + "@" + zip_entry_path; + std::string nested_path = path.to_string() + "@" + zip_entry_path; collection->files_[zip_entry_path] = util::make_unique<ZipFile>( collection->handle_, zip_data, Source(nested_path)); } @@ -120,7 +122,7 @@ std::unique_ptr<ZipFileCollection> ZipFileCollection::Create( } IFile* ZipFileCollection::FindFile(const StringPiece& path) { - auto iter = files_.find(path.ToString()); + auto iter = files_.find(path.to_string()); if (iter != files_.end()) { return iter->second.get(); } diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h index 85ca1aed4edc..634adad8af32 100644 --- a/tools/aapt2/io/ZipArchive.h +++ b/tools/aapt2/io/ZipArchive.h @@ -21,8 +21,9 @@ #include <map> +#include "androidfw/StringPiece.h" + #include "io/File.h" -#include "util/StringPiece.h" namespace aapt { namespace io { @@ -64,10 +65,10 @@ class ZipFileCollectionIterator : public IFileCollectionIterator { */ class ZipFileCollection : public IFileCollection { public: - static std::unique_ptr<ZipFileCollection> Create(const StringPiece& path, + static std::unique_ptr<ZipFileCollection> Create(const android::StringPiece& path, std::string* outError); - io::IFile* FindFile(const StringPiece& path) override; + io::IFile* FindFile(const android::StringPiece& path) override; std::unique_ptr<IFileCollectionIterator> Iterator() override; ~ZipFileCollection() override; diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp index 2951e5cff6d7..a0ef00b1ea1f 100644 --- a/tools/aapt2/java/AnnotationProcessor.cpp +++ b/tools/aapt2/java/AnnotationProcessor.cpp @@ -20,6 +20,8 @@ #include "util/Util.h" +using android::StringPiece; + namespace aapt { void AnnotationProcessor::AppendCommentLine(std::string& comment) { @@ -54,7 +56,7 @@ void AnnotationProcessor::AppendComment(const StringPiece& comment) { for (StringPiece line : util::Tokenize(comment, '\n')) { line = util::TrimWhitespace(line); if (!line.empty()) { - std::string lineCopy = line.ToString(); + std::string lineCopy = line.to_string(); AppendCommentLine(lineCopy); } } diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h index 666a7f356768..99cd44fd2cc1 100644 --- a/tools/aapt2/java/AnnotationProcessor.h +++ b/tools/aapt2/java/AnnotationProcessor.h @@ -20,7 +20,7 @@ #include <sstream> #include <string> -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" namespace aapt { @@ -58,7 +58,7 @@ class AnnotationProcessor { * configurations, * we need to collect all the comments. */ - void AppendComment(const StringPiece& comment); + void AppendComment(const android::StringPiece& comment); void AppendNewLine(); @@ -66,7 +66,7 @@ class AnnotationProcessor { * Writes the comments and annotations to the stream, with the given prefix * before each line. */ - void WriteToStream(std::ostream* out, const StringPiece& prefix) const; + void WriteToStream(std::ostream* out, const android::StringPiece& prefix) const; private: enum : uint32_t { diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp index f1f1f925480c..53d6ea1a79c5 100644 --- a/tools/aapt2/java/ClassDefinition.cpp +++ b/tools/aapt2/java/ClassDefinition.cpp @@ -16,7 +16,9 @@ #include "java/ClassDefinition.h" -#include "util/StringPiece.h" +#include "androidfw/StringPiece.h" + +using android::StringPiece; namespace aapt { @@ -43,7 +45,7 @@ void ClassDefinition::WriteToStream(const StringPiece& prefix, bool final, } *out << "final class " << name_ << " {\n"; - std::string new_prefix = prefix.ToString(); + std::string new_prefix = prefix.to_string(); new_prefix.append(kIndent); for (const std::unique_ptr<ClassMember>& member : members_) { diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h index d8b61d919fd8..64e4b2987be3 100644 --- a/tools/aapt2/java/ClassDefinition.h +++ b/tools/aapt2/java/ClassDefinition.h @@ -21,10 +21,10 @@ #include <string> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "Resource.h" #include "java/AnnotationProcessor.h" -#include "util/StringPiece.h" #include "util/Util.h" namespace aapt { @@ -41,7 +41,7 @@ class ClassMember { virtual bool empty() const = 0; - virtual void WriteToStream(const StringPiece& prefix, bool final, + virtual void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const { processor_.WriteToStream(out, prefix); } @@ -53,12 +53,12 @@ class ClassMember { template <typename T> class PrimitiveMember : public ClassMember { public: - PrimitiveMember(const StringPiece& name, const T& val) - : name_(name.ToString()), val_(val) {} + PrimitiveMember(const android::StringPiece& name, const T& val) + : name_(name.to_string()), val_(val) {} bool empty() const override { return false; } - void WriteToStream(const StringPiece& prefix, bool final, + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { ClassMember::WriteToStream(prefix, final, out); @@ -79,12 +79,12 @@ class PrimitiveMember : public ClassMember { template <> class PrimitiveMember<std::string> : public ClassMember { public: - PrimitiveMember(const StringPiece& name, const std::string& val) - : name_(name.ToString()), val_(val) {} + PrimitiveMember(const android::StringPiece& name, const std::string& val) + : name_(name.to_string()), val_(val) {} bool empty() const override { return false; } - void WriteToStream(const StringPiece& prefix, bool final, + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { ClassMember::WriteToStream(prefix, final, out); @@ -106,14 +106,13 @@ using StringMember = PrimitiveMember<std::string>; template <typename T> class PrimitiveArrayMember : public ClassMember { public: - explicit PrimitiveArrayMember(const StringPiece& name) - : name_(name.ToString()) {} + explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {} void AddElement(const T& val) { elements_.push_back(val); } bool empty() const override { return false; } - void WriteToStream(const StringPiece& prefix, bool final, + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { ClassMember::WriteToStream(prefix, final, out); @@ -147,22 +146,18 @@ enum class ClassQualifier { None, Static }; class ClassDefinition : public ClassMember { public: - static bool WriteJavaFile(const ClassDefinition* def, - const StringPiece& package, bool final, - std::ostream* out); + static bool WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package, + bool final, std::ostream* out); - ClassDefinition(const StringPiece& name, ClassQualifier qualifier, - bool createIfEmpty) - : name_(name.ToString()), - qualifier_(qualifier), - create_if_empty_(createIfEmpty) {} + ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty) + : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {} void AddMember(std::unique_ptr<ClassMember> member) { members_.push_back(std::move(member)); } bool empty() const override; - void WriteToStream(const StringPiece& prefix, bool final, + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override; private: diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 6e7c707847b9..b71dc485633b 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -23,6 +23,7 @@ #include <tuple> #include "android-base/logging.h" +#include "androidfw/StringPiece.h" #include "NameMangler.h" #include "Resource.h" @@ -32,7 +33,8 @@ #include "java/AnnotationProcessor.h" #include "java/ClassDefinition.h" #include "process/SymbolTable.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { @@ -58,7 +60,7 @@ static bool IsValidSymbol(const StringPiece& symbol) { * Replace those with '_'. */ static std::string Transform(const StringPiece& symbol) { - std::string output = symbol.ToString(); + std::string output = symbol.to_string(); for (char& c : output) { if (c == '.' || c == '-') { c = '_'; diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h index 190e73b66b9e..5cf556ea5707 100644 --- a/tools/aapt2/java/JavaClassGenerator.h +++ b/tools/aapt2/java/JavaClassGenerator.h @@ -20,10 +20,11 @@ #include <ostream> #include <string> +#include "androidfw/StringPiece.h" + #include "ResourceTable.h" #include "ResourceValues.h" #include "process/IResourceTableConsumer.h" -#include "util/StringPiece.h" namespace aapt { @@ -69,22 +70,20 @@ class JavaClassGenerator { * We need to generate these symbols in a separate file. * Returns true on success. */ - bool Generate(const StringPiece& packageNameToGenerate, std::ostream* out); + bool Generate(const android::StringPiece& packageNameToGenerate, std::ostream* out); - bool Generate(const StringPiece& packageNameToGenerate, - const StringPiece& outputPackageName, std::ostream* out); + bool Generate(const android::StringPiece& packageNameToGenerate, + const android::StringPiece& outputPackageName, std::ostream* out); const std::string& getError() const; private: - bool AddMembersToTypeClass(const StringPiece& packageNameToGenerate, - const ResourceTablePackage* package, - const ResourceTableType* type, + bool AddMembersToTypeClass(const android::StringPiece& packageNameToGenerate, + const ResourceTablePackage* package, const ResourceTableType* type, ClassDefinition* outTypeClassDef); - void AddMembersToStyleableClass(const StringPiece& packageNameToGenerate, - const std::string& entryName, - const Styleable* styleable, + void AddMembersToStyleableClass(const android::StringPiece& packageNameToGenerate, + const std::string& entryName, const Styleable* styleable, ClassDefinition* outStyleableClassDef); bool SkipSymbol(SymbolState state); diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp index 3d3d24e6aab5..55c5cb26892f 100644 --- a/tools/aapt2/java/JavaClassGenerator_test.cpp +++ b/tools/aapt2/java/JavaClassGenerator_test.cpp @@ -22,6 +22,8 @@ #include "test/Test.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) { diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp index db84f295db2a..de8e59aed6da 100644 --- a/tools/aapt2/java/ManifestClassGenerator.cpp +++ b/tools/aapt2/java/ManifestClassGenerator.cpp @@ -24,6 +24,8 @@ #include "util/Maybe.h" #include "xml/XmlDom.h" +using android::StringPiece; + namespace aapt { static Maybe<StringPiece> ExtractJavaIdentifier(IDiagnostics* diag, diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp index 5518fe2cae37..b029b20bcf15 100644 --- a/tools/aapt2/jni/aapt2_jni.cpp +++ b/tools/aapt2/jni/aapt2_jni.cpp @@ -26,6 +26,8 @@ #include "util/Util.h" +using android::StringPiece; + namespace aapt { extern int Compile(const std::vector<StringPiece> &args); extern int Link(const std::vector<StringPiece> &args); @@ -65,9 +67,8 @@ static std::vector<ScopedUtfChars> list_to_utfchars(JNIEnv *env, jobject obj) { * The returned pieces can only be used while the original ones have not been * destroyed. */ -static std::vector<aapt::StringPiece> extract_pieces( - const std::vector<ScopedUtfChars> &strings) { - std::vector<aapt::StringPiece> pieces; +static std::vector<StringPiece> extract_pieces(const std::vector<ScopedUtfChars> &strings) { + std::vector<StringPiece> pieces; std::for_each( strings.begin(), strings.end(), @@ -80,8 +81,7 @@ JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile( JNIEnv *env, jclass aapt_obj, jobject arguments_obj) { std::vector<ScopedUtfChars> compile_args_jni = list_to_utfchars(env, arguments_obj); - std::vector<aapt::StringPiece> compile_args = - extract_pieces(compile_args_jni); + std::vector<StringPiece> compile_args = extract_pieces(compile_args_jni); aapt::Compile(compile_args); } @@ -89,7 +89,7 @@ JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink( JNIEnv *env, jclass aapt_obj, jobject arguments_obj) { std::vector<ScopedUtfChars> link_args_jni = list_to_utfchars(env, arguments_obj); - std::vector<aapt::StringPiece> link_args = extract_pieces(link_args_jni); + std::vector<StringPiece> link_args = extract_pieces(link_args_jni); aapt::Link(link_args); } diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp index b525758004f0..c3ce0760f554 100644 --- a/tools/aapt2/link/Link.cpp +++ b/tools/aapt2/link/Link.cpp @@ -23,6 +23,7 @@ #include "android-base/errors.h" #include "android-base/file.h" +#include "androidfw/StringPiece.h" #include "google/protobuf/io/coded_stream.h" #include "AppInfo.h" @@ -51,9 +52,9 @@ #include "split/TableSplitter.h" #include "unflatten/BinaryResourceParser.h" #include "util/Files.h" -#include "util/StringPiece.h" #include "xml/XmlDom.h" +using android::StringPiece; using ::google::protobuf::io::CopyingOutputStreamAdaptor; namespace aapt { @@ -121,7 +122,7 @@ class LinkContext : public IAaptContext { } void SetCompilationPackage(const StringPiece& package_name) { - compilation_package_ = package_name.ToString(); + compilation_package_ = package_name.to_string(); } uint8_t GetPackageId() override { return package_id_; } @@ -2011,14 +2012,14 @@ int Link(const std::vector<StringPiece>& args) { for (std::string& extra_package : extra_java_packages) { // A given package can actually be a colon separated list of packages. for (StringPiece package : util::Split(extra_package, ':')) { - options.extra_java_packages.insert(package.ToString()); + options.extra_java_packages.insert(package.to_string()); } } if (product_list) { for (StringPiece product : util::Tokenize(product_list.value(), ',')) { if (product != "" && product != "default") { - options.products.insert(product.ToString()); + options.products.insert(product.to_string()); } } } diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 4185937e6e38..e5eaf2fe62a8 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -25,6 +25,8 @@ #include "xml/XmlActionExecutor.h" #include "xml/XmlDom.h" +using android::StringPiece; + namespace aapt { /** @@ -293,7 +295,7 @@ static bool RenameManifestPackage(const StringPiece& package_override, CHECK(attr != nullptr); std::string original_package = std::move(attr->value); - attr->value = package_override.ToString(); + attr->value = package_override.to_string(); FullyQualifiedClassNameVisitor visitor(original_package); manifest_el->Accept(&visitor); diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index fc6970c8c5bd..12a304a39f4b 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -18,6 +18,8 @@ #include "test/Test.h" +using android::StringPiece; + namespace aapt { struct ManifestFixerTest : public ::testing::Test { diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index be787b2727ad..ea68b61f89c4 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -30,6 +30,8 @@ #include "util/Util.h" #include "xml/XmlUtil.h" +using android::StringPiece; + namespace aapt { namespace { @@ -192,8 +194,7 @@ class EmptyDeclStack : public xml::IPackageDeclStack { const StringPiece& alias, const StringPiece& local_package) const override { if (alias.empty()) { - return xml::ExtractedPackage{local_package.ToString(), - true /* private */}; + return xml::ExtractedPackage{local_package.to_string(), true /* private */}; } return {}; } diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index d808da31d3b3..7e7b9fb86948 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -24,6 +24,8 @@ #include "ValueVisitor.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table, @@ -351,9 +353,8 @@ std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile( const std::string& package, const FileReference& file_ref) { StringPiece prefix, entry, suffix; if (util::ExtractResFilePathParts(*file_ref.path, &prefix, &entry, &suffix)) { - std::string mangled_entry = - NameMangler::MangleEntry(package, entry.ToString()); - std::string newPath = prefix.ToString() + mangled_entry + suffix.ToString(); + std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string()); + std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string(); std::unique_ptr<FileReference> new_file_ref = util::make_unique<FileReference>( master_table_->string_pool.MakeRef(newPath)); diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h index 4ab83c3f2de3..c96b1b0b4dfb 100644 --- a/tools/aapt2/link/TableMerger.h +++ b/tools/aapt2/link/TableMerger.h @@ -96,8 +96,8 @@ class TableMerger { * An io::IFileCollection is needed in order to find the referenced Files and * process them. */ - bool MergeAndMangle(const Source& src, const StringPiece& package, - ResourceTable* table, io::IFileCollection* collection); + bool MergeAndMangle(const Source& src, const android::StringPiece& package, ResourceTable* table, + io::IFileCollection* collection); /** * Merges a compiled file that belongs to this same or empty package. This is diff --git a/tools/aapt2/link/VersionCollapser_test.cpp b/tools/aapt2/link/VersionCollapser_test.cpp index 1b5592f717d9..44babb21ae6e 100644 --- a/tools/aapt2/link/VersionCollapser_test.cpp +++ b/tools/aapt2/link/VersionCollapser_test.cpp @@ -18,6 +18,8 @@ #include "test/Test.h" +using android::StringPiece; + namespace aapt { static std::unique_ptr<ResourceTable> BuildTableWithConfigs( diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp index 767384d8d956..1a3da73b8ce0 100644 --- a/tools/aapt2/process/SymbolTable.cpp +++ b/tools/aapt2/process/SymbolTable.cpp @@ -25,6 +25,8 @@ #include "ValueVisitor.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { void SymbolTable::AppendSource(std::unique_ptr<ISymbolSource> source) { diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h index 25f756522580..cf597bb4e679 100644 --- a/tools/aapt2/process/SymbolTable.h +++ b/tools/aapt2/process/SymbolTable.h @@ -154,7 +154,7 @@ class AssetManagerSymbolSource : public ISymbolSource { public: AssetManagerSymbolSource() = default; - bool AddAssetPath(const StringPiece& path); + bool AddAssetPath(const android::StringPiece& path); std::unique_ptr<SymbolTable::Symbol> FindByName( const ResourceName& name) override; diff --git a/tools/aapt2/proto/ProtoHelpers.h b/tools/aapt2/proto/ProtoHelpers.h index 735cda0bde78..344e9477ea71 100644 --- a/tools/aapt2/proto/ProtoHelpers.h +++ b/tools/aapt2/proto/ProtoHelpers.h @@ -23,7 +23,7 @@ #include "ResourceTable.h" #include "Source.h" #include "StringPool.h" -#include "proto/frameworks/base/tools/aapt2/Format.pb.h" +#include "Format.pb.h" namespace aapt { diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp index 0d0e46da4ec8..7230b55e10e3 100644 --- a/tools/aapt2/proto/TableProtoSerializer.cpp +++ b/tools/aapt2/proto/TableProtoSerializer.cpp @@ -22,7 +22,7 @@ #include "proto/ProtoSerialize.h" #include "util/BigBuffer.h" -#include <android-base/logging.h> +#include "android-base/logging.h" using google::protobuf::io::CodedOutputStream; using google::protobuf::io::CodedInputStream; @@ -239,7 +239,7 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) { if (type->id) { pb_type->set_id(type->id.value()); } - pb_type->set_name(ToString(type->type).ToString()); + pb_type->set_name(ToString(type->type).to_string()); for (auto& entry : type->entries) { pb::Entry* pb_entry = pb_type->add_entries(); diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp index 7aad86fa7257..38cfd2e61054 100644 --- a/tools/aapt2/split/TableSplitter.cpp +++ b/tools/aapt2/split/TableSplitter.cpp @@ -21,6 +21,7 @@ #include <set> #include <unordered_map> #include <vector> + #include "android-base/logging.h" #include "ConfigDescription.h" diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h index 9377306dc1b6..6888cf32fab8 100644 --- a/tools/aapt2/test/Builders.h +++ b/tools/aapt2/test/Builders.h @@ -37,95 +37,86 @@ class ResourceTableBuilder { StringPool* string_pool() { return &table_->string_pool; } - ResourceTableBuilder& SetPackageId(const StringPiece& package_name, - uint8_t id) { + ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id) { ResourceTablePackage* package = table_->CreatePackage(package_name, id); CHECK(package != nullptr); return *this; } - ResourceTableBuilder& AddSimple(const StringPiece& name, - const ResourceId& id = {}) { + ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {}) { return AddValue(name, id, util::make_unique<Id>()); } - ResourceTableBuilder& AddSimple(const StringPiece& name, - const ConfigDescription& config, + ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ConfigDescription& config, const ResourceId& id = {}) { return AddValue(name, config, id, util::make_unique<Id>()); } - ResourceTableBuilder& AddReference(const StringPiece& name, - const StringPiece& ref) { + ResourceTableBuilder& AddReference(const android::StringPiece& name, + const android::StringPiece& ref) { return AddReference(name, {}, ref); } - ResourceTableBuilder& AddReference(const StringPiece& name, - const ResourceId& id, - const StringPiece& ref) { + ResourceTableBuilder& AddReference(const android::StringPiece& name, const ResourceId& id, + const android::StringPiece& ref) { return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref))); } - ResourceTableBuilder& AddString(const StringPiece& name, - const StringPiece& str) { + ResourceTableBuilder& AddString(const android::StringPiece& name, + const android::StringPiece& str) { return AddString(name, {}, str); } - ResourceTableBuilder& AddString(const StringPiece& name, const ResourceId& id, - const StringPiece& str) { + ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id, + const android::StringPiece& str) { return AddValue( name, id, util::make_unique<String>(table_->string_pool.MakeRef(str))); } - ResourceTableBuilder& AddString(const StringPiece& name, const ResourceId& id, + ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id, const ConfigDescription& config, - const StringPiece& str) { + const android::StringPiece& str) { return AddValue(name, config, id, util::make_unique<String>( table_->string_pool.MakeRef(str))); } - ResourceTableBuilder& AddFileReference(const StringPiece& name, - const StringPiece& path) { + ResourceTableBuilder& AddFileReference(const android::StringPiece& name, + const android::StringPiece& path) { return AddFileReference(name, {}, path); } - ResourceTableBuilder& AddFileReference(const StringPiece& name, - const ResourceId& id, - const StringPiece& path) { + ResourceTableBuilder& AddFileReference(const android::StringPiece& name, const ResourceId& id, + const android::StringPiece& path) { return AddValue(name, id, util::make_unique<FileReference>( table_->string_pool.MakeRef(path))); } - ResourceTableBuilder& AddFileReference(const StringPiece& name, - const StringPiece& path, + ResourceTableBuilder& AddFileReference(const android::StringPiece& name, + const android::StringPiece& path, const ConfigDescription& config) { return AddValue(name, config, {}, util::make_unique<FileReference>( table_->string_pool.MakeRef(path))); } - ResourceTableBuilder& AddValue(const StringPiece& name, - std::unique_ptr<Value> value) { + ResourceTableBuilder& AddValue(const android::StringPiece& name, std::unique_ptr<Value> value) { return AddValue(name, {}, std::move(value)); } - ResourceTableBuilder& AddValue(const StringPiece& name, const ResourceId& id, + ResourceTableBuilder& AddValue(const android::StringPiece& name, const ResourceId& id, std::unique_ptr<Value> value) { return AddValue(name, {}, id, std::move(value)); } - ResourceTableBuilder& AddValue(const StringPiece& name, - const ConfigDescription& config, - const ResourceId& id, - std::unique_ptr<Value> value) { + ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config, + const ResourceId& id, std::unique_ptr<Value> value) { ResourceName res_name = ParseNameOrDie(name); CHECK(table_->AddResourceAllowMangled(res_name, id, config, {}, std::move(value), &diagnostics_)); return *this; } - ResourceTableBuilder& SetSymbolState(const StringPiece& name, - const ResourceId& id, + ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id, SymbolState state) { ResourceName res_name = ParseNameOrDie(name); Symbol symbol; @@ -144,8 +135,8 @@ class ResourceTableBuilder { std::unique_ptr<ResourceTable> table_ = util::make_unique<ResourceTable>(); }; -inline std::unique_ptr<Reference> BuildReference( - const StringPiece& ref, const Maybe<ResourceId>& id = {}) { +inline std::unique_ptr<Reference> BuildReference(const android::StringPiece& ref, + const Maybe<ResourceId>& id = {}) { std::unique_ptr<Reference> reference = util::make_unique<Reference>(ParseNameOrDie(ref)); reference->id = id; @@ -174,7 +165,7 @@ class ValueBuilder { return *this; } - ValueBuilder& SetComment(const StringPiece& str) { + ValueBuilder& SetComment(const android::StringPiece& str) { value_->SetComment(str); return *this; } @@ -199,7 +190,7 @@ class AttributeBuilder { return *this; } - AttributeBuilder& AddItem(const StringPiece& name, uint32_t value) { + AttributeBuilder& AddItem(const android::StringPiece& name, uint32_t value) { attr_->symbols.push_back(Attribute::Symbol{ Reference(ResourceName({}, ResourceType::kId, name)), value}); return *this; @@ -217,18 +208,18 @@ class StyleBuilder { public: StyleBuilder() = default; - StyleBuilder& SetParent(const StringPiece& str) { + StyleBuilder& SetParent(const android::StringPiece& str) { style_->parent = Reference(ParseNameOrDie(str)); return *this; } - StyleBuilder& AddItem(const StringPiece& str, std::unique_ptr<Item> value) { + StyleBuilder& AddItem(const android::StringPiece& str, std::unique_ptr<Item> value) { style_->entries.push_back( Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)}); return *this; } - StyleBuilder& AddItem(const StringPiece& str, const ResourceId& id, + StyleBuilder& AddItem(const android::StringPiece& str, const ResourceId& id, std::unique_ptr<Item> value) { AddItem(str, std::move(value)); style_->entries.back().key.id = id; @@ -247,8 +238,7 @@ class StyleableBuilder { public: StyleableBuilder() = default; - StyleableBuilder& AddItem(const StringPiece& str, - const Maybe<ResourceId>& id = {}) { + StyleableBuilder& AddItem(const android::StringPiece& str, const Maybe<ResourceId>& id = {}) { styleable_->entries.push_back(Reference(ParseNameOrDie(str))); styleable_->entries.back().id = id; return *this; @@ -262,7 +252,7 @@ class StyleableBuilder { std::unique_ptr<Styleable> styleable_ = util::make_unique<Styleable>(); }; -inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const StringPiece& str) { +inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const android::StringPiece& str) { std::stringstream in; in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str; StdErrDiagnostics diag; @@ -273,7 +263,7 @@ inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const StringPiece& str) { } inline std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName( - IAaptContext* context, const StringPiece& str) { + IAaptContext* context, const android::StringPiece& str) { std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str); doc->file.name.package = context->GetCompilationPackage(); return doc; diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h index 36892017f2d3..248921f3afea 100644 --- a/tools/aapt2/test/Common.h +++ b/tools/aapt2/test/Common.h @@ -21,6 +21,7 @@ #include "android-base/logging.h" #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "gtest/gtest.h" #include "ConfigDescription.h" @@ -30,7 +31,6 @@ #include "ValueVisitor.h" #include "io/File.h" #include "process/IResourceTableConsumer.h" -#include "util/StringPiece.h" // // GTEST 1.7 doesn't explicitly cast to bool, which causes explicit operators to @@ -68,23 +68,22 @@ inline IDiagnostics* GetDiagnostics() { return &diag; } -inline ResourceName ParseNameOrDie(const StringPiece& str) { +inline ResourceName ParseNameOrDie(const android::StringPiece& str) { ResourceNameRef ref; CHECK(ResourceUtils::ParseResourceName(str, &ref)) << "invalid resource name"; return ref.ToResourceName(); } -inline ConfigDescription ParseConfigOrDie(const StringPiece& str) { +inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) { ConfigDescription config; CHECK(ConfigDescription::Parse(str, &config)) << "invalid configuration"; return config; } template <typename T> -T* GetValueForConfigAndProduct(ResourceTable* table, - const StringPiece& res_name, +T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name, const ConfigDescription& config, - const StringPiece& product) { + const android::StringPiece& product) { Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name)); if (result) { @@ -98,19 +97,19 @@ T* GetValueForConfigAndProduct(ResourceTable* table, } template <typename T> -T* GetValueForConfig(ResourceTable* table, const StringPiece& res_name, +T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name, const ConfigDescription& config) { return GetValueForConfigAndProduct<T>(table, res_name, config, {}); } template <typename T> -T* GetValue(ResourceTable* table, const StringPiece& res_name) { +T* GetValue(ResourceTable* table, const android::StringPiece& res_name) { return GetValueForConfig<T>(table, res_name, {}); } class TestFile : public io::IFile { public: - explicit TestFile(const StringPiece& path) : source_(path) {} + explicit TestFile(const android::StringPiece& path) : source_(path) {} std::unique_ptr<io::IData> OpenAsData() override { return {}; } diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h index 7986329ab640..63e5f1628581 100644 --- a/tools/aapt2/test/Context.h +++ b/tools/aapt2/test/Context.h @@ -70,8 +70,8 @@ class Context : public IAaptContext { class ContextBuilder { public: - ContextBuilder& SetCompilationPackage(const StringPiece& package) { - context_->compilation_package_ = package.ToString(); + ContextBuilder& SetCompilationPackage(const android::StringPiece& package) { + context_->compilation_package_ = package.to_string(); return *this; } @@ -103,9 +103,8 @@ class ContextBuilder { class StaticSymbolSourceBuilder { public: - StaticSymbolSourceBuilder& AddPublicSymbol( - const StringPiece& name, ResourceId id, - std::unique_ptr<Attribute> attr = {}) { + StaticSymbolSourceBuilder& AddPublicSymbol(const android::StringPiece& name, ResourceId id, + std::unique_ptr<Attribute> attr = {}) { std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(id, std::move(attr), true); symbol_source_->name_map_[ParseNameOrDie(name)] = symbol.get(); @@ -114,7 +113,7 @@ class StaticSymbolSourceBuilder { return *this; } - StaticSymbolSourceBuilder& AddSymbol(const StringPiece& name, ResourceId id, + StaticSymbolSourceBuilder& AddSymbol(const android::StringPiece& name, ResourceId id, std::unique_ptr<Attribute> attr = {}) { std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(id, std::move(attr), false); diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp index f034607ea8f5..aa840e2e3c8d 100644 --- a/tools/aapt2/util/Files.cpp +++ b/tools/aapt2/util/Files.cpp @@ -35,6 +35,8 @@ #include <direct.h> #endif +using android::StringPiece; + namespace aapt { namespace file { @@ -72,10 +74,9 @@ FileType GetFileType(const StringPiece& path) { inline static int MkdirImpl(const StringPiece& path) { #ifdef _WIN32 - return _mkdir(path.ToString().c_str()); + return _mkdir(path.to_string().c_str()); #else - return mkdir(path.ToString().c_str(), - S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP); + return mkdir(path.to_string().c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP); #endif } @@ -184,7 +185,7 @@ bool AppendArgsFromFile(const StringPiece& path, std::vector<std::string>* out_arglist, std::string* out_error) { std::string contents; - if (!android::base::ReadFileToString(path.ToString(), &contents)) { + if (!android::base::ReadFileToString(path.to_string(), &contents)) { if (out_error) *out_error = "failed to read argument-list file"; return false; } @@ -192,7 +193,7 @@ bool AppendArgsFromFile(const StringPiece& path, for (StringPiece line : util::Tokenize(contents, ' ')) { line = util::TrimWhitespace(line); if (!line.empty()) { - out_arglist->push_back(line.ToString()); + out_arglist->push_back(line.to_string()); } } return true; diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h index a157dbd80893..95c492f3b3af 100644 --- a/tools/aapt2/util/Files.h +++ b/tools/aapt2/util/Files.h @@ -22,12 +22,12 @@ #include <vector> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "utils/FileMap.h" #include "Diagnostics.h" #include "Maybe.h" #include "Source.h" -#include "util/StringPiece.h" namespace aapt { namespace file { @@ -50,51 +50,49 @@ enum class FileType { kSocket, }; -FileType GetFileType(const StringPiece& path); +FileType GetFileType(const android::StringPiece& path); /* * Appends a path to `base`, separated by the directory separator. */ -void AppendPath(std::string* base, StringPiece part); +void AppendPath(std::string* base, android::StringPiece part); /* * Makes all the directories in `path`. The last element in the path * is interpreted as a directory. */ -bool mkdirs(const StringPiece& path); +bool mkdirs(const android::StringPiece& path); /** * Returns all but the last part of the path. */ -StringPiece GetStem(const StringPiece& path); +android::StringPiece GetStem(const android::StringPiece& path); /** * Returns the last part of the path with extension. */ -StringPiece GetFilename(const StringPiece& path); +android::StringPiece GetFilename(const android::StringPiece& path); /** * Returns the extension of the path. This is the entire string after * the first '.' of the last part of the path. */ -StringPiece GetExtension(const StringPiece& path); +android::StringPiece GetExtension(const android::StringPiece& path); /** * Converts a package name (com.android.app) to a path: com/android/app */ -std::string PackageToPath(const StringPiece& package); +std::string PackageToPath(const android::StringPiece& package); /** * Creates a FileMap for the file at path. */ -Maybe<android::FileMap> MmapPath(const StringPiece& path, - std::string* out_error); +Maybe<android::FileMap> MmapPath(const android::StringPiece& path, std::string* out_error); /** * Reads the file at path and appends each line to the outArgList vector. */ -bool AppendArgsFromFile(const StringPiece& path, - std::vector<std::string>* out_arglist, +bool AppendArgsFromFile(const android::StringPiece& path, std::vector<std::string>* out_arglist, std::string* out_error); /* @@ -120,7 +118,7 @@ class FileFilter { * - Otherwise the full string is matched. * - match is not case-sensitive. */ - bool SetPattern(const StringPiece& pattern); + bool SetPattern(const android::StringPiece& pattern); /** * Applies the filter, returning true for pass, false for fail. diff --git a/tools/aapt2/util/StringPiece.h b/tools/aapt2/util/StringPiece.h deleted file mode 100644 index 5144b1f1fd6a..000000000000 --- a/tools/aapt2/util/StringPiece.h +++ /dev/null @@ -1,298 +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_STRING_PIECE_H -#define AAPT_STRING_PIECE_H - -#include <ostream> -#include <string> - -#include "utils/JenkinsHash.h" -#include "utils/String8.h" -#include "utils/Unicode.h" - -namespace aapt { - -/** - * Read only wrapper around basic C strings. - * Prevents excessive copying. - * - * WARNING: When creating from std::basic_string<>, moving the original - * std::basic_string<> will invalidate the data held in a BasicStringPiece<>. - * BasicStringPiece<> should only be used transitively. - */ -template <typename TChar> -class BasicStringPiece { - public: - using const_iterator = const TChar*; - using difference_type = size_t; - - // End of string marker. - constexpr static const size_t npos = static_cast<size_t>(-1); - - BasicStringPiece(); - BasicStringPiece(const BasicStringPiece<TChar>& str); - BasicStringPiece(const std::basic_string<TChar>& str); // NOLINT(implicit) - BasicStringPiece(const TChar* str); // NOLINT(implicit) - BasicStringPiece(const TChar* str, size_t len); - - BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs); - BasicStringPiece<TChar>& assign(const TChar* str, size_t len); - - BasicStringPiece<TChar> substr(size_t start, size_t len = npos) const; - BasicStringPiece<TChar> substr( - BasicStringPiece<TChar>::const_iterator begin, - BasicStringPiece<TChar>::const_iterator end) const; - - const TChar* data() const; - size_t length() const; - size_t size() const; - bool empty() const; - std::basic_string<TChar> ToString() const; - - bool contains(const BasicStringPiece<TChar>& rhs) const; - int compare(const BasicStringPiece<TChar>& rhs) const; - bool operator<(const BasicStringPiece<TChar>& rhs) const; - bool operator>(const BasicStringPiece<TChar>& rhs) const; - bool operator==(const BasicStringPiece<TChar>& rhs) const; - bool operator!=(const BasicStringPiece<TChar>& rhs) const; - - const_iterator begin() const; - const_iterator end() const; - - private: - const TChar* data_; - size_t length_; -}; - -using StringPiece = BasicStringPiece<char>; -using StringPiece16 = BasicStringPiece<char16_t>; - -// -// BasicStringPiece implementation. -// - -template <typename TChar> -constexpr const size_t BasicStringPiece<TChar>::npos; - -template <typename TChar> -inline BasicStringPiece<TChar>::BasicStringPiece() - : data_(nullptr), length_(0) {} - -template <typename TChar> -inline BasicStringPiece<TChar>::BasicStringPiece( - const BasicStringPiece<TChar>& str) - : data_(str.data_), length_(str.length_) {} - -template <typename TChar> -inline BasicStringPiece<TChar>::BasicStringPiece( - const std::basic_string<TChar>& str) - : data_(str.data()), length_(str.length()) {} - -template <> -inline BasicStringPiece<char>::BasicStringPiece(const char* str) - : data_(str), length_(str != nullptr ? strlen(str) : 0) {} - -template <> -inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str) - : data_(str), length_(str != nullptr ? strlen16(str) : 0) {} - -template <typename TChar> -inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len) - : data_(str), length_(len) {} - -template <typename TChar> -inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=( - const BasicStringPiece<TChar>& rhs) { - data_ = rhs.data_; - length_ = rhs.length_; - return *this; -} - -template <typename TChar> -inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign( - const TChar* str, size_t len) { - data_ = str; - length_ = len; - return *this; -} - -template <typename TChar> -inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr( - size_t start, size_t len) const { - if (len == npos) { - len = length_ - start; - } - - if (start > length_ || start + len > length_) { - return BasicStringPiece<TChar>(); - } - return BasicStringPiece<TChar>(data_ + start, len); -} - -template <typename TChar> -inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr( - BasicStringPiece<TChar>::const_iterator begin, - BasicStringPiece<TChar>::const_iterator end) const { - return BasicStringPiece<TChar>(begin, end - begin); -} - -template <typename TChar> -inline const TChar* BasicStringPiece<TChar>::data() const { - return data_; -} - -template <typename TChar> -inline size_t BasicStringPiece<TChar>::length() const { - return length_; -} - -template <typename TChar> -inline size_t BasicStringPiece<TChar>::size() const { - return length_; -} - -template <typename TChar> -inline bool BasicStringPiece<TChar>::empty() const { - return length_ == 0; -} - -template <typename TChar> -inline std::basic_string<TChar> BasicStringPiece<TChar>::ToString() const { - return std::basic_string<TChar>(data_, length_); -} - -template <> -inline bool BasicStringPiece<char>::contains( - const BasicStringPiece<char>& rhs) const { - if (!data_ || !rhs.data_) { - return false; - } - if (rhs.length_ > length_) { - return false; - } - return strstr(data_, rhs.data_) != nullptr; -} - -template <> -inline int BasicStringPiece<char>::compare( - const BasicStringPiece<char>& rhs) const { - const char nullStr = '\0'; - const char* b1 = data_ != nullptr ? data_ : &nullStr; - const char* e1 = b1 + length_; - const char* b2 = rhs.data_ != nullptr ? rhs.data_ : &nullStr; - const char* e2 = b2 + rhs.length_; - - while (b1 < e1 && b2 < e2) { - const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++); - if (d) { - return d; - } - } - return static_cast<int>(length_ - rhs.length_); -} - -inline ::std::ostream& operator<<(::std::ostream& out, - const BasicStringPiece<char16_t>& str) { - android::String8 utf8(str.data(), str.size()); - return out.write(utf8.string(), utf8.size()); -} - -template <> -inline bool BasicStringPiece<char16_t>::contains( - const BasicStringPiece<char16_t>& rhs) const { - if (!data_ || !rhs.data_) { - return false; - } - if (rhs.length_ > length_) { - return false; - } - return strstr16(data_, rhs.data_) != nullptr; -} - -template <> -inline int BasicStringPiece<char16_t>::compare( - const BasicStringPiece<char16_t>& rhs) const { - const char16_t nullStr = u'\0'; - const char16_t* b1 = data_ != nullptr ? data_ : &nullStr; - const char16_t* b2 = rhs.data_ != nullptr ? rhs.data_ : &nullStr; - return strzcmp16(b1, length_, b2, rhs.length_); -} - -template <typename TChar> -inline bool BasicStringPiece<TChar>::operator<( - const BasicStringPiece<TChar>& rhs) const { - return compare(rhs) < 0; -} - -template <typename TChar> -inline bool BasicStringPiece<TChar>::operator>( - const BasicStringPiece<TChar>& rhs) const { - return compare(rhs) > 0; -} - -template <typename TChar> -inline bool BasicStringPiece<TChar>::operator==( - const BasicStringPiece<TChar>& rhs) const { - return compare(rhs) == 0; -} - -template <typename TChar> -inline bool BasicStringPiece<TChar>::operator!=( - const BasicStringPiece<TChar>& rhs) const { - return compare(rhs) != 0; -} - -template <typename TChar> -inline typename BasicStringPiece<TChar>::const_iterator -BasicStringPiece<TChar>::begin() const { - return data_; -} - -template <typename TChar> -inline typename BasicStringPiece<TChar>::const_iterator -BasicStringPiece<TChar>::end() const { - return data_ + length_; -} - -inline ::std::ostream& operator<<(::std::ostream& out, - const BasicStringPiece<char>& str) { - return out.write(str.data(), str.size()); -} - -} // namespace aapt - -inline ::std::ostream& operator<<(::std::ostream& out, - const std::u16string& str) { - android::String8 utf8(str.data(), str.size()); - return out.write(utf8.string(), utf8.size()); -} - -namespace std { - -template <typename TChar> -struct hash<aapt::BasicStringPiece<TChar>> { - size_t operator()(const aapt::BasicStringPiece<TChar>& str) const { - uint32_t hashCode = android::JenkinsHashMixBytes( - 0, reinterpret_cast<const uint8_t*>(str.data()), - sizeof(TChar) * str.size()); - return static_cast<size_t>(hashCode); - } -}; - -} // namespace std - -#endif // AAPT_STRING_PIECE_H diff --git a/tools/aapt2/util/StringPiece_test.cpp b/tools/aapt2/util/StringPiece_test.cpp deleted file mode 100644 index 048961d49584..000000000000 --- a/tools/aapt2/util/StringPiece_test.cpp +++ /dev/null @@ -1,95 +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 "util/StringPiece.h" - -#include <algorithm> -#include <string> -#include <vector> - -#include "test/Test.h" - -namespace aapt { - -TEST(StringPieceTest, CompareNonNullTerminatedPiece) { - StringPiece a("hello world", 5); - StringPiece b("hello moon", 5); - EXPECT_EQ(a, b); - - StringPiece16 a16(u"hello world", 5); - StringPiece16 b16(u"hello moon", 5); - EXPECT_EQ(a16, b16); -} - -TEST(StringPieceTest, PiecesHaveCorrectSortOrder) { - std::string testing("testing"); - std::string banana("banana"); - std::string car("car"); - - EXPECT_TRUE(StringPiece(testing) > banana); - EXPECT_TRUE(StringPiece(testing) > car); - EXPECT_TRUE(StringPiece(banana) < testing); - EXPECT_TRUE(StringPiece(banana) < car); - EXPECT_TRUE(StringPiece(car) < testing); - EXPECT_TRUE(StringPiece(car) > banana); -} - -TEST(StringPieceTest, PiecesHaveCorrectSortOrderUtf8) { - std::string testing("testing"); - std::string banana("banana"); - std::string car("car"); - - EXPECT_TRUE(StringPiece(testing) > banana); - EXPECT_TRUE(StringPiece(testing) > car); - EXPECT_TRUE(StringPiece(banana) < testing); - EXPECT_TRUE(StringPiece(banana) < car); - EXPECT_TRUE(StringPiece(car) < testing); - EXPECT_TRUE(StringPiece(car) > banana); -} - -TEST(StringPieceTest, ContainsOtherStringPiece) { - StringPiece text("I am a leaf on the wind."); - StringPiece start_needle("I am"); - StringPiece end_needle("wind."); - StringPiece middle_needle("leaf"); - StringPiece empty_needle(""); - StringPiece missing_needle("soar"); - StringPiece long_needle("This string is longer than the text."); - - EXPECT_TRUE(text.contains(start_needle)); - EXPECT_TRUE(text.contains(end_needle)); - EXPECT_TRUE(text.contains(middle_needle)); - EXPECT_TRUE(text.contains(empty_needle)); - EXPECT_FALSE(text.contains(missing_needle)); - EXPECT_FALSE(text.contains(long_needle)); - - StringPiece16 text16(u"I am a leaf on the wind."); - StringPiece16 start_needle16(u"I am"); - StringPiece16 end_needle16(u"wind."); - StringPiece16 middle_needle16(u"leaf"); - StringPiece16 empty_needle16(u""); - StringPiece16 missing_needle16(u"soar"); - StringPiece16 long_needle16(u"This string is longer than the text."); - - EXPECT_TRUE(text16.contains(start_needle16)); - EXPECT_TRUE(text16.contains(end_needle16)); - EXPECT_TRUE(text16.contains(middle_needle16)); - EXPECT_TRUE(text16.contains(empty_needle16)); - EXPECT_FALSE(text16.contains(missing_needle16)); - EXPECT_FALSE(text16.contains(long_needle16)); -} - -} // namespace aapt diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp index d5c0c8a7a5fe..cf2232254ec4 100644 --- a/tools/aapt2/util/Util.cpp +++ b/tools/aapt2/util/Util.cpp @@ -15,9 +15,6 @@ */ #include "util/Util.h" -#include "util/BigBuffer.h" -#include "util/Maybe.h" -#include "util/StringPiece.h" #include <utils/Unicode.h> #include <algorithm> @@ -25,6 +22,14 @@ #include <string> #include <vector> +#include "androidfw/StringPiece.h" + +#include "util/BigBuffer.h" +#include "util/Maybe.h" + +using android::StringPiece; +using android::StringPiece16; + namespace aapt { namespace util { @@ -36,7 +41,7 @@ static std::vector<std::string> SplitAndTransform( StringPiece::const_iterator current; do { current = std::find(start, end, sep); - parts.emplace_back(str.substr(start, current).ToString()); + 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); @@ -162,7 +167,7 @@ Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, } if (util::IsJavaClassName(classname)) { - return classname.ToString(); + return classname.to_string(); } if (package.empty()) { diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h index 05e9cc5d28ca..f8fa80ed7d66 100644 --- a/tools/aapt2/util/Util.h +++ b/tools/aapt2/util/Util.h @@ -24,11 +24,11 @@ #include <vector> #include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" #include "utils/ByteOrder.h" #include "util/BigBuffer.h" #include "util/Maybe.h" -#include "util/StringPiece.h" #ifdef _WIN32 // TODO(adamlesinski): remove once http://b/32447322 is resolved. @@ -44,26 +44,24 @@ namespace aapt { namespace util { -std::vector<std::string> Split(const StringPiece& str, char sep); -std::vector<std::string> SplitAndLowercase(const StringPiece& str, char sep); +std::vector<std::string> Split(const android::StringPiece& str, char sep); +std::vector<std::string> SplitAndLowercase(const android::StringPiece& str, char sep); /** * Returns true if the string starts with prefix. */ -bool StartsWith(const StringPiece& str, const StringPiece& prefix); +bool StartsWith(const android::StringPiece& str, const android::StringPiece& prefix); /** * Returns true if the string ends with suffix. */ -bool EndsWith(const StringPiece& str, const StringPiece& suffix); +bool EndsWith(const android::StringPiece& str, const android::StringPiece& suffix); /** * Creates a new StringPiece16 that points to a substring * of the original string without leading or trailing whitespace. */ -StringPiece TrimWhitespace(const StringPiece& str); - -StringPiece TrimWhitespace(const StringPiece& str); +android::StringPiece TrimWhitespace(const android::StringPiece& str); /** * UTF-16 isspace(). It basically checks for lower range characters that are @@ -75,18 +73,18 @@ inline bool isspace16(char16_t c) { return c < 0x0080 && isspace(c); } * Returns an iterator to the first character that is not alpha-numeric and that * is not in the allowedChars set. */ -StringPiece::const_iterator FindNonAlphaNumericAndNotInSet( - const StringPiece& str, const StringPiece& allowed_chars); +android::StringPiece::const_iterator FindNonAlphaNumericAndNotInSet( + const android::StringPiece& str, const android::StringPiece& allowed_chars); /** * Tests that the string is a valid Java class name. */ -bool IsJavaClassName(const StringPiece& str); +bool IsJavaClassName(const android::StringPiece& str); /** * Tests that the string is a valid Java package name. */ -bool IsJavaPackageName(const StringPiece& str); +bool IsJavaPackageName(const android::StringPiece& str); /** * Converts the class name to a fully qualified class name from the given @@ -97,8 +95,8 @@ bool IsJavaPackageName(const StringPiece& str); * .a.b --> package.a.b * asdf.adsf --> asdf.adsf */ -Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package, - const StringPiece& class_name); +Maybe<std::string> GetFullyQualifiedClassName(const android::StringPiece& package, + const android::StringPiece& class_name); /** * Makes a std::unique_ptr<> with the template parameter inferred by the @@ -138,7 +136,7 @@ template <typename Container> * stored as UTF-8, * the conversion to UTF-16 happens within ResStringPool. */ -StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx); +android::StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx); /** * Helper method to extract a UTF-8 string from a StringPool. If the string is @@ -159,11 +157,11 @@ std::string GetString(const android::ResStringPool& pool, size_t idx); * which will * break the string interpolation. */ -bool VerifyJavaStringFormat(const StringPiece& str); +bool VerifyJavaStringFormat(const android::StringPiece& str); class StringBuilder { public: - StringBuilder& Append(const StringPiece& str); + StringBuilder& Append(const android::StringPiece& str); const std::string& ToString() const; const std::string& Error() const; @@ -194,8 +192,8 @@ inline StringBuilder::operator bool() const { return error_.empty(); } /** * Converts a UTF8 string to a UTF16 string. */ -std::u16string Utf8ToUtf16(const StringPiece& utf8); -std::string Utf16ToUtf8(const StringPiece16& utf16); +std::u16string Utf8ToUtf16(const android::StringPiece& utf8); +std::string Utf16ToUtf8(const android::StringPiece16& utf16); /** * Writes the entire BigBuffer to the output stream. @@ -220,22 +218,22 @@ class Tokenizer { iterator& operator++(); - StringPiece operator*() { return token_; } + android::StringPiece operator*() { return token_; } bool operator==(const iterator& rhs) const; bool operator!=(const iterator& rhs) const; private: friend class Tokenizer; - iterator(StringPiece s, char sep, StringPiece tok, bool end); + iterator(android::StringPiece s, char sep, android::StringPiece tok, bool end); - StringPiece str_; + android::StringPiece str_; char separator_; - StringPiece token_; + android::StringPiece token_; bool end_; }; - Tokenizer(StringPiece str, char sep); + Tokenizer(android::StringPiece str, char sep); iterator begin() { return begin_; } @@ -246,9 +244,7 @@ class Tokenizer { const iterator end_; }; -inline Tokenizer Tokenize(const StringPiece& str, char sep) { - return Tokenizer(str, sep); -} +inline Tokenizer Tokenize(const android::StringPiece& str, char sep) { return Tokenizer(str, sep); } inline uint16_t HostToDevice16(uint16_t value) { return htods(value); } @@ -267,8 +263,8 @@ inline uint32_t DeviceToHost32(uint32_t value) { return dtohl(value); } * * Returns true if successful. */ -bool ExtractResFilePathParts(const StringPiece& path, StringPiece* out_prefix, - StringPiece* out_entry, StringPiece* out_suffix); +bool ExtractResFilePathParts(const android::StringPiece& path, android::StringPiece* out_prefix, + android::StringPiece* out_entry, android::StringPiece* out_suffix); } // namespace util diff --git a/tools/aapt2/util/Util_test.cpp b/tools/aapt2/util/Util_test.cpp index cac3de4696ab..e49aee5d50ed 100644 --- a/tools/aapt2/util/Util_test.cpp +++ b/tools/aapt2/util/Util_test.cpp @@ -20,6 +20,8 @@ #include "test/Test.h" +using android::StringPiece; + namespace aapt { TEST(UtilTest, TrimOnlyWhitespace) { diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp index 960d3614305e..fab2f19fc0ac 100644 --- a/tools/aapt2/xml/XmlDom.cpp +++ b/tools/aapt2/xml/XmlDom.cpp @@ -29,6 +29,9 @@ #include "XmlPullParser.h" #include "util/Util.h" +using android::StringPiece; +using android::StringPiece16; + namespace aapt { namespace xml { @@ -52,10 +55,10 @@ static void SplitName(const char* name, std::string* out_ns, if (*p == 0) { out_ns->clear(); - *out_name = StringPiece(name).ToString(); + out_name->assign(name); } else { - *out_ns = StringPiece(name, (p - name)).ToString(); - *out_name = StringPiece(p + 1).ToString(); + out_ns->assign(name, (p - name)); + out_name->assign(p + 1); } } @@ -83,11 +86,11 @@ static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, std::unique_ptr<Namespace> ns = util::make_unique<Namespace>(); if (prefix) { - ns->namespace_prefix = StringPiece(prefix).ToString(); + ns->namespace_prefix = prefix; } if (uri) { - ns->namespace_uri = StringPiece(uri).ToString(); + ns->namespace_uri = uri; } AddToStack(stack, parser, std::move(ns)); @@ -117,7 +120,7 @@ static void XMLCALL StartElementHandler(void* user_data, const char* name, while (*attrs) { Attribute attribute; SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); - attribute.value = StringPiece(*attrs++).ToString(); + attribute.value = *attrs++; // Insert in sorted order. auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), @@ -153,14 +156,14 @@ static void XMLCALL CharacterDataHandler(void* user_data, const char* s, if (!currentParent->children.empty()) { Node* last_child = currentParent->children.back().get(); if (Text* text = NodeCast<Text>(last_child)) { - text->text += StringPiece(s, len).ToString(); + text->text.append(s, len); return; } } } std::unique_ptr<Text> text = util::make_unique<Text>(); - text->text = StringPiece(s, len).ToString(); + text->text.assign(s, len); AddToStack(stack, parser, std::move(text)); } @@ -495,15 +498,14 @@ void PackageAwareVisitor::Visit(Namespace* ns) { Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias( const StringPiece& alias, const StringPiece& local_package) const { if (alias.empty()) { - return ExtractedPackage{local_package.ToString(), false /* private */}; + return ExtractedPackage{local_package.to_string(), false /* private */}; } const auto rend = package_decls_.rend(); for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) { if (alias == iter->prefix) { if (iter->package.package.empty()) { - return ExtractedPackage{local_package.ToString(), - iter->package.private_namespace}; + return ExtractedPackage{local_package.to_string(), iter->package.private_namespace}; } return iter->package; } diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h index 720fe357bfa1..90cdfb6932b1 100644 --- a/tools/aapt2/xml/XmlDom.h +++ b/tools/aapt2/xml/XmlDom.h @@ -22,10 +22,11 @@ #include <string> #include <vector> +#include "androidfw/StringPiece.h" + #include "Diagnostics.h" #include "Resource.h" #include "ResourceValues.h" -#include "util/StringPiece.h" #include "util/Util.h" #include "xml/XmlUtil.h" @@ -100,13 +101,13 @@ class Element : public BaseNode<Element> { std::string name; std::vector<Attribute> attributes; - Attribute* FindAttribute(const StringPiece& ns, const StringPiece& name); - xml::Element* FindChild(const StringPiece& ns, const StringPiece& name); - xml::Element* FindChildWithAttribute(const StringPiece& ns, - const StringPiece& name, - const StringPiece& attr_ns, - const StringPiece& attr_name, - const StringPiece& attr_value); + Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name); + xml::Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name); + xml::Element* FindChildWithAttribute(const android::StringPiece& ns, + const android::StringPiece& name, + const android::StringPiece& attr_ns, + const android::StringPiece& attr_name, + const android::StringPiece& attr_value); std::vector<xml::Element*> GetChildElements(); std::unique_ptr<Node> Clone() override; }; @@ -190,8 +191,7 @@ class PackageAwareVisitor : public Visitor, public IPackageDeclStack { void Visit(Namespace* ns) override; Maybe<ExtractedPackage> TransformPackageAlias( - const StringPiece& alias, - const StringPiece& local_package) const override; + const android::StringPiece& alias, const android::StringPiece& local_package) const override; private: struct PackageDecl { diff --git a/tools/aapt2/xml/XmlPullParser.cpp b/tools/aapt2/xml/XmlPullParser.cpp index e59fa86788cd..c2a9c8283a6d 100644 --- a/tools/aapt2/xml/XmlPullParser.cpp +++ b/tools/aapt2/xml/XmlPullParser.cpp @@ -22,6 +22,8 @@ #include "xml/XmlPullParser.h" #include "xml/XmlUtil.h" +using android::StringPiece; + namespace aapt { namespace xml { @@ -136,15 +138,14 @@ const std::string& XmlPullParser::namespace_uri() const { Maybe<ExtractedPackage> XmlPullParser::TransformPackageAlias( const StringPiece& alias, const StringPiece& local_package) const { if (alias.empty()) { - return ExtractedPackage{local_package.ToString(), false /* private */}; + return ExtractedPackage{local_package.to_string(), false /* private */}; } const auto end_iter = package_aliases_.rend(); for (auto iter = package_aliases_.rbegin(); iter != end_iter; ++iter) { if (alias == iter->prefix) { if (iter->package.package.empty()) { - return ExtractedPackage{local_package.ToString(), - iter->package.private_namespace}; + return ExtractedPackage{local_package.to_string(), iter->package.private_namespace}; } return iter->package; } @@ -188,19 +189,18 @@ size_t XmlPullParser::attribute_count() const { /** * Extracts the namespace and name of an expanded element or attribute name. */ -static void SplitName(const char* name, std::string& out_ns, - std::string& out_name) { +static void SplitName(const char* name, std::string* out_ns, std::string* out_name) { const char* p = name; while (*p != 0 && *p != kXmlNamespaceSep) { p++; } if (*p == 0) { - out_ns = std::string(); - out_name = name; + out_ns->clear(); + out_name->assign(name); } else { - out_ns = StringPiece(name, (p - name)).ToString(); - out_name = p + 1; + out_ns->assign(name, (p - name)); + out_name->assign(p + 1); } } @@ -224,11 +224,11 @@ void XMLCALL XmlPullParser::StartElementHandler(void* user_data, EventData data = {Event::kStartElement, XML_GetCurrentLineNumber(parser->parser_), parser->depth_++}; - SplitName(name, data.data1, data.data2); + SplitName(name, &data.data1, &data.data2); while (*attrs) { Attribute attribute; - SplitName(*attrs++, attribute.namespace_uri, attribute.name); + SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); attribute.value = *attrs++; // Insert in sorted order. @@ -245,9 +245,8 @@ void XMLCALL XmlPullParser::CharacterDataHandler(void* user_data, const char* s, int len) { XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data); - parser->event_queue_.push( - EventData{Event::kText, XML_GetCurrentLineNumber(parser->parser_), - parser->depth_, StringPiece(s, len).ToString()}); + parser->event_queue_.push(EventData{Event::kText, XML_GetCurrentLineNumber(parser->parser_), + parser->depth_, std::string(s, len)}); } void XMLCALL XmlPullParser::EndElementHandler(void* user_data, @@ -257,7 +256,7 @@ void XMLCALL XmlPullParser::EndElementHandler(void* user_data, EventData data = {Event::kEndElement, XML_GetCurrentLineNumber(parser->parser_), --(parser->depth_)}; - SplitName(name, data.data1, data.data2); + SplitName(name, &data.data1, &data.data2); // Move the data into the queue (no copy). parser->event_queue_.push(std::move(data)); diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h index ff58d604e35e..cdeeefd13976 100644 --- a/tools/aapt2/xml/XmlPullParser.h +++ b/tools/aapt2/xml/XmlPullParser.h @@ -28,11 +28,11 @@ #include <vector> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "Resource.h" #include "process/IResourceTableConsumer.h" #include "util/Maybe.h" -#include "util/StringPiece.h" #include "xml/XmlUtil.h" namespace aapt { @@ -119,8 +119,7 @@ class XmlPullParser : public IPackageDeclStack { * 'package' will be set to 'defaultPackage'. */ Maybe<ExtractedPackage> TransformPackageAlias( - const StringPiece& alias, - const StringPiece& local_package) const override; + const android::StringPiece& alias, const android::StringPiece& local_package) const override; // // Remaining methods are for retrieving information about attributes @@ -146,8 +145,7 @@ class XmlPullParser : public IPackageDeclStack { const_iterator begin_attributes() const; const_iterator end_attributes() const; size_t attribute_count() const; - const_iterator FindAttribute(StringPiece namespace_uri, - StringPiece name) const; + const_iterator FindAttribute(android::StringPiece namespace_uri, android::StringPiece name) const; private: DISALLOW_COPY_AND_ASSIGN(XmlPullParser); @@ -190,16 +188,16 @@ class XmlPullParser : public IPackageDeclStack { /** * Finds the attribute in the current element within the global namespace. */ -Maybe<StringPiece> FindAttribute(const XmlPullParser* parser, - const StringPiece& name); +Maybe<android::StringPiece> FindAttribute(const XmlPullParser* parser, + const android::StringPiece& name); /** * Finds the attribute in the current element within the global namespace. The * attribute's value * must not be the empty string. */ -Maybe<StringPiece> FindNonEmptyAttribute(const XmlPullParser* parser, - const StringPiece& name); +Maybe<android::StringPiece> FindNonEmptyAttribute(const XmlPullParser* parser, + const android::StringPiece& name); // // Implementation @@ -299,13 +297,13 @@ inline bool XmlPullParser::Attribute::operator!=(const Attribute& rhs) const { } inline XmlPullParser::const_iterator XmlPullParser::FindAttribute( - StringPiece namespace_uri, StringPiece name) const { + android::StringPiece namespace_uri, android::StringPiece name) const { const auto end_iter = end_attributes(); const auto iter = std::lower_bound( begin_attributes(), end_iter, - std::pair<StringPiece, StringPiece>(namespace_uri, name), + std::pair<android::StringPiece, android::StringPiece>(namespace_uri, name), [](const Attribute& attr, - const std::pair<StringPiece, StringPiece>& rhs) -> bool { + const std::pair<android::StringPiece, android::StringPiece>& rhs) -> bool { int cmp = attr.namespace_uri.compare( 0, attr.namespace_uri.size(), rhs.first.data(), rhs.first.size()); if (cmp < 0) return true; diff --git a/tools/aapt2/xml/XmlPullParser_test.cpp b/tools/aapt2/xml/XmlPullParser_test.cpp index 4f18cd218cd9..1cce4850cac5 100644 --- a/tools/aapt2/xml/XmlPullParser_test.cpp +++ b/tools/aapt2/xml/XmlPullParser_test.cpp @@ -18,8 +18,11 @@ #include <sstream> +#include "androidfw/StringPiece.h" + #include "test/Test.h" -#include "util/StringPiece.h" + +using android::StringPiece; namespace aapt { diff --git a/tools/aapt2/xml/XmlUtil.cpp b/tools/aapt2/xml/XmlUtil.cpp index d00f7f2fe0aa..fb8cee8b5634 100644 --- a/tools/aapt2/xml/XmlUtil.cpp +++ b/tools/aapt2/xml/XmlUtil.cpp @@ -21,6 +21,8 @@ #include "util/Maybe.h" #include "util/Util.h" +using android::StringPiece; + namespace aapt { namespace xml { @@ -42,7 +44,7 @@ Maybe<ExtractedPackage> ExtractPackageFromNamespace( if (package.empty()) { return {}; } - return ExtractedPackage{package.ToString(), false /* is_private */}; + return ExtractedPackage{package.to_string(), false /* is_private */}; } else if (util::StartsWith(namespace_uri, kSchemaPrivatePrefix)) { StringPiece schema_prefix = kSchemaPrivatePrefix; @@ -52,7 +54,7 @@ Maybe<ExtractedPackage> ExtractPackageFromNamespace( if (package.empty()) { return {}; } - return ExtractedPackage{package.ToString(), true /* is_private */}; + return ExtractedPackage{package.to_string(), true /* is_private */}; } else if (namespace_uri == kSchemaAuto) { return ExtractedPackage{std::string(), true /* is_private */}; diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h index 536540162d07..1650ac2124ac 100644 --- a/tools/aapt2/xml/XmlUtil.h +++ b/tools/aapt2/xml/XmlUtil.h @@ -74,7 +74,7 @@ Maybe<ExtractedPackage> ExtractPackageFromNamespace( * * http://schemas.android.com/apk/prv/res/<package> */ -std::string BuildPackageNamespace(const StringPiece& package, +std::string BuildPackageNamespace(const android::StringPiece& package, bool private_reference = false); /** @@ -90,7 +90,7 @@ struct IPackageDeclStack { * package declaration. */ virtual Maybe<ExtractedPackage> TransformPackageAlias( - const StringPiece& alias, const StringPiece& local_package) const = 0; + const android::StringPiece& alias, const android::StringPiece& local_package) const = 0; }; /** @@ -100,8 +100,7 @@ struct IPackageDeclStack { * the namespace of the package declaration was private. */ void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack, - const StringPiece& local_package, - Reference* in_ref); + const android::StringPiece& local_package, Reference* in_ref); } // namespace xml } // namespace aapt diff --git a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java index b10ec9fec2ad..ce2aec790119 100644 --- a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java +++ b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java @@ -25,7 +25,6 @@ import com.android.layoutlib.bridge.impl.RenderSessionImpl; import android.os.Handler; import android.os.Handler_Delegate; -import android.os.Handler_Delegate.IHandlerCallback; import android.os.Message; import java.util.PriorityQueue; diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java index c3d4cef61b35..e0f8e1c33bc6 100644 --- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java +++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java @@ -21,6 +21,7 @@ import com.android.ide.common.rendering.api.ArrayResourceValue; import com.android.ide.common.rendering.api.DensityBasedResourceValue; import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.common.rendering.api.LayoutlibCallback; +import com.android.ide.common.rendering.api.PluralsResourceValue; import com.android.ide.common.rendering.api.RenderResources; import com.android.ide.common.rendering.api.ResourceValue; import com.android.layoutlib.bridge.Bridge; @@ -43,6 +44,7 @@ import android.annotation.Nullable; import android.content.res.Resources.NotFoundException; import android.content.res.Resources.Theme; import android.graphics.drawable.Drawable; +import android.icu.text.PluralRules; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.LruCache; @@ -405,9 +407,6 @@ public class Resources_Delegate { rv = resources.mContext.getRenderResources().resolveResValue(rv); if (rv != null) { return rv.getValue(); - } else { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, - "Unable to resolve resource " + ref, null); } } // Not a reference. @@ -738,6 +737,48 @@ public class Resources_Delegate { } @LayoutlibDelegate + static String getQuantityString(Resources resources, int id, int quantity) throws + NotFoundException { + Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); + + if (value != null) { + if (value.getSecond() instanceof PluralsResourceValue) { + PluralsResourceValue pluralsResourceValue = (PluralsResourceValue) value.getSecond(); + PluralRules pluralRules = PluralRules.forLocale(resources.getConfiguration().getLocales() + .get(0)); + String strValue = pluralsResourceValue.getValue(pluralRules.select(quantity)); + if (strValue == null) { + strValue = pluralsResourceValue.getValue(PluralRules.KEYWORD_OTHER); + } + + return strValue; + } + else { + return value.getSecond().getValue(); + } + } + + // id was not found or not resolved. Throw a NotFoundException. + throwException(resources, id); + + // this is not used since the method above always throws + return null; + } + + @LayoutlibDelegate + static String getQuantityString(Resources resources, int id, int quantity, Object... formatArgs) + throws NotFoundException { + String raw = getQuantityString(resources, id, quantity); + return String.format(resources.getConfiguration().getLocales().get(0), raw, formatArgs); + } + + @LayoutlibDelegate + static CharSequence getQuantityText(Resources resources, int id, int quantity) throws + NotFoundException { + return getQuantityString(resources, id, quantity); + } + + @LayoutlibDelegate static void getValue(Resources resources, int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException { Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag); diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java index 21f36ceb0c1b..c6827a3c9c5f 100644 --- a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java +++ b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java @@ -30,6 +30,7 @@ import java.awt.Graphics2D; import java.awt.Toolkit; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.LinkedList; @@ -41,6 +42,7 @@ import java.util.List; */ @SuppressWarnings("deprecation") public class BidiRenderer { + private static String JAVA_VENDOR = System.getProperty("java.vendor"); private static class ScriptRun { int start; @@ -221,9 +223,16 @@ public class BidiRenderer { frc = mGraphics.getFontRenderContext(); } else { frc = Toolkit.getDefaultToolkit().getFontMetrics(font).getFontRenderContext(); + // Metrics obtained this way don't have anti-aliasing set. So, // we create a new FontRenderContext with anti-aliasing set. - frc = new FontRenderContext(font.getTransform(), mPaint.isAntiAliased(), frc.usesFractionalMetrics()); + AffineTransform transform = font.getTransform(); + if (mPaint.isAntiAliased() && + // Workaround for http://b.android.com/211659 + (transform.getScaleX() <= 9.9 || + !"JetBrains s.r.o".equals(JAVA_VENDOR))) { + frc = new FontRenderContext(transform, true, frc.usesFractionalMetrics()); + } } GlyphVector gv = font.layoutGlyphVector(frc, mText, start, limit, flag); int ng = gv.getNumGlyphs(); diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index 43a0ff5a23dc..c599e9d6d6bc 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -20,24 +20,14 @@ import com.android.ide.common.rendering.api.LayoutLog; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.layoutlib.bridge.impl.GcSnapshot; -import com.android.layoutlib.bridge.impl.PorterDuffUtility; -import com.android.ninepatch.NinePatchChunk; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import android.annotation.Nullable; import android.graphics.Bitmap.Config; -import android.text.TextUtils; -import java.awt.Color; -import java.awt.Composite; import java.awt.Graphics2D; import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; import java.awt.geom.AffineTransform; -import java.awt.geom.Arc2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; import libcore.util.NativeAllocationRegistry_Delegate; @@ -401,23 +391,6 @@ public final class Canvas_Delegate extends BaseCanvas_Delegate { } @LayoutlibDelegate - public static boolean nClipRegion(long nativeCanvas, - long nativeRegion, - int regionOp) { - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return true; - } - - Region_Delegate region = Region_Delegate.getDelegate(nativeRegion); - if (region == null) { - return true; - } - - return canvasDelegate.mSnapshot.clip(region.getJavaArea(), regionOp); - } - - @LayoutlibDelegate public static void nSetDrawFilter(long nativeCanvas, long nativeFilter) { Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas); if (canvasDelegate == null) { diff --git a/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java b/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java new file mode 100644 index 000000000000..4a5ea9b5bb65 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 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. + */ + +package android.view; + +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +import android.content.Context; +import android.content.res.Resources; + +public class PointerIcon_Delegate { + + @LayoutlibDelegate + /*package*/ static void loadResource(PointerIcon icon, Context context, Resources resources, + int resourceId) { + // HACK: This bypasses the problem of having an enum resolved as a resourceId. + // PointerIcon would not be displayed by layoutlib anyway, so we always return the null + // icon. + } +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java index 3ac1889dbe72..77b131fa9d86 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java @@ -76,6 +76,23 @@ public class BridgeRenderSession extends RenderSession { } @Override + public Result measure(long timeout) { + try { + Bridge.prepareThread(); + mLastResult = mSession.acquire(timeout); + if (mLastResult.isSuccess()) { + mSession.invalidateRenderingSize(); + mLastResult = mSession.measure(); + } + } finally { + mSession.release(); + Bridge.cleanupThread(); + } + + return mLastResult; + } + + @Override public Result render(long timeout, boolean forceMeasure) { try { Bridge.prepareThread(); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 1b3b563fb51e..68680d5d8d9c 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -40,6 +40,7 @@ import org.xmlpull.v1.XmlPullParserException; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.Notification; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -66,7 +67,6 @@ import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.net.Uri; -import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -104,6 +104,7 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE; /** @@ -113,6 +114,28 @@ import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_AP public final class BridgeContext extends Context { private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; + private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2); + private static final Map<String, ResourceValue> FRAMEWORK_REPLACE_VALUES = new HashMap<>(3); + + static { + FRAMEWORK_PATCHED_VALUES.put("animateFirstView", new ResourceValue( + ResourceType.BOOL, "animateFirstView", "false", false)); + FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges", + new ResourceValue(ResourceType.BOOL, "animateLayoutChanges", "false", false)); + + + FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout", + new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionItemLayout", + "text_edit_suggestion_item", true)); + FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout", + new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionContainerLayout", + "text_edit_suggestion_container", true)); + FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle", + new ResourceValue(ResourceType.STYLE, "textEditSuggestionHighlightStyle", + "TextAppearance.Holo.SuggestionHighlight", true)); + + } + /** The map adds cookies to each view so that IDE can link xml tags to views. */ private final HashMap<View, Object> mViewKeyMap = new HashMap<>(); /** @@ -312,7 +335,7 @@ public final class BridgeContext extends Context { * Returns the current parser at the top the of the stack. * @return a parser or null. */ - public BridgeXmlBlockParser getCurrentParser() { + private BridgeXmlBlockParser getCurrentParser() { return mParserStack.peek(); } @@ -406,7 +429,8 @@ public final class BridgeContext extends Context { } public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent, - boolean attachToRoot, boolean skipCallbackParser) { + @SuppressWarnings("SameParameterValue") boolean attachToRoot, + boolean skipCallbackParser) { boolean isPlatformLayout = resource.isFramework(); if (!isPlatformLayout && !skipCallbackParser) { @@ -711,11 +735,7 @@ public final class BridgeContext extends Context { Object key = parser.getViewCookie(); if (key != null) { - defaultPropMap = mDefaultPropMaps.get(key); - if (defaultPropMap == null) { - defaultPropMap = new PropertiesMap(); - mDefaultPropMaps.put(key, defaultPropMap); - } + defaultPropMap = mDefaultPropMaps.computeIfAbsent(key, k -> new PropertiesMap()); } } else if (set instanceof BridgeLayoutParamsMapAttributes) { @@ -909,6 +929,16 @@ public final class BridgeContext extends Context { // if there's no direct value for this attribute in the XML, we look for default // values in the widget defStyle, and then in the theme. if (value == null) { + if (frameworkAttr) { + // For some framework values, layoutlib patches the actual value in the + // theme when it helps to improve the final preview. In most cases + // we just disable animations. + ResourceValue patchedValue = FRAMEWORK_PATCHED_VALUES.get(attrName); + if (patchedValue != null) { + defaultValue = patchedValue; + } + } + // if we found a value, we make sure this doesn't reference another value. // So we resolve it. if (defaultValue != null) { @@ -916,16 +946,21 @@ public final class BridgeContext extends Context { // exist, we should log a warning and omit it. String val = defaultValue.getValue(); if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) { - if (!attrName.equals(RTL_ATTRS.get(val)) || - getApplicationInfo().targetSdkVersion < - VERSION_CODES.JELLY_BEAN_MR1) { + // Because we always use the latest framework code, some resources might + // fail to resolve when using old themes (they haven't been backported). + // Since this is an artifact caused by us using always the latest + // code, we check for some of those values and replace them here. + defaultValue = FRAMEWORK_REPLACE_VALUES.get(attrName); + + if (defaultValue == null && + (getApplicationInfo().targetSdkVersion < JELLY_BEAN_MR1 || + !attrName.equals(RTL_ATTRS.get(val)))) { // Only log a warning if the referenced value isn't one of the RTL // attributes, or the app targets old API. Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, String.format("Failed to find '%s' in current theme.", val), val); } - defaultValue = null; } } @@ -1786,6 +1821,13 @@ public final class BridgeContext extends Context { } @Override + public ComponentName startServiceInForeground(Intent service, + int id, Notification notification) { + // pass + return null; + } + + @Override public boolean stopService(Intent arg0) { // pass return false; @@ -1798,6 +1840,13 @@ public final class BridgeContext extends Context { } @Override + public ComponentName startServiceInForegroundAsUser(Intent service, + int id, Notification notification, UserHandle user) { + // pass + return null; + } + + @Override public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { // pass return false; @@ -1944,7 +1993,7 @@ public final class BridgeContext extends Context { Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache; - public TypedArrayCache() { + private TypedArrayCache() { mCache = new IdentityHashMap<>(); } @@ -1965,17 +2014,9 @@ public final class BridgeContext extends Context { public void put(int[] attrs, List<StyleResourceValue> themes, int resId, Pair<BridgeTypedArray, PropertiesMap> value) { Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>> - cacheFromThemes = mCache.get(attrs); - if (cacheFromThemes == null) { - cacheFromThemes = new HashMap<>(); - mCache.put(attrs, cacheFromThemes); - } + cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>()); Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId = - cacheFromThemes.get(themes); - if (cacheFromResId == null) { - cacheFromResId = new HashMap<>(); - cacheFromThemes.put(themes, cacheFromResId); - } + cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>()); cacheFromResId.put(resId, value); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java index 8835b5845175..d3ec9e271ba4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java @@ -42,14 +42,15 @@ import android.content.pm.PermissionInfo; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.SharedLibraryInfo; import android.content.pm.VerifierDeviceIdentity; +import android.content.pm.VersionedPackage; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Handler; -import android.os.RemoteException; import android.os.UserHandle; import android.os.storage.VolumeInfo; import java.util.List; @@ -71,6 +72,23 @@ public class BridgePackageManager extends PackageManager { } @Override + public PackageInfo getPackageInfo(VersionedPackage versionedPackage, + @PackageInfoFlags int flags) throws NameNotFoundException { + return null; + } + + @Override + public List<SharedLibraryInfo> getSharedLibraries(@InstallFlags int flags) { + return null; + } + + @Override + public List<SharedLibraryInfo> getSharedLibrariesAsUser(@InstallFlags int flags, + int userId) { + return null; + } + + @Override public String[] currentToCanonicalPackageNames(String[] names) { return new String[0]; } @@ -868,4 +886,9 @@ public class BridgePackageManager extends PackageManager { public boolean isPackageAvailable(String packageName) { return false; } + + @Override + public int getInstallReason(String packageName, UserHandle user) { + return INSTALL_REASON_UNKNOWN; + } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java index 30317012fb52..d7d16cf6d764 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java @@ -17,6 +17,7 @@ package com.android.layoutlib.bridge.android.view; import android.util.DisplayMetrics; import android.view.Display; +import android.view.Display.Mode; import android.view.DisplayAdjustments; import android.view.DisplayInfo; import android.view.View; @@ -33,6 +34,9 @@ public class WindowManagerImpl implements WindowManager { DisplayInfo info = new DisplayInfo(); info.logicalHeight = mMetrics.heightPixels; info.logicalWidth = mMetrics.widthPixels; + info.supportedModes = new Mode[] { + new Mode(0, mMetrics.widthPixels, mMetrics.heightPixels, 60f) + }; mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java index 09937bc5ac38..5386b1758682 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java @@ -74,8 +74,8 @@ public class Config { } public static String getTime(int platformVersion) { - if (isGreaterOrEqual(platformVersion, M)) { - return "6:00"; + if (isGreaterOrEqual(platformVersion, N)) { + return "7:00"; } if (platformVersion < GINGERBREAD) { return "2:20"; @@ -98,6 +98,9 @@ public class Config { if (platformVersion < M) { return "5:10"; } + if (platformVersion < N) { + return "6:00"; + } // Should never happen. return "4:04"; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index 91a783ae7efc..85fe2a450e4f 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -208,7 +208,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { /** * Measures the the current layout if needed (see {@link #invalidateRenderingSize}). */ - private void measure(@NonNull SessionParams params) { + private void measureLayout(@NonNull SessionParams params) { // only do the screen measure when needed. if (mMeasuredScreenWidth != -1) { return; @@ -353,7 +353,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { setActiveToolbar(view, context, params); - measure(params); + measureLayout(params); measureView(mViewRoot, null /*measuredView*/, mMeasuredScreenWidth, MeasureSpec.EXACTLY, mMeasuredScreenHeight, MeasureSpec.EXACTLY); @@ -385,13 +385,10 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { } /** - * Renders the given view hierarchy to the passed canvas and returns the result of the render - * operation. - * @param canvas an optional canvas to render the views to. If null, only the measure and - * layout steps will be executed. + * Runs a layout pass for the given view root */ - private static Result render(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot, - @Nullable Canvas canvas, int width, int height) { + private static void doLayout(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot, + int width, int height) { // measure again with the size we need // This must always be done before the call to layout measureView(viewRoot, null /*measuredView*/, @@ -401,7 +398,16 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { // now do the layout. viewRoot.layout(0, 0, width, height); handleScrolling(context, viewRoot); + } + /** + * Renders the given view hierarchy to the passed canvas and returns the result of the render + * operation. + * @param canvas an optional canvas to render the views to. If null, only the measure and + * layout steps will be executed. + */ + private static Result renderAndBuildResult(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot, + @Nullable Canvas canvas, int width, int height) { if (canvas == null) { return SUCCESS.createResult(); } @@ -428,6 +434,40 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { * @see RenderSession#render(long) */ public Result render(boolean freshRender) { + return renderAndBuildResult(freshRender, false); + } + + /** + * Measures the layout + * <p> + * {@link #acquire(long)} must have been called before this. + * + * @throws IllegalStateException if the current context is different than the one owned by + * the scene, or if {@link #acquire(long)} was not called. + * + * @see SessionParams#getRenderingMode() + * @see RenderSession#render(long) + */ + public Result measure() { + return renderAndBuildResult(false, true); + } + + /** + * Renders the scene. + * <p> + * {@link #acquire(long)} must have been called before this. + * + * @param freshRender whether the render is a new one and should erase the existing bitmap (in + * the case where bitmaps are reused). This is typically needed when not playing + * animations.) + * + * @throws IllegalStateException if the current context is different than the one owned by + * the scene, or if {@link #acquire(long)} was not called. + * + * @see SessionParams#getRenderingMode() + * @see RenderSession#render(long) + */ + private Result renderAndBuildResult(boolean freshRender, boolean onlyMeasure) { checkLock(); SessionParams params = getParams(); @@ -437,14 +477,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { return ERROR_NOT_INFLATED.createResult(); } - measure(params); + measureLayout(params); HardwareConfig hardwareConfig = params.getHardwareConfig(); Result renderResult = SUCCESS.createResult(); - if (params.isLayoutOnly()) { + if (onlyMeasure) { // delete the canvas and image to reset them on the next full rendering mImage = null; mCanvas = null; + doLayout(getContext(), mViewRoot, mMeasuredScreenWidth, mMeasuredScreenHeight); } else { // draw the views // create the BufferedImage into which the layout will be rendered. @@ -505,11 +546,12 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { gc.dispose(); } + doLayout(getContext(), mViewRoot, mMeasuredScreenWidth, mMeasuredScreenHeight); if (mElapsedFrameTimeNanos >= 0) { long initialTime = System_Delegate.nanoTime(); if (!mFirstFrameExecuted) { // We need to run an initial draw call to initialize the animations - render(getContext(), mViewRoot, NOP_CANVAS, mMeasuredScreenWidth, mMeasuredScreenHeight); + renderAndBuildResult(getContext(), mViewRoot, NOP_CANVAS, mMeasuredScreenWidth, mMeasuredScreenHeight); // The first frame will initialize the animations Choreographer_Delegate.doFrame(initialTime); @@ -518,7 +560,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { // Second frame will move the animations Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos); } - renderResult = render(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth, + renderResult = renderAndBuildResult(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth, mMeasuredScreenHeight); } diff --git a/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java b/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java index 6246ec1b8661..04fabc242454 100644 --- a/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java +++ b/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java @@ -52,9 +52,15 @@ public class NativeAllocationRegistry_Delegate { @LayoutlibDelegate /*package*/ static void applyFreeFunction(long freeFunction, long nativePtr) { - NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction); - if (delegate != null) { - delegate.mFinalizer.free(nativePtr); + // This method MIGHT run in the context of the finalizer thread. If the delegate method + // crashes, it could bring down the VM. That's why we catch all the exceptions and ignore + // them. + try { + NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction); + if (delegate != null) { + delegate.mFinalizer.free(nativePtr); + } + } catch (Throwable ignore) { } } diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk index 9ee416a3b4ca..33d55dea6f79 100644 --- a/tools/layoutlib/bridge/tests/Android.mk +++ b/tools/layoutlib/bridge/tests/Android.mk @@ -30,7 +30,8 @@ LOCAL_JAVA_LIBRARIES := layoutlib \ layoutlib_api-prebuilt \ tools-common-prebuilt \ sdk-common \ - junit-host + junit-host \ + guavalib include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png Binary files differindex f274dbfbbdd6..199ea60e0e24 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png Binary files differindex ef95f83f8b24..89ff5db8f40b 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png Binary files differindex 6eeb82c93735..1f4405d49ffc 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png Binary files differindex 336f9d8b4798..c3bd70837ff1 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png Binary files differnew file mode 100644 index 000000000000..eb431b0280da --- /dev/null +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png Binary files differindex 290018b6497d..b75671990ce6 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml index adb58a322abb..05a3665deab1 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml @@ -28,7 +28,8 @@ android:layout_alignParentStart="true" android:layout_below="@id/frameLayout" android:text="Large Text" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceLarge" + android:pointerIcon="hand" /> <TextView android:id="@id/textView3" diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/arrays.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/arrays.xml index f6e14d2b83b9..5f58d390bf32 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/arrays.xml +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/arrays.xml @@ -17,6 +17,7 @@ <!-- theme ref in android NS. value = @string/candidates_style = <u>candidates</u> --> <item>?android:attr/candidatesTextStyleSpans</item> <item>@android:string/unknownName</item> <!-- value = Unknown --> + <item>?EC</item> </string-array> <!-- resources that the above array can refer to --> diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml index c8a5fec71f09..debe33bea72e 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml @@ -3,7 +3,6 @@ <!-- Base application theme. --> <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar"> <item name="myattr">@integer/ten</item> - <item name="android:animateFirstView">false</item> </style> </resources> diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java index cdcae89097b5..ded52a762709 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2016 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. @@ -16,815 +16,23 @@ package com.android.layoutlib.bridge.intensive; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.ide.common.rendering.api.SessionParams.RenderingMode; -import com.android.ide.common.rendering.api.ViewInfo; -import com.android.ide.common.resources.FrameworkResources; -import com.android.ide.common.resources.ResourceItem; -import com.android.ide.common.resources.ResourceRepository; -import com.android.ide.common.resources.ResourceResolver; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.io.FolderWrapper; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.RenderParamsFlags; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.impl.RenderAction; -import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator; -import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback; -import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser; -import com.android.resources.Density; -import com.android.resources.Navigation; -import com.android.resources.ResourceType; -import com.android.resources.ScreenOrientation; -import com.android.tools.layoutlib.java.System_Delegate; -import com.android.utils.ILogger; +import com.android.layoutlib.bridge.TestDelegates; +import com.android.layoutlib.bridge.android.BridgeXmlBlockParserTest; +import com.android.layoutlib.bridge.impl.LayoutParserWrapperTest; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.res.AssetManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.util.DisplayMetrics; - -import java.io.File; -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; - -import com.google.android.collect.Lists; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import android.graphics.Matrix_DelegateTest; /** - * This is a set of tests that loads all the framework resources and a project checked in this - * test's resources. The main dependencies - * are: - * 1. Fonts directory. - * 2. Framework Resources. - * 3. App resources. - * 4. build.prop file - * - * These are configured by two variables set in the system properties. - * - * 1. platform.dir: This is the directory for the current platform in the built SDK - * (.../sdk/platforms/android-<version>). - * - * The fonts are platform.dir/data/fonts. - * The Framework resources are platform.dir/data/res. - * build.prop is at platform.dir/build.prop. - * - * 2. test_res.dir: This is the directory for the resources of the test. If not specified, this - * falls back to getClass().getProtectionDomain().getCodeSource().getLocation() - * - * The app resources are at: test_res.dir/testApp/MyApplication/app/src/main/res + * Suite used by the layoutlib build system */ +@RunWith(Suite.class) +@SuiteClasses({ + RenderTests.class, LayoutParserWrapperTest.class, BridgeXmlBlockParserTest.class, + Matrix_DelegateTest.class, TestDelegates.class +}) public class Main { - - private static final String PLATFORM_DIR_PROPERTY = "platform.dir"; - private static final String RESOURCE_DIR_PROPERTY = "test_res.dir"; - - private static final String PLATFORM_DIR; - private static final String TEST_RES_DIR; - /** Location of the app to test inside {@link #TEST_RES_DIR}*/ - private static final String APP_TEST_DIR = "testApp/MyApplication"; - /** Location of the app's res dir inside {@link #TEST_RES_DIR}*/ - private static final String APP_TEST_RES = APP_TEST_DIR + "/src/main/res"; - private static final String APP_CLASSES_LOCATION = - APP_TEST_DIR + "/build/intermediates/classes/debug/"; - - private static LayoutLog sLayoutLibLog; - private static FrameworkResources sFrameworkRepo; - private static ResourceRepository sProjectResources; - private static ILogger sLogger; - private static Bridge sBridge; - - /** List of log messages generated by a render call. It can be used to find specific errors */ - private static ArrayList<String> sRenderMessages = Lists.newArrayList(); - - // Default class loader with access to the app classes - private ClassLoader mDefaultClassLoader = - new ModuleClassLoader(APP_CLASSES_LOCATION, getClass().getClassLoader()); - - @Rule - public TestWatcher sRenderMessageWatcher = new TestWatcher() { - @Override - protected void succeeded(Description description) { - // We only check error messages if the rest of the test case was successful. - if (!sRenderMessages.isEmpty()) { - fail(description.getMethodName() + " render error message: " + sRenderMessages.get - (0)); - } - } - }; - - static { - // Test that System Properties are properly set. - PLATFORM_DIR = getPlatformDir(); - if (PLATFORM_DIR == null) { - fail(String.format("System Property %1$s not properly set. The value is %2$s", - PLATFORM_DIR_PROPERTY, System.getProperty(PLATFORM_DIR_PROPERTY))); - } - - TEST_RES_DIR = getTestResDir(); - if (TEST_RES_DIR == null) { - fail(String.format("System property %1$s.dir not properly set. The value is %2$s", - RESOURCE_DIR_PROPERTY, System.getProperty(RESOURCE_DIR_PROPERTY))); - } - } - - private static String getPlatformDir() { - String platformDir = System.getProperty(PLATFORM_DIR_PROPERTY); - if (platformDir != null && !platformDir.isEmpty() && new File(platformDir).isDirectory()) { - return platformDir; - } - // System Property not set. Try to find the directory in the build directory. - String androidHostOut = System.getenv("ANDROID_HOST_OUT"); - if (androidHostOut != null) { - platformDir = getPlatformDirFromHostOut(new File(androidHostOut)); - if (platformDir != null) { - return platformDir; - } - } - String workingDirString = System.getProperty("user.dir"); - File workingDir = new File(workingDirString); - // Test if workingDir is android checkout root. - platformDir = getPlatformDirFromRoot(workingDir); - if (platformDir != null) { - return platformDir; - } - - // Test if workingDir is platform/frameworks/base/tools/layoutlib/bridge. - File currentDir = workingDir; - if (currentDir.getName().equalsIgnoreCase("bridge")) { - currentDir = currentDir.getParentFile(); - } - // Test if currentDir is platform/frameworks/base/tools/layoutlib. That is, root should be - // workingDir/../../../../ (4 levels up) - for (int i = 0; i < 4; i++) { - if (currentDir != null) { - currentDir = currentDir.getParentFile(); - } - } - return currentDir == null ? null : getPlatformDirFromRoot(currentDir); - } - - private static String getPlatformDirFromRoot(File root) { - if (!root.isDirectory()) { - return null; - } - File out = new File(root, "out"); - if (!out.isDirectory()) { - return null; - } - File host = new File(out, "host"); - if (!host.isDirectory()) { - return null; - } - File[] hosts = host.listFiles(path -> path.isDirectory() && - (path.getName().startsWith("linux-") || path.getName().startsWith("darwin-"))); - assert hosts != null; - for (File hostOut : hosts) { - String platformDir = getPlatformDirFromHostOut(hostOut); - if (platformDir != null) { - return platformDir; - } - } - return null; - } - - private static String getPlatformDirFromHostOut(File out) { - if (!out.isDirectory()) { - return null; - } - File sdkDir = new File(out, "sdk"); - if (!sdkDir.isDirectory()) { - return null; - } - File[] sdkDirs = sdkDir.listFiles(path -> { - // We need to search for $TARGET_PRODUCT (usually, sdk_phone_armv7) - return path.isDirectory() && path.getName().startsWith("sdk"); - }); - assert sdkDirs != null; - for (File dir : sdkDirs) { - String platformDir = getPlatformDirFromHostOutSdkSdk(dir); - if (platformDir != null) { - return platformDir; - } - } - return null; - } - - private static String getPlatformDirFromHostOutSdkSdk(File sdkDir) { - File[] possibleSdks = sdkDir.listFiles( - path -> path.isDirectory() && path.getName().contains("android-sdk")); - assert possibleSdks != null; - for (File possibleSdk : possibleSdks) { - File platformsDir = new File(possibleSdk, "platforms"); - File[] platforms = platformsDir.listFiles( - path -> path.isDirectory() && path.getName().startsWith("android-")); - if (platforms == null || platforms.length == 0) { - continue; - } - Arrays.sort(platforms, (o1, o2) -> { - final int MAX_VALUE = 1000; - String suffix1 = o1.getName().substring("android-".length()); - String suffix2 = o2.getName().substring("android-".length()); - int suff1, suff2; - try { - suff1 = Integer.parseInt(suffix1); - } catch (NumberFormatException e) { - suff1 = MAX_VALUE; - } - try { - suff2 = Integer.parseInt(suffix2); - } catch (NumberFormatException e) { - suff2 = MAX_VALUE; - } - if (suff1 != MAX_VALUE || suff2 != MAX_VALUE) { - return suff2 - suff1; - } - return suffix2.compareTo(suffix1); - }); - return platforms[0].getAbsolutePath(); - } - return null; - } - - private static String getTestResDir() { - String resourceDir = System.getProperty(RESOURCE_DIR_PROPERTY); - if (resourceDir != null && !resourceDir.isEmpty() && new File(resourceDir).isDirectory()) { - return resourceDir; - } - // TEST_RES_DIR not explicitly set. Fallback to the class's source location. - try { - URL location = Main.class.getProtectionDomain().getCodeSource().getLocation(); - return new File(location.getPath()).exists() ? location.getPath() : null; - } catch (NullPointerException e) { - // Prevent a lot of null checks by just catching the exception. - return null; - } - } - - /** - * Initialize the bridge and the resource maps. - */ - @BeforeClass - public static void setUp() { - File data_dir = new File(PLATFORM_DIR, "data"); - File res = new File(data_dir, "res"); - sFrameworkRepo = new FrameworkResources(new FolderWrapper(res)); - sFrameworkRepo.loadResources(); - sFrameworkRepo.loadPublicResources(getLogger()); - - sProjectResources = - new ResourceRepository(new FolderWrapper(TEST_RES_DIR + "/" + APP_TEST_RES), - false) { - @NonNull - @Override - protected ResourceItem createResourceItem(@NonNull String name) { - return new ResourceItem(name); - } - }; - sProjectResources.loadResources(); - - File fontLocation = new File(data_dir, "fonts"); - File buildProp = new File(PLATFORM_DIR, "build.prop"); - File attrs = new File(res, "values" + File.separator + "attrs.xml"); - sBridge = new Bridge(); - sBridge.init(ConfigGenerator.loadProperties(buildProp), fontLocation, - ConfigGenerator.getEnumMap(attrs), getLayoutLog()); - } - - @Before - public void beforeTestCase() { - sRenderMessages.clear(); - } - - /** Test activity.xml */ - @Test - public void testActivity() throws ClassNotFoundException { - renderAndVerify("activity.xml", "activity.png"); - } - - @Test - public void testTranslucentBars() throws ClassNotFoundException { - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - - LayoutPullParser parser = createLayoutPullParser("four_corners.xml"); - SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.Light.NoActionBar.TranslucentDecor", false, - RenderingMode.NORMAL, 22); - renderAndVerify(params, "four_corners_translucent.png"); - - parser = createLayoutPullParser("four_corners.xml"); - params = getSessionParams(parser, ConfigGenerator.NEXUS_5_LAND, - layoutLibCallback, "Theme.Material.Light.NoActionBar.TranslucentDecor", false, - RenderingMode.NORMAL, 22); - renderAndVerify(params, "four_corners_translucent_land.png"); - - parser = createLayoutPullParser("four_corners.xml"); - params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.Light.NoActionBar", false, - RenderingMode.NORMAL, 22); - renderAndVerify(params, "four_corners.png"); - } - - private static void gc() { - // See RuntimeUtil#gc in jlibs (http://jlibs.in/) - Object obj = new Object(); - WeakReference ref = new WeakReference<>(obj); - //noinspection UnusedAssignment - obj = null; - while(ref.get() != null) { - System.gc(); - System.runFinalization(); - } - - System.gc(); - System.runFinalization(); - } - - /** Test allwidgets.xml */ - @Test - public void testAllWidgets() throws ClassNotFoundException { - renderAndVerify("allwidgets.xml", "allwidgets.png"); - - // We expect fidelity warnings for Path.isConvex. Fail for anything else. - sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported.")); - } - - @Test - public void testArrayCheck() throws ClassNotFoundException { - renderAndVerify("array_check.xml", "array_check.png"); - } - - @Test - public void testAllWidgetsTablet() throws ClassNotFoundException { - renderAndVerify("allwidgets.xml", "allwidgets_tab.png", ConfigGenerator.NEXUS_7_2012); - - // We expect fidelity warnings for Path.isConvex. Fail for anything else. - sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported.")); - } - - @Test - public void testActivityActionBar() throws ClassNotFoundException { - LayoutPullParser parser = createLayoutPullParser("simple_activity.xml"); - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - - SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.Light.NoActionBar", false, - RenderingMode.V_SCROLL, 22); - - renderAndVerify(params, "simple_activity_noactionbar.png"); - - parser = createLayoutPullParser("simple_activity.xml"); - params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.Light", false, - RenderingMode.V_SCROLL, 22); - - renderAndVerify(params, "simple_activity.png"); - - // This also tests that a theme with "NoActionBar" DOES HAVE an action bar when we are - // displaying menus. - parser = createLayoutPullParser("simple_activity.xml"); - params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.Light.NoActionBar", false, - RenderingMode.V_SCROLL, 22); - params.setFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG, "menu"); - renderAndVerify(params, "simple_activity.png"); - } - - @Test - public void testOnApplyInsetsCall() - throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { - // We get the widget via reflection to avoid IntelliJ complaining about the class being - // located in the wrong package. (From the Bridge tests point of view, it is) - Class insetsWidgetClass = Class.forName("com.android.layoutlib.test.myapplication.widgets" + - ".InsetsWidget"); - Field field = insetsWidgetClass.getDeclaredField("sApplyInsetsCalled"); - assertFalse((Boolean)field.get(null)); - - LayoutPullParser parser = createLayoutPullParser("insets.xml"); - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.Light.NoActionBar", false, - RenderingMode.NORMAL, 22); - - render(params, -1); - - assertTrue((Boolean)field.get(null)); - field.set(null, false); - } - - @AfterClass - public static void tearDown() { - sLayoutLibLog = null; - sFrameworkRepo = null; - sProjectResources = null; - sLogger = null; - sBridge = null; - - gc(); - - System.out.println("Objects still linked from the DelegateManager:"); - DelegateManager.dump(System.out); - } - - /** Test expand_layout.xml */ - @Test - public void testExpand() throws ClassNotFoundException { - // Create the layout pull parser. - LayoutPullParser parser = createLayoutPullParser("expand_vert_layout.xml"); - // Create LayoutLibCallback. - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - - ConfigGenerator customConfigGenerator = new ConfigGenerator() - .setScreenWidth(300) - .setScreenHeight(20) - .setDensity(Density.XHIGH) - .setNavigation(Navigation.NONAV); - - SessionParams params = getSessionParams(parser, customConfigGenerator, - layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false, - RenderingMode.V_SCROLL, 22); - - renderAndVerify(params, "expand_vert_layout.png"); - - customConfigGenerator = new ConfigGenerator() - .setScreenWidth(20) - .setScreenHeight(300) - .setDensity(Density.XHIGH) - .setNavigation(Navigation.NONAV); - parser = createLayoutPullParser("expand_horz_layout.xml"); - params = getSessionParams(parser, customConfigGenerator, - layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false, - RenderingMode.H_SCROLL, 22); - - renderAndVerify(params, "expand_horz_layout.png"); - } - - /** Test indeterminate_progressbar.xml */ - @Test - public void testVectorAnimation() throws ClassNotFoundException { - // Create the layout pull parser. - LayoutPullParser parser = createLayoutPullParser("indeterminate_progressbar.xml"); - // Create LayoutLibCallback. - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - - SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, - RenderingMode.V_SCROLL, 22); - - renderAndVerify(params, "animated_vector.png", TimeUnit.SECONDS.toNanos(2)); - - parser = createLayoutPullParser("indeterminate_progressbar.xml"); - params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, - RenderingMode.V_SCROLL, 22); - renderAndVerify(params, "animated_vector_1.png", TimeUnit.SECONDS.toNanos(3)); - } - - /** - * Test a vector drawable that uses trimStart and trimEnd. It also tests all the primitives - * for vector drawables (lines, moves and cubic and quadratic curves). - */ - @Test - public void testVectorDrawable() throws ClassNotFoundException { - // Create the layout pull parser. - LayoutPullParser parser = createLayoutPullParser("vector_drawable.xml"); - // Create LayoutLibCallback. - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - - SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, - RenderingMode.V_SCROLL, 22); - - renderAndVerify(params, "vector_drawable.png", TimeUnit.SECONDS.toNanos(2)); - } - - /** - * Regression test for http://b.android.com/91383 and http://b.android.com/203797 - */ - @Test - public void testVectorDrawable91383() throws ClassNotFoundException { - // Create the layout pull parser. - LayoutPullParser parser = createLayoutPullParser("vector_drawable_android.xml"); - // Create LayoutLibCallback. - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - - SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, - RenderingMode.V_SCROLL, 22); - - renderAndVerify(params, "vector_drawable_91383.png", TimeUnit.SECONDS.toNanos(2)); - } - - /** Test activity.xml */ - @Test - public void testScrolling() throws ClassNotFoundException { - // Create the layout pull parser. - LayoutPullParser parser = createLayoutPullParser("scrolled.xml"); - // Create LayoutLibCallback. - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - - SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, - layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, - RenderingMode.V_SCROLL, 22); - params.setForceNoDecor(); - params.setExtendedViewInfoMode(true); - - RenderResult result = renderAndVerify(params, "scrolled.png"); - assertNotNull(result); - assertNotNull(result.getResult()); - assertTrue(result.getResult().isSuccess()); - - ViewInfo rootLayout = result.getRootViews().get(0); - // Check the first box in the main LinearLayout - assertEquals(-90, rootLayout.getChildren().get(0).getTop()); - assertEquals(-30, rootLayout.getChildren().get(0).getLeft()); - assertEquals(90, rootLayout.getChildren().get(0).getBottom()); - assertEquals(150, rootLayout.getChildren().get(0).getRight()); - - // Check the first box within the nested LinearLayout - assertEquals(-450, rootLayout.getChildren().get(5).getChildren().get(0).getTop()); - assertEquals(90, rootLayout.getChildren().get(5).getChildren().get(0).getLeft()); - assertEquals(-270, rootLayout.getChildren().get(5).getChildren().get(0).getBottom()); - assertEquals(690, rootLayout.getChildren().get(5).getChildren().get(0).getRight()); - } - - @Test - public void testGetResourceNameVariants() throws Exception { - // Setup - // Create the layout pull parser for our resources (empty.xml can not be part of the test - // app as it won't compile). - LayoutPullParser parser = new LayoutPullParser("/empty.xml"); - // Create LayoutLibCallback. - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4, - layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22); - AssetManager assetManager = AssetManager.getSystem(); - DisplayMetrics metrics = new DisplayMetrics(); - Configuration configuration = RenderAction.getConfiguration(params); - Resources resources = new Resources(assetManager, metrics, configuration); - resources.mLayoutlibCallback = params.getLayoutlibCallback(); - resources.mContext = - new BridgeContext(params.getProjectKey(), metrics, params.getResources(), - params.getAssets(), params.getLayoutlibCallback(), configuration, - params.getTargetSdkVersion(), params.isRtlSupported()); - // Test - assertEquals("android:style/ButtonBar", - resources.getResourceName(android.R.style.ButtonBar)); - assertEquals("android", resources.getResourcePackageName(android.R.style.ButtonBar)); - assertEquals("ButtonBar", resources.getResourceEntryName(android.R.style.ButtonBar)); - assertEquals("style", resources.getResourceTypeName(android.R.style.ButtonBar)); - int id = resources.mLayoutlibCallback.getResourceId(ResourceType.STRING, "app_name"); - assertEquals("com.android.layoutlib.test.myapplication:string/app_name", - resources.getResourceName(id)); - assertEquals("com.android.layoutlib.test.myapplication", - resources.getResourcePackageName(id)); - assertEquals("string", resources.getResourceTypeName(id)); - assertEquals("app_name", resources.getResourceEntryName(id)); - } - - @NonNull - private LayoutPullParser createLayoutPullParser(String layoutPath) { - return new LayoutPullParser(APP_TEST_RES + "/layout/" + layoutPath); - } - - @NonNull - private static RenderResult render(SessionParams params, long frameTimeNanos) { - // TODO: Set up action bar handler properly to test menu rendering. - // Create session params. - System_Delegate.setBootTimeNanos(TimeUnit.MILLISECONDS.toNanos(871732800000L)); - System_Delegate.setNanosTime(TimeUnit.MILLISECONDS.toNanos(871732800000L)); - RenderSession session = sBridge.createSession(params); - - try { - - if (frameTimeNanos != -1) { - session.setElapsedFrameTimeNanos(frameTimeNanos); - } - - if (!session.getResult().isSuccess()) { - getLogger().error(session.getResult().getException(), - session.getResult().getErrorMessage()); - } - // Render the session with a timeout of 50s. - Result renderResult = session.render(50000); - if (!renderResult.isSuccess()) { - getLogger().error(session.getResult().getException(), - session.getResult().getErrorMessage()); - } - - return RenderResult.getFromSession(session); - } finally { - session.dispose(); - } - } - - /** - * Create a new rendering session and test that rendering the given layout doesn't throw any - * exceptions and matches the provided image. - * <p> - * If frameTimeNanos is >= 0 a frame will be executed during the rendering. The time indicates - * how far in the future is. - */ - @Nullable - private static RenderResult renderAndVerify(SessionParams params, String goldenFileName, long - frameTimeNanos) - throws ClassNotFoundException { - RenderResult result = Main.render(params, frameTimeNanos); - try { - String goldenImagePath = APP_TEST_DIR + "/golden/" + goldenFileName; - assertNotNull(result.getImage()); - ImageUtils.requireSimilar(goldenImagePath, result.getImage()); - } catch (IOException e) { - getLogger().error(e, e.getMessage()); - } - - return result; - } - - /** - * Create a new rendering session and test that rendering the given layout doesn't throw any - * exceptions and matches the provided image. - */ - @Nullable - private static RenderResult renderAndVerify(SessionParams params, String goldenFileName) - throws ClassNotFoundException { - return Main.renderAndVerify(params, goldenFileName, -1); - } - - /** - * Create a new rendering session and test that rendering the given layout on nexus 5 - * doesn't throw any exceptions and matches the provided image. - */ - @Nullable - private RenderResult renderAndVerify(String layoutFileName, String goldenFileName) - throws ClassNotFoundException { - return renderAndVerify(layoutFileName, goldenFileName, ConfigGenerator.NEXUS_5); - } - - /** - * Create a new rendering session and test that rendering the given layout on given device - * doesn't throw any exceptions and matches the provided image. - */ - @Nullable - private RenderResult renderAndVerify(String layoutFileName, String goldenFileName, - ConfigGenerator deviceConfig) - throws ClassNotFoundException { - SessionParams params = createSessionParams(layoutFileName, deviceConfig); - return renderAndVerify(params, goldenFileName); - } - - private SessionParams createSessionParams(String layoutFileName, ConfigGenerator deviceConfig) - throws ClassNotFoundException { - // Create the layout pull parser. - LayoutPullParser parser = createLayoutPullParser(layoutFileName); - // Create LayoutLibCallback. - LayoutLibTestCallback layoutLibCallback = - new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); - layoutLibCallback.initResources(); - // TODO: Set up action bar handler properly to test menu rendering. - // Create session params. - return getSessionParams(parser, deviceConfig, - layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22); - } - - /** - * Uses Theme.Material and Target sdk version as 22. - */ - private SessionParams getSessionParams(LayoutPullParser layoutParser, - ConfigGenerator configGenerator, LayoutLibTestCallback layoutLibCallback, - String themeName, boolean isProjectTheme, RenderingMode renderingMode, int targetSdk) { - FolderConfiguration config = configGenerator.getFolderConfig(); - ResourceResolver resourceResolver = - ResourceResolver.create(sProjectResources.getConfiguredResources(config), - sFrameworkRepo.getConfiguredResources(config), - themeName, isProjectTheme); - - SessionParams sessionParams = new SessionParams( - layoutParser, - renderingMode, - null /*used for caching*/, - configGenerator.getHardwareConfig(), - resourceResolver, - layoutLibCallback, - 0, - targetSdk, - getLayoutLog()); - sessionParams.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true); - return sessionParams; - } - - private static LayoutLog getLayoutLog() { - if (sLayoutLibLog == null) { - sLayoutLibLog = new LayoutLog() { - @Override - public void warning(String tag, String message, Object data) { - System.out.println("Warning " + tag + ": " + message); - failWithMsg(message); - } - - @Override - public void fidelityWarning(@Nullable String tag, String message, - Throwable throwable, Object data) { - - System.out.println("FidelityWarning " + tag + ": " + message); - if (throwable != null) { - throwable.printStackTrace(); - } - failWithMsg(message == null ? "" : message); - } - - @Override - public void error(String tag, String message, Object data) { - System.out.println("Error " + tag + ": " + message); - failWithMsg(message); - } - - @Override - public void error(String tag, String message, Throwable throwable, Object data) { - System.out.println("Error " + tag + ": " + message); - if (throwable != null) { - throwable.printStackTrace(); - } - failWithMsg(message); - } - }; - } - return sLayoutLibLog; - } - - private static ILogger getLogger() { - if (sLogger == null) { - sLogger = new ILogger() { - @Override - public void error(Throwable t, @Nullable String msgFormat, Object... args) { - if (t != null) { - t.printStackTrace(); - } - failWithMsg(msgFormat == null ? "" : msgFormat, args); - } - - @Override - public void warning(@NonNull String msgFormat, Object... args) { - failWithMsg(msgFormat, args); - } - - @Override - public void info(@NonNull String msgFormat, Object... args) { - // pass. - } - - @Override - public void verbose(@NonNull String msgFormat, Object... args) { - // pass. - } - }; - } - return sLogger; - } - - private static void failWithMsg(@NonNull String msgFormat, Object... args) { - sRenderMessages.add(args == null ? msgFormat : String.format(msgFormat, args)); - } } diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/PerformanceTests.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/PerformanceTests.java new file mode 100644 index 000000000000..c90c26aad8ec --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/PerformanceTests.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.layoutlib.bridge.intensive; + +import com.android.ide.common.rendering.api.SessionParams; +import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator; +import com.android.layoutlib.bridge.intensive.util.perf.PerformanceRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import android.annotation.NonNull; + +/** + * Set of render tests + */ +@RunWith(PerformanceRunner.class) +public class PerformanceTests extends RenderTestBase { + + @Before + public void setUp() { + ignoreAllLogging(); + } + + + private void render(@NonNull String layoutFileName) throws ClassNotFoundException { + SessionParams params = createSessionParams(layoutFileName, ConfigGenerator.NEXUS_5); + render(params, 250); + } + + @Test + public void testActivity() throws ClassNotFoundException { + render("activity.xml"); + } + + @Test + public void testAllWidgets() throws ClassNotFoundException { + render("allwidgets.xml"); + } +} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java new file mode 100644 index 000000000000..3e5f9e074fef --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.layoutlib.bridge.intensive; + +import com.android.ide.common.rendering.api.LayoutLog; +import com.android.ide.common.rendering.api.RenderSession; +import com.android.ide.common.rendering.api.Result; +import com.android.ide.common.rendering.api.SessionParams; +import com.android.ide.common.rendering.api.SessionParams.RenderingMode; +import com.android.ide.common.resources.FrameworkResources; +import com.android.ide.common.resources.ResourceItem; +import com.android.ide.common.resources.ResourceRepository; +import com.android.ide.common.resources.ResourceResolver; +import com.android.ide.common.resources.configuration.FolderConfiguration; +import com.android.io.FolderWrapper; +import com.android.layoutlib.bridge.Bridge; +import com.android.layoutlib.bridge.android.RenderParamsFlags; +import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator; +import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback; +import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser; +import com.android.layoutlib.bridge.intensive.util.ImageUtils; +import com.android.layoutlib.bridge.intensive.util.ModuleClassLoader; +import com.android.layoutlib.bridge.intensive.util.TestUtils; +import com.android.tools.layoutlib.java.System_Delegate; +import com.android.utils.ILogger; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import com.google.android.collect.Lists; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +/** + * Base class for render tests. The render tests load all the framework resources and a project + * checked in this test's resources. The main dependencies + * are: + * 1. Fonts directory. + * 2. Framework Resources. + * 3. App resources. + * 4. build.prop file + * <p> + * These are configured by two variables set in the system properties. + * <p> + * 1. platform.dir: This is the directory for the current platform in the built SDK + * (.../sdk/platforms/android-<version>). + * <p> + * The fonts are platform.dir/data/fonts. + * The Framework resources are platform.dir/data/res. + * build.prop is at platform.dir/build.prop. + * <p> + * 2. test_res.dir: This is the directory for the resources of the test. If not specified, this + * falls back to getClass().getProtectionDomain().getCodeSource().getLocation() + * <p> + * The app resources are at: test_res.dir/testApp/MyApplication/app/src/main/res + */ +public class RenderTestBase { + + private static final String PLATFORM_DIR_PROPERTY = "platform.dir"; + private static final String RESOURCE_DIR_PROPERTY = "test_res.dir"; + + private static final String PLATFORM_DIR; + private static final String TEST_RES_DIR; + /** Location of the app to test inside {@link #TEST_RES_DIR} */ + private static final String APP_TEST_DIR = "testApp/MyApplication"; + /** Location of the app's res dir inside {@link #TEST_RES_DIR} */ + private static final String APP_TEST_RES = APP_TEST_DIR + "/src/main/res"; + private static final String APP_CLASSES_LOCATION = + APP_TEST_DIR + "/build/intermediates/classes/debug/"; + protected static Bridge sBridge; + /** List of log messages generated by a render call. It can be used to find specific errors */ + protected static ArrayList<String> sRenderMessages = Lists.newArrayList(); + private static LayoutLog sLayoutLibLog; + private static FrameworkResources sFrameworkRepo; + private static ResourceRepository sProjectResources; + private static ILogger sLogger; + + static { + // Test that System Properties are properly set. + PLATFORM_DIR = getPlatformDir(); + if (PLATFORM_DIR == null) { + fail(String.format("System Property %1$s not properly set. The value is %2$s", + PLATFORM_DIR_PROPERTY, System.getProperty(PLATFORM_DIR_PROPERTY))); + } + + TEST_RES_DIR = getTestResDir(); + if (TEST_RES_DIR == null) { + fail(String.format("System property %1$s.dir not properly set. The value is %2$s", + RESOURCE_DIR_PROPERTY, System.getProperty(RESOURCE_DIR_PROPERTY))); + } + } + + @Rule + public TestWatcher sRenderMessageWatcher = new TestWatcher() { + @Override + protected void succeeded(Description description) { + // We only check error messages if the rest of the test case was successful. + if (!sRenderMessages.isEmpty()) { + fail(description.getMethodName() + " render error message: " + + sRenderMessages.get(0)); + } + } + }; + // Default class loader with access to the app classes + protected ClassLoader mDefaultClassLoader = + new ModuleClassLoader(APP_CLASSES_LOCATION, getClass().getClassLoader()); + + private static String getPlatformDir() { + String platformDir = System.getProperty(PLATFORM_DIR_PROPERTY); + if (platformDir != null && !platformDir.isEmpty() && new File(platformDir).isDirectory()) { + return platformDir; + } + // System Property not set. Try to find the directory in the build directory. + String androidHostOut = System.getenv("ANDROID_HOST_OUT"); + if (androidHostOut != null) { + platformDir = getPlatformDirFromHostOut(new File(androidHostOut)); + if (platformDir != null) { + return platformDir; + } + } + String workingDirString = System.getProperty("user.dir"); + File workingDir = new File(workingDirString); + // Test if workingDir is android checkout root. + platformDir = getPlatformDirFromRoot(workingDir); + if (platformDir != null) { + return platformDir; + } + + // Test if workingDir is platform/frameworks/base/tools/layoutlib/bridge. + File currentDir = workingDir; + if (currentDir.getName().equalsIgnoreCase("bridge")) { + currentDir = currentDir.getParentFile(); + } + // Test if currentDir is platform/frameworks/base/tools/layoutlib. That is, root should be + // workingDir/../../../../ (4 levels up) + for (int i = 0; i < 4; i++) { + if (currentDir != null) { + currentDir = currentDir.getParentFile(); + } + } + return currentDir == null ? null : getPlatformDirFromRoot(currentDir); + } + + private static String getPlatformDirFromRoot(File root) { + if (!root.isDirectory()) { + return null; + } + File out = new File(root, "out"); + if (!out.isDirectory()) { + return null; + } + File host = new File(out, "host"); + if (!host.isDirectory()) { + return null; + } + File[] hosts = host.listFiles(path -> path.isDirectory() && + (path.getName().startsWith("linux-") || path.getName().startsWith("darwin-"))); + assert hosts != null; + for (File hostOut : hosts) { + String platformDir = getPlatformDirFromHostOut(hostOut); + if (platformDir != null) { + return platformDir; + } + } + return null; + } + + private static String getPlatformDirFromHostOut(File out) { + if (!out.isDirectory()) { + return null; + } + File sdkDir = new File(out, "sdk"); + if (!sdkDir.isDirectory()) { + return null; + } + File[] sdkDirs = sdkDir.listFiles(path -> { + // We need to search for $TARGET_PRODUCT (usually, sdk_phone_armv7) + return path.isDirectory() && path.getName().startsWith("sdk"); + }); + assert sdkDirs != null; + for (File dir : sdkDirs) { + String platformDir = getPlatformDirFromHostOutSdkSdk(dir); + if (platformDir != null) { + return platformDir; + } + } + return null; + } + + private static String getPlatformDirFromHostOutSdkSdk(File sdkDir) { + File[] possibleSdks = sdkDir.listFiles( + path -> path.isDirectory() && path.getName().contains("android-sdk")); + assert possibleSdks != null; + for (File possibleSdk : possibleSdks) { + File platformsDir = new File(possibleSdk, "platforms"); + File[] platforms = platformsDir.listFiles( + path -> path.isDirectory() && path.getName().startsWith("android-")); + if (platforms == null || platforms.length == 0) { + continue; + } + Arrays.sort(platforms, (o1, o2) -> { + final int MAX_VALUE = 1000; + String suffix1 = o1.getName().substring("android-".length()); + String suffix2 = o2.getName().substring("android-".length()); + int suff1, suff2; + try { + suff1 = Integer.parseInt(suffix1); + } catch (NumberFormatException e) { + suff1 = MAX_VALUE; + } + try { + suff2 = Integer.parseInt(suffix2); + } catch (NumberFormatException e) { + suff2 = MAX_VALUE; + } + if (suff1 != MAX_VALUE || suff2 != MAX_VALUE) { + return suff2 - suff1; + } + return suffix2.compareTo(suffix1); + }); + return platforms[0].getAbsolutePath(); + } + return null; + } + + private static String getTestResDir() { + String resourceDir = System.getProperty(RESOURCE_DIR_PROPERTY); + if (resourceDir != null && !resourceDir.isEmpty() && new File(resourceDir).isDirectory()) { + return resourceDir; + } + // TEST_RES_DIR not explicitly set. Fallback to the class's source location. + try { + URL location = RenderTestBase.class.getProtectionDomain().getCodeSource().getLocation(); + return new File(location.getPath()).exists() ? location.getPath() : null; + } catch (NullPointerException e) { + // Prevent a lot of null checks by just catching the exception. + return null; + } + } + + /** + * Initialize the bridge and the resource maps. + */ + @BeforeClass + public static void beforeClass() { + File data_dir = new File(PLATFORM_DIR, "data"); + File res = new File(data_dir, "res"); + sFrameworkRepo = new FrameworkResources(new FolderWrapper(res)); + sFrameworkRepo.loadResources(); + sFrameworkRepo.loadPublicResources(getLogger()); + + sProjectResources = + new ResourceRepository(new FolderWrapper(TEST_RES_DIR + "/" + APP_TEST_RES), + false) { + @NonNull + @Override + protected ResourceItem createResourceItem(@NonNull String name) { + return new ResourceItem(name); + } + }; + sProjectResources.loadResources(); + + File fontLocation = new File(data_dir, "fonts"); + File buildProp = new File(PLATFORM_DIR, "build.prop"); + File attrs = new File(res, "values" + File.separator + "attrs.xml"); + sBridge = new Bridge(); + sBridge.init(ConfigGenerator.loadProperties(buildProp), fontLocation, + ConfigGenerator.getEnumMap(attrs), getLayoutLog()); + Bridge.getLock().lock(); + try { + Bridge.setLog(getLayoutLog()); + } finally { + Bridge.getLock().unlock(); + } + } + + @AfterClass + public static void tearDown() { + sLayoutLibLog = null; + sFrameworkRepo = null; + sProjectResources = null; + sLogger = null; + sBridge = null; + + TestUtils.gc(); + + System.out.println("Objects still linked from the DelegateManager:"); + DelegateManager.dump(System.out); + } + + @NonNull + protected static RenderResult render(SessionParams params, long frameTimeNanos) { + // TODO: Set up action bar handler properly to test menu rendering. + // Create session params. + System_Delegate.setBootTimeNanos(TimeUnit.MILLISECONDS.toNanos(871732800000L)); + System_Delegate.setNanosTime(TimeUnit.MILLISECONDS.toNanos(871732800000L)); + RenderSession session = sBridge.createSession(params); + + try { + + if (frameTimeNanos != -1) { + session.setElapsedFrameTimeNanos(frameTimeNanos); + } + + if (!session.getResult().isSuccess()) { + getLogger().error(session.getResult().getException(), + session.getResult().getErrorMessage()); + } + // Render the session with a timeout of 50s. + Result renderResult = session.render(50000); + if (!renderResult.isSuccess()) { + getLogger().error(session.getResult().getException(), + session.getResult().getErrorMessage()); + } + + return RenderResult.getFromSession(session); + } finally { + session.dispose(); + } + } + + /** + * Create a new rendering session and test that rendering the given layout doesn't throw any + * exceptions and matches the provided image. + * <p> + * If frameTimeNanos is >= 0 a frame will be executed during the rendering. The time indicates + * how far in the future is. + */ + @Nullable + protected static RenderResult renderAndVerify(SessionParams params, String goldenFileName, + long frameTimeNanos) throws ClassNotFoundException { + RenderResult result = RenderTestBase.render(params, frameTimeNanos); + try { + String goldenImagePath = APP_TEST_DIR + "/golden/" + goldenFileName; + assertNotNull(result.getImage()); + ImageUtils.requireSimilar(goldenImagePath, result.getImage()); + } catch (IOException e) { + getLogger().error(e, e.getMessage()); + } + + return result; + } + + /** + * Create a new rendering session and test that rendering the given layout doesn't throw any + * exceptions and matches the provided image. + */ + @Nullable + protected static RenderResult renderAndVerify(SessionParams params, String goldenFileName) + throws ClassNotFoundException { + return RenderTestBase.renderAndVerify(params, goldenFileName, -1); + } + + private static LayoutLog getLayoutLog() { + if (sLayoutLibLog == null) { + sLayoutLibLog = new LayoutLog() { + @Override + public void warning(String tag, String message, Object data) { + System.out.println("Warning " + tag + ": " + message); + failWithMsg(message); + } + + @Override + public void fidelityWarning(@Nullable String tag, String message, + Throwable throwable, Object data) { + + System.out.println("FidelityWarning " + tag + ": " + message); + if (throwable != null) { + throwable.printStackTrace(); + } + failWithMsg(message == null ? "" : message); + } + + @Override + public void error(String tag, String message, Object data) { + System.out.println("Error " + tag + ": " + message); + failWithMsg(message); + } + + @Override + public void error(String tag, String message, Throwable throwable, Object data) { + System.out.println("Error " + tag + ": " + message); + if (throwable != null) { + throwable.printStackTrace(); + } + failWithMsg(message); + } + }; + } + return sLayoutLibLog; + } + + protected static void ignoreAllLogging() { + sLayoutLibLog = new LayoutLog(); + sLogger = new ILogger() { + @Override + public void error(Throwable t, String msgFormat, Object... args) { + } + + @Override + public void warning(String msgFormat, Object... args) { + } + + @Override + public void info(String msgFormat, Object... args) { + } + + @Override + public void verbose(String msgFormat, Object... args) { + } + }; + } + + protected static ILogger getLogger() { + if (sLogger == null) { + sLogger = new ILogger() { + @Override + public void error(Throwable t, @Nullable String msgFormat, Object... args) { + if (t != null) { + t.printStackTrace(); + } + failWithMsg(msgFormat == null ? "" : msgFormat, args); + } + + @Override + public void warning(@NonNull String msgFormat, Object... args) { + failWithMsg(msgFormat, args); + } + + @Override + public void info(@NonNull String msgFormat, Object... args) { + // pass. + } + + @Override + public void verbose(@NonNull String msgFormat, Object... args) { + // pass. + } + }; + } + return sLogger; + } + + private static void failWithMsg(@NonNull String msgFormat, Object... args) { + sRenderMessages.add(args == null ? msgFormat : String.format(msgFormat, args)); + } + + @Before + public void beforeTestCase() { + sRenderMessages.clear(); + } + + @NonNull + protected LayoutPullParser createLayoutPullParser(String layoutPath) { + return new LayoutPullParser(APP_TEST_RES + "/layout/" + layoutPath); + } + + /** + * Create a new rendering session and test that rendering the given layout on nexus 5 + * doesn't throw any exceptions and matches the provided image. + */ + @Nullable + protected RenderResult renderAndVerify(String layoutFileName, String goldenFileName) + throws ClassNotFoundException { + return renderAndVerify(layoutFileName, goldenFileName, ConfigGenerator.NEXUS_5); + } + + /** + * Create a new rendering session and test that rendering the given layout on given device + * doesn't throw any exceptions and matches the provided image. + */ + @Nullable + protected RenderResult renderAndVerify(String layoutFileName, String goldenFileName, + ConfigGenerator deviceConfig) throws ClassNotFoundException { + SessionParams params = createSessionParams(layoutFileName, deviceConfig); + return renderAndVerify(params, goldenFileName); + } + + protected SessionParams createSessionParams(String layoutFileName, ConfigGenerator deviceConfig) + throws ClassNotFoundException { + // Create the layout pull parser. + LayoutPullParser parser = createLayoutPullParser(layoutFileName); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + // TODO: Set up action bar handler properly to test menu rendering. + // Create session params. + return getSessionParams(parser, deviceConfig, layoutLibCallback, "AppTheme", true, + RenderingMode.NORMAL, 22); + } + + /** + * Uses Theme.Material and Target sdk version as 22. + */ + protected SessionParams getSessionParams(LayoutPullParser layoutParser, + ConfigGenerator configGenerator, LayoutLibTestCallback layoutLibCallback, + String themeName, boolean isProjectTheme, RenderingMode renderingMode, + @SuppressWarnings("SameParameterValue") int targetSdk) { + FolderConfiguration config = configGenerator.getFolderConfig(); + ResourceResolver resourceResolver = + ResourceResolver.create(sProjectResources.getConfiguredResources(config), + sFrameworkRepo.getConfiguredResources(config), themeName, isProjectTheme); + + SessionParams sessionParams = + new SessionParams(layoutParser, renderingMode, null /*used for caching*/, + configGenerator.getHardwareConfig(), resourceResolver, layoutLibCallback, 0, + targetSdk, getLayoutLog()); + sessionParams.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true); + return sessionParams; + } +} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java new file mode 100644 index 000000000000..73e51ecf73ce --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2014 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. + */ + +package com.android.layoutlib.bridge.intensive; + +import com.android.ide.common.rendering.api.RenderSession; +import com.android.ide.common.rendering.api.SessionParams; +import com.android.ide.common.rendering.api.SessionParams.RenderingMode; +import com.android.ide.common.rendering.api.ViewInfo; +import com.android.layoutlib.bridge.android.BridgeContext; +import com.android.layoutlib.bridge.android.RenderParamsFlags; +import com.android.layoutlib.bridge.impl.RenderAction; +import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator; +import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback; +import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser; +import com.android.resources.Density; +import com.android.resources.Navigation; +import com.android.resources.ResourceType; + +import org.junit.Test; + +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.util.DisplayMetrics; + +import java.lang.reflect.Field; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Set of render tests + */ +public class RenderTests extends RenderTestBase { + + @Test + public void testActivity() throws ClassNotFoundException { + renderAndVerify("activity.xml", "activity.png"); + } + + @Test + public void testActivityOnOldTheme() throws ClassNotFoundException { + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + + LayoutPullParser parser = createLayoutPullParser("simple_activity.xml"); + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.NoTitleBar", false, + RenderingMode.NORMAL, 22); + + renderAndVerify(params, "simple_activity-old-theme.png"); + } + + @Test + public void testTranslucentBars() throws ClassNotFoundException { + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + + LayoutPullParser parser = createLayoutPullParser("four_corners.xml"); + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.Light.NoActionBar.TranslucentDecor", false, + RenderingMode.NORMAL, 22); + renderAndVerify(params, "four_corners_translucent.png"); + + parser = createLayoutPullParser("four_corners.xml"); + params = getSessionParams(parser, ConfigGenerator.NEXUS_5_LAND, + layoutLibCallback, "Theme.Material.Light.NoActionBar.TranslucentDecor", false, + RenderingMode.NORMAL, 22); + renderAndVerify(params, "four_corners_translucent_land.png"); + + parser = createLayoutPullParser("four_corners.xml"); + params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.Light.NoActionBar", false, + RenderingMode.NORMAL, 22); + renderAndVerify(params, "four_corners.png"); + } + + @Test + public void testAllWidgets() throws ClassNotFoundException { + renderAndVerify("allwidgets.xml", "allwidgets.png"); + + // We expect fidelity warnings for Path.isConvex. Fail for anything else. + sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported.")); + } + + @Test + public void testArrayCheck() throws ClassNotFoundException { + renderAndVerify("array_check.xml", "array_check.png"); + } + + @Test + public void testAllWidgetsTablet() throws ClassNotFoundException { + renderAndVerify("allwidgets.xml", "allwidgets_tab.png", ConfigGenerator.NEXUS_7_2012); + + // We expect fidelity warnings for Path.isConvex. Fail for anything else. + sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported.")); + } + + @Test + public void testActivityActionBar() throws ClassNotFoundException { + LayoutPullParser parser = createLayoutPullParser("simple_activity.xml"); + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.Light.NoActionBar", false, + RenderingMode.V_SCROLL, 22); + + renderAndVerify(params, "simple_activity_noactionbar.png"); + + parser = createLayoutPullParser("simple_activity.xml"); + params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.Light", false, + RenderingMode.V_SCROLL, 22); + + renderAndVerify(params, "simple_activity.png"); + + // This also tests that a theme with "NoActionBar" DOES HAVE an action bar when we are + // displaying menus. + parser = createLayoutPullParser("simple_activity.xml"); + params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.Light.NoActionBar", false, + RenderingMode.V_SCROLL, 22); + params.setFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG, "menu"); + renderAndVerify(params, "simple_activity.png"); + } + + @Test + public void testOnApplyInsetsCall() + throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { + // We get the widget via reflection to avoid IntelliJ complaining about the class being + // located in the wrong package. (From the Bridge tests point of view, it is) + Class insetsWidgetClass = Class.forName("com.android.layoutlib.test.myapplication.widgets" + + ".InsetsWidget"); + Field field = insetsWidgetClass.getDeclaredField("sApplyInsetsCalled"); + assertFalse((Boolean)field.get(null)); + + LayoutPullParser parser = createLayoutPullParser("insets.xml"); + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.Light.NoActionBar", false, + RenderingMode.NORMAL, 22); + + render(params, -1); + + assertTrue((Boolean)field.get(null)); + field.set(null, false); + } + + /** Test expand_layout.xml */ + @Test + public void testExpand() throws ClassNotFoundException { + // Create the layout pull parser. + LayoutPullParser parser = createLayoutPullParser("expand_vert_layout.xml"); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + + ConfigGenerator customConfigGenerator = new ConfigGenerator() + .setScreenWidth(300) + .setScreenHeight(20) + .setDensity(Density.XHIGH) + .setNavigation(Navigation.NONAV); + + SessionParams params = getSessionParams(parser, customConfigGenerator, + layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false, + RenderingMode.V_SCROLL, 22); + + renderAndVerify(params, "expand_vert_layout.png"); + + customConfigGenerator = new ConfigGenerator() + .setScreenWidth(20) + .setScreenHeight(300) + .setDensity(Density.XHIGH) + .setNavigation(Navigation.NONAV); + parser = createLayoutPullParser("expand_horz_layout.xml"); + params = getSessionParams(parser, customConfigGenerator, + layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false, + RenderingMode.H_SCROLL, 22); + + renderAndVerify(params, "expand_horz_layout.png"); + } + + /** Test indeterminate_progressbar.xml */ + @Test + public void testVectorAnimation() throws ClassNotFoundException { + // Create the layout pull parser. + LayoutPullParser parser = createLayoutPullParser("indeterminate_progressbar.xml"); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, + RenderingMode.V_SCROLL, 22); + + renderAndVerify(params, "animated_vector.png", TimeUnit.SECONDS.toNanos(2)); + + parser = createLayoutPullParser("indeterminate_progressbar.xml"); + params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, + RenderingMode.V_SCROLL, 22); + renderAndVerify(params, "animated_vector_1.png", TimeUnit.SECONDS.toNanos(3)); + } + + /** + * Test a vector drawable that uses trimStart and trimEnd. It also tests all the primitives + * for vector drawables (lines, moves and cubic and quadratic curves). + */ + @Test + public void testVectorDrawable() throws ClassNotFoundException { + // Create the layout pull parser. + LayoutPullParser parser = createLayoutPullParser("vector_drawable.xml"); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, + RenderingMode.V_SCROLL, 22); + + renderAndVerify(params, "vector_drawable.png", TimeUnit.SECONDS.toNanos(2)); + } + + /** + * Regression test for http://b.android.com/91383 and http://b.android.com/203797 + */ + @Test + public void testVectorDrawable91383() throws ClassNotFoundException { + // Create the layout pull parser. + LayoutPullParser parser = createLayoutPullParser("vector_drawable_android.xml"); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, + RenderingMode.V_SCROLL, 22); + + renderAndVerify(params, "vector_drawable_91383.png", TimeUnit.SECONDS.toNanos(2)); + } + + /** Test activity.xml */ + @Test + public void testScrollingAndMeasure() throws ClassNotFoundException { + // Create the layout pull parser. + LayoutPullParser parser = createLayoutPullParser("scrolled.xml"); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, + RenderingMode.V_SCROLL, 22); + params.setForceNoDecor(); + params.setExtendedViewInfoMode(true); + + // Do an only-measure pass + RenderSession session = sBridge.createSession(params); + session.measure(); + RenderResult result = RenderResult.getFromSession(session); + assertNotNull(result); + assertNotNull(result.getResult()); + assertTrue(result.getResult().isSuccess()); + + ViewInfo rootLayout = result.getRootViews().get(0); + // Check the first box in the main LinearLayout + assertEquals(-90, rootLayout.getChildren().get(0).getTop()); + assertEquals(-30, rootLayout.getChildren().get(0).getLeft()); + assertEquals(90, rootLayout.getChildren().get(0).getBottom()); + assertEquals(150, rootLayout.getChildren().get(0).getRight()); + + // Check the first box within the nested LinearLayout + assertEquals(-450, rootLayout.getChildren().get(5).getChildren().get(0).getTop()); + assertEquals(90, rootLayout.getChildren().get(5).getChildren().get(0).getLeft()); + assertEquals(-270, rootLayout.getChildren().get(5).getChildren().get(0).getBottom()); + assertEquals(690, rootLayout.getChildren().get(5).getChildren().get(0).getRight()); + + // Do a full render pass + parser = createLayoutPullParser("scrolled.xml"); + + params = getSessionParams(parser, ConfigGenerator.NEXUS_5, + layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false, + RenderingMode.V_SCROLL, 22); + params.setForceNoDecor(); + params.setExtendedViewInfoMode(true); + + result = renderAndVerify(params, "scrolled.png"); + assertNotNull(result); + assertNotNull(result.getResult()); + assertTrue(result.getResult().isSuccess()); + } + + @Test + public void testGetResourceNameVariants() throws Exception { + // Setup + // Create the layout pull parser for our resources (empty.xml can not be part of the test + // app as it won't compile). + LayoutPullParser parser = new LayoutPullParser("/empty.xml"); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4, + layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22); + AssetManager assetManager = AssetManager.getSystem(); + DisplayMetrics metrics = new DisplayMetrics(); + Configuration configuration = RenderAction.getConfiguration(params); + Resources resources = new Resources(assetManager, metrics, configuration); + resources.mLayoutlibCallback = params.getLayoutlibCallback(); + resources.mContext = + new BridgeContext(params.getProjectKey(), metrics, params.getResources(), + params.getAssets(), params.getLayoutlibCallback(), configuration, + params.getTargetSdkVersion(), params.isRtlSupported()); + // Test + assertEquals("android:style/ButtonBar", + resources.getResourceName(android.R.style.ButtonBar)); + assertEquals("android", resources.getResourcePackageName(android.R.style.ButtonBar)); + assertEquals("ButtonBar", resources.getResourceEntryName(android.R.style.ButtonBar)); + assertEquals("style", resources.getResourceTypeName(android.R.style.ButtonBar)); + int id = resources.mLayoutlibCallback.getResourceId(ResourceType.STRING, "app_name"); + assertEquals("com.android.layoutlib.test.myapplication:string/app_name", + resources.getResourceName(id)); + assertEquals("com.android.layoutlib.test.myapplication", + resources.getResourcePackageName(id)); + assertEquals("string", resources.getResourceTypeName(id)); + assertEquals("app_name", resources.getResourceEntryName(id)); + } + + @Test + public void testStringEscaping() throws Exception { + // Setup + // Create the layout pull parser for our resources (empty.xml can not be part of the test + // app as it won't compile). + LayoutPullParser parser = new LayoutPullParser("/empty.xml"); + // Create LayoutLibCallback. + LayoutLibTestCallback layoutLibCallback = + new LayoutLibTestCallback(RenderTestBase.getLogger(), mDefaultClassLoader); + layoutLibCallback.initResources(); + SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4, + layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22); + AssetManager assetManager = AssetManager.getSystem(); + DisplayMetrics metrics = new DisplayMetrics(); + Configuration configuration = RenderAction.getConfiguration(params); + Resources resources = new Resources(assetManager, metrics, configuration); + resources.mLayoutlibCallback = params.getLayoutlibCallback(); + resources.mContext = + new BridgeContext(params.getProjectKey(), metrics, params.getResources(), + params.getAssets(), params.getLayoutlibCallback(), configuration, + params.getTargetSdkVersion(), params.isRtlSupported()); + + int id = resources.mLayoutlibCallback.getResourceId(ResourceType.ARRAY, "string_array"); + String[] strings = resources.getStringArray(id); + assertArrayEquals( + new String[]{"mystring", "Hello world!", "candidates", "Unknown", "?EC"}, + strings); + assertTrue(sRenderMessages.isEmpty()); + } +} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java index d3f0f893f2ec..18c662915a6d 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2016 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.layoutlib.bridge.intensive; +package com.android.layoutlib.bridge.intensive.util; import android.annotation.NonNull; diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ModuleClassLoader.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ModuleClassLoader.java index 3fac7782b3ae..da360f37dff1 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ModuleClassLoader.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ModuleClassLoader.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.layoutlib.bridge.intensive; +package com.android.layoutlib.bridge.intensive.util; import java.io.IOException; import java.util.HashMap; diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/TestUtils.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/TestUtils.java new file mode 100644 index 000000000000..1df8e7978ba8 --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/TestUtils.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.layoutlib.bridge.intensive.util; + +import java.lang.ref.WeakReference; + +public class TestUtils { + public static void gc() { + // See RuntimeUtil#gc in jlibs (http://jlibs.in/) + Object obj = new Object(); + WeakReference ref = new WeakReference<>(obj); + //noinspection UnusedAssignment + obj = null; + while (ref.get() != null) { + System.gc(); + System.runFinalization(); + } + + System.gc(); + System.runFinalization(); + } +} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/LongStatsCollector.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/LongStatsCollector.java new file mode 100644 index 000000000000..ee98b4ba3b65 --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/LongStatsCollector.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.layoutlib.bridge.intensive.util.perf; + +import android.annotation.NonNull; +import android.util.LongArray; + +import java.util.Arrays; +import java.util.function.LongConsumer; + +/** + * Class that collect a series of longs and produces the median, min and max values. + */ +public class LongStatsCollector implements LongConsumer { + private final LongArray mAllValues; + private long mMin = Long.MAX_VALUE; + private long mMax = Long.MIN_VALUE; + public LongStatsCollector(int estimatedRuns) { + mAllValues = new LongArray(estimatedRuns); + } + + public int size() { + return mAllValues.size(); + } + + @NonNull + public Stats getStats() { + if (mAllValues.size() == 0) { + throw new IndexOutOfBoundsException("No data"); + } + + double median; + int size = mAllValues.size(); + long[] buffer = new long[size]; + for (int i = 0; i < size; i++) { + buffer[i] = mAllValues.get(i); + } + + Arrays.sort(buffer); + + int midPoint = size / 2; + median = (size % 2 == 0) ? (buffer[midPoint - 1] + buffer[midPoint]) / 2 : buffer[midPoint]; + + return new Stats(mAllValues.size(), mMin, mMax, median); + } + + @Override + public void accept(long value) { + mMin = Math.min(mMin, value); + mMax = Math.max(mMax, value); + mAllValues.add(value); + } + + public static class Stats { + private final int mSamples; + private final long mMin; + private final long mMax; + private final double mMedian; + + private Stats(int samples, long min, long max, double median) { + mSamples = samples; + mMin = min; + mMax = max; + mMedian = median; + } + + public int getSampleCount() { + return mSamples; + } + + public long getMin() { + return mMin; + } + + public long getMax() { + return mMax; + } + + public double getMedian() { + return mMedian; + } + } +} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/PerformanceRunner.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/PerformanceRunner.java new file mode 100644 index 000000000000..7225a10dbed4 --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/PerformanceRunner.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.layoutlib.bridge.intensive.util.perf; + +import org.junit.runner.Runner; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.Statement; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * JUnit {@link Runner} that times the test execution and produces some stats. + */ +public class PerformanceRunner extends BlockJUnit4ClassRunner { + private static final int DEFAULT_WARMUP_ITERATIONS = 50; + private static final int DEFAULT_RUNS = 100; + + private final int mWarmUpIterations; + private final int mRuns; + + public PerformanceRunner(Class<?> testClass) throws InitializationError { + super(testClass); + + Configuration classConfig = testClass.getAnnotation(Configuration.class); + mWarmUpIterations = classConfig != null && classConfig.warmUpIterations() != -1 ? + classConfig.warmUpIterations() : + DEFAULT_WARMUP_ITERATIONS; + mRuns = classConfig != null && classConfig.runs() != -1 ? + classConfig.runs() : + DEFAULT_RUNS; + } + + @Override + protected Statement methodInvoker(FrameworkMethod method, Object test) { + int warmUpIterations; + int runs; + + Configuration methodConfig = method.getAnnotation(Configuration.class); + warmUpIterations = methodConfig != null && methodConfig.warmUpIterations() != -1 ? + methodConfig.warmUpIterations() : + mWarmUpIterations; + runs = methodConfig != null && methodConfig.runs() != -1 ? + methodConfig.runs() : + mRuns; + return new TimedStatement(super.methodInvoker(method, test), warmUpIterations, runs, + (result) -> System.out.println(result.toString())); + } + + @Override + public void run(RunNotifier notifier) { + super.run(notifier); + } + + @Retention(RetentionPolicy.RUNTIME) + @Inherited + public @interface Configuration { + int warmUpIterations() default -1; + + int runs() default -1; + } +} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/TimedStatement.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/TimedStatement.java new file mode 100644 index 000000000000..77a2b0e50920 --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/TimedStatement.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.layoutlib.bridge.intensive.util.perf; + +import com.android.layoutlib.bridge.intensive.util.TestUtils; + +import org.junit.runners.model.Statement; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; + +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hashing; + +/** + * JUnit {@link Statement} used to measure some statistics about the test method. + */ +public class TimedStatement extends Statement { + private static final int CALIBRATION_WARMUP_ITERATIONS = 50; + private static final int CALIBRATION_RUNS = 100; + + private static boolean sIsCalibrated; + private static double sCalibrated; + + private final Statement mStatement; + private final int mWarmUpIterations; + private final int mRuns; + private final Runtime mRuntime = Runtime.getRuntime(); + private final Consumer<TimedStatementResult> mCallback; + + TimedStatement(Statement statement, int warmUpIterations, int runs, + Consumer<TimedStatementResult> finishedCallback) { + mStatement = statement; + mWarmUpIterations = warmUpIterations; + mRuns = runs; + mCallback = finishedCallback; + } + + /** + * The calibrate method tries to do some work that involves IO, memory allocations and some + * operations on the randomly generated data to calibrate the speed of the machine with + * something that resembles the execution of a test case. + */ + private static void calibrateMethod() throws IOException { + File tmpFile = File.createTempFile("test", "file"); + Random rnd = new Random(); + HashFunction hashFunction = Hashing.sha512(); + for (int i = 0; i < 5 + rnd.nextInt(5); i++) { + FileOutputStream stream = new FileOutputStream(tmpFile); + int bytes = 30000 + rnd.nextInt(60000); + byte[] buffer = new byte[bytes]; + + rnd.nextBytes(buffer); + byte acc = 0; + for (int j = 0; j < bytes; j++) { + acc += buffer[i]; + } + buffer[0] = acc; + stream.write(buffer); + System.gc(); + stream.close(); + FileInputStream input = new FileInputStream(tmpFile); + byte[] readBuffer = new byte[bytes]; + //noinspection ResultOfMethodCallIgnored + input.read(readBuffer); + buffer = readBuffer; + HashCode code1 = hashFunction.hashBytes(buffer); + Arrays.sort(buffer); + HashCode code2 = hashFunction.hashBytes(buffer); + input.close(); + + FileOutputStream hashStream = new FileOutputStream(tmpFile); + hashStream.write(code1.asBytes()); + hashStream.write(code2.asBytes()); + hashStream.close(); + } + } + + /** + * Runs the calibration process and sets the calibration measure in {@link #sCalibrated} + */ + private static void doCalibration() throws IOException { + System.out.println("Calibrating ..."); + TestUtils.gc(); + for (int i = 0; i < CALIBRATION_WARMUP_ITERATIONS; i++) { + calibrateMethod(); + } + + LongStatsCollector stats = new LongStatsCollector(CALIBRATION_RUNS); + for (int i = 0; i < CALIBRATION_RUNS; i++) { + TestUtils.gc(); + long start = System.currentTimeMillis(); + calibrateMethod(); + stats.accept(System.currentTimeMillis() - start); + } + + sCalibrated = stats.getStats().getMedian(); + sIsCalibrated = true; + System.out.printf(" DONE %fms\n", sCalibrated); + } + + private long getUsedMemory() { + return mRuntime.totalMemory() - mRuntime.freeMemory(); + } + + + @Override + public void evaluate() throws Throwable { + if (!sIsCalibrated) { + doCalibration(); + } + + for (int i = 0; i < mWarmUpIterations; i++) { + mStatement.evaluate(); + } + + LongStatsCollector timeStats = new LongStatsCollector(mRuns); + LongStatsCollector memoryUseStats = new LongStatsCollector(mRuns); + AtomicBoolean collectSamples = new AtomicBoolean(false); + + ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); + TestUtils.gc(); + executorService.scheduleAtFixedRate(() -> { + if (!collectSamples.get()) { + return; + } + memoryUseStats.accept(getUsedMemory()); + }, 0, 200, TimeUnit.MILLISECONDS); + + try { + for (int i = 0; i < mRuns; i++) { + TestUtils.gc(); + collectSamples.set(true); + long startTimeMs = System.currentTimeMillis(); + mStatement.evaluate(); + long stopTimeMs = System.currentTimeMillis(); + collectSamples.set(true); + timeStats.accept(stopTimeMs - startTimeMs); + + } + } finally { + executorService.shutdownNow(); + } + + TimedStatementResult result = new TimedStatementResult( + mWarmUpIterations, + mRuns, + sCalibrated, + timeStats.getStats(), + memoryUseStats.getStats()); + mCallback.accept(result); + } + +} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/TimedStatementResult.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/TimedStatementResult.java new file mode 100644 index 000000000000..59f90d295436 --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/TimedStatementResult.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.layoutlib.bridge.intensive.util.perf; + +import com.android.layoutlib.bridge.intensive.util.perf.LongStatsCollector.Stats; + +import java.text.DecimalFormat; + +/** + * Result value of a {@link TimedStatement} + */ +public class TimedStatementResult { + private static final DecimalFormat UNITS_FORMAT = new DecimalFormat("#.##"); + + private final int mWarmUpIterations; + private final int mRuns; + private final double mCalibrationTimeMs; + private final Stats mTimeStats; + private final Stats mMemoryStats; + + TimedStatementResult(int warmUpIterations, int runs, + double calibrationTimeMs, + Stats timeStats, + Stats memoryStats) { + mWarmUpIterations = warmUpIterations; + mRuns = runs; + mCalibrationTimeMs = calibrationTimeMs; + mTimeStats = timeStats; + mMemoryStats = memoryStats; + } + + @Override + public String toString() { + return String.format( + "Warm up %d. Runs %d\n" + "Time: %s ms (min: %s, max %s)\n" + + "Calibration Time: %f ms\n" + + "Calibrated Time: %s units (min: %s, max %s)\n" + + "Sampled %d times\n" + + " Memory used: %d bytes (max %d)\n\n", + mWarmUpIterations, mRuns, + mTimeStats.getMedian(), mTimeStats.getMin(), mTimeStats.getMax(), + mCalibrationTimeMs, + UNITS_FORMAT.format((mTimeStats.getMedian() / mCalibrationTimeMs) * 100000), + UNITS_FORMAT.format((mTimeStats.getMin() / mCalibrationTimeMs) * 100000), + UNITS_FORMAT.format((mTimeStats.getMax() / mCalibrationTimeMs) * 100000), + mMemoryStats.getSampleCount(), + (long)mMemoryStats.getMedian() - mMemoryStats.getMin(), + mMemoryStats.getMax() - mMemoryStats.getMin()); + } +} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index 92fd75cc5a36..7ba86fdc5c30 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -154,6 +154,8 @@ public final class CreateInfo implements ICreateInfo { "android.content.res.Resources#getIntArray", "android.content.res.Resources#getInteger", "android.content.res.Resources#getLayout", + "android.content.res.Resources#getQuantityString", + "android.content.res.Resources#getQuantityText", "android.content.res.Resources#getResourceEntryName", "android.content.res.Resources#getResourceName", "android.content.res.Resources#getResourcePackageName", @@ -232,6 +234,7 @@ public final class CreateInfo implements ICreateInfo { "android.view.RenderNode#nSetScaleY", "android.view.RenderNode#nGetScaleY", "android.view.RenderNode#nIsPivotExplicitlySet", + "android.view.PointerIcon#loadResource", "android.view.ViewGroup#drawChild", "com.android.internal.view.menu.MenuBuilder#createNewMenuItem", "com.android.internal.util.XmlUtils#convertValueToInt", diff --git a/tools/localedata/extract_icu_data.py b/tools/localedata/extract_icu_data.py index b071093a5615..9dceba2163eb 100755 --- a/tools/localedata/extract_icu_data.py +++ b/tools/localedata/extract_icu_data.py @@ -48,6 +48,8 @@ def read_likely_subtags(input_file_name): # they may be used by apps for other purposes.) "en_XA": "~~~A", "ar_XB": "~~~B", + # Removed data from later versions of ICU + "ji": "Hebr", # Old code for Yiddish, still used in Java and Android } representative_locales = { # Android's additions @@ -69,7 +71,7 @@ def read_likely_subtags(input_file_name): _, to_scr, to_region = get_locale_parts(to_locale) if from_lang == 'und': continue # not very useful for our purposes - if from_region is None and to_region != '001': + if from_region is None and to_region not in ['001', 'ZZ']: representative_locales.add(to_locale) if from_scr is None: likely_script_dict[from_locale] = to_scr |