diff options
| author | 2017-12-07 15:58:46 -0800 | |
|---|---|---|
| committer | 2017-12-07 17:23:25 -0800 | |
| commit | dc785052d0fb8a6651df25f42bf4254330445ce9 (patch) | |
| tree | df63f49030c9bd97f81de074da33ef943972eac6 | |
| parent | 1523386d85517ce655ff5c4ffb30c70c27bc3fc6 (diff) | |
AAPT2: Enable mangled symbol lookup in AssetManagerSymbolTable
Bug: 70045583
Test: make AaptTestNamespace_Split
Test: make aapt2_tests
Change-Id: I25da9d58736fc9090d1527782391c9b2220d2f8d
8 files changed, 201 insertions, 14 deletions
diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk index 94686c095bd8..2da294ce88ad 100644 --- a/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk +++ b/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk @@ -20,6 +20,7 @@ include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true LOCAL_AAPT_NAMESPACES := true LOCAL_PACKAGE_NAME := AaptTestNamespace_App +LOCAL_EXPORT_PACKAGE_RESOURCES := true LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under,src) LOCAL_STATIC_ANDROID_LIBRARIES := \ diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/res/values/values.xml b/tools/aapt2/integration-tests/NamespaceTest/App/res/values/values.xml index 1b80d9542881..174e746e55ce 100644 --- a/tools/aapt2/integration-tests/NamespaceTest/App/res/values/values.xml +++ b/tools/aapt2/integration-tests/NamespaceTest/App/res/values/values.xml @@ -26,4 +26,4 @@ @com.android.aapt.namespace.libtwo:string/public_string </item> </style> -</resources>
\ No newline at end of file +</resources> diff --git a/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk new file mode 100644 index 000000000000..a35f6edd77a5 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2017 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) + +include $(CLEAR_VARS) +LOCAL_USE_AAPT2 := true +LOCAL_AAPT_NAMESPACES := true +LOCAL_PACKAGE_NAME := AaptTestNamespace_Split +LOCAL_MODULE_TAGS := tests +LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_APK_LIBRARIES := AaptTestNamespace_App +LOCAL_RES_LIBRARIES := AaptTestNamespace_App +LOCAL_AAPT_FLAGS := --package-id 0x80 --rename-manifest-package com.android.aapt.namespace.app +include $(BUILD_PACKAGE) diff --git a/tools/aapt2/integration-tests/NamespaceTest/Split/AndroidManifest.xml b/tools/aapt2/integration-tests/NamespaceTest/Split/AndroidManifest.xml new file mode 100644 index 000000000000..bc9583b70ef8 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/Split/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.aapt.namespace.split" + featureSplit="split"> + + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="26"/> + + <application> + <activity android:name=".SplitActivity" android:theme="@style/ActivityTheme"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/tools/aapt2/integration-tests/NamespaceTest/Split/res/values/values.xml b/tools/aapt2/integration-tests/NamespaceTest/Split/res/values/values.xml new file mode 100644 index 000000000000..63da5529f757 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/Split/res/values/values.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 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. +--> + +<resources> + <string name="activity_name">Namespace Split</string> + + <style name="ActivityTheme" parent="com.android.aapt.namespace.libone:style/Theme"> + <item name="android:colorPrimary">#FF9800</item> + <item name="android:colorPrimaryDark">#E65100</item> + <item name="android:colorAccent">#FFD180</item> + </style> +</resources> diff --git a/tools/aapt2/integration-tests/NamespaceTest/Split/src/com/android/aapt/namespace/split/SplitActivity.java b/tools/aapt2/integration-tests/NamespaceTest/Split/src/com/android/aapt/namespace/split/SplitActivity.java new file mode 100644 index 000000000000..3fff3cf38dc4 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/Split/src/com/android/aapt/namespace/split/SplitActivity.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 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.aapt.namespace.split; + +import android.app.Activity; +import android.os.Bundle; + +public class SplitActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } +} diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp index 2d517c76944b..0cfc0bdfaaa6 100644 --- a/tools/aapt2/process/SymbolTable.cpp +++ b/tools/aapt2/process/SymbolTable.cpp @@ -30,7 +30,8 @@ #include "ValueVisitor.h" #include "util/Util.h" -using android::StringPiece; +using ::android::StringPiece; +using ::android::StringPiece16; namespace aapt { @@ -291,11 +292,34 @@ std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindByName( const std::u16string package16 = util::Utf8ToUtf16(name.package); const std::u16string type16 = util::Utf8ToUtf16(to_string(name.type)); const std::u16string entry16 = util::Utf8ToUtf16(name.entry); + const std::u16string mangled_entry16 = + util::Utf8ToUtf16(NameMangler::MangleEntry(name.package, name.entry)); + + uint32_t type_spec_flags; + ResourceId res_id; + + // There can be mangled resources embedded within other packages. Here we will + // look into each package and look-up the mangled name until we find the resource. + const size_t count = table.getBasePackageCount(); + for (size_t i = 0; i < count; i++) { + const android::String16 package_name = table.getBasePackageName(i); + StringPiece16 real_package16 = package16; + StringPiece16 real_entry16 = entry16; + std::u16string scratch_entry16; + if (StringPiece16(package_name) != package16) { + real_entry16 = mangled_entry16; + real_package16 = package_name.string(); + } + + type_spec_flags = 0; + res_id = table.identifierForName(real_entry16.data(), real_entry16.size(), type16.data(), + type16.size(), real_package16.data(), real_package16.size(), + &type_spec_flags); + if (res_id.is_valid()) { + break; + } + } - uint32_t type_spec_flags = 0; - ResourceId res_id = table.identifierForName( - entry16.data(), entry16.size(), type16.data(), type16.size(), - package16.data(), package16.size(), &type_spec_flags); if (!res_id.is_valid()) { return {}; } diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp index fd8a5080278b..1f59d7034300 100644 --- a/tools/aapt2/process/SymbolTable_test.cpp +++ b/tools/aapt2/process/SymbolTable_test.cpp @@ -16,7 +16,15 @@ #include "process/SymbolTable.h" +#include "SdkConstants.h" +#include "format/binary/TableFlattener.h" #include "test/Test.h" +#include "util/BigBuffer.h" + +using ::testing::Eq; +using ::testing::IsNull; +using ::testing::Ne; +using ::testing::NotNull; namespace aapt { @@ -30,13 +38,13 @@ TEST(ResourceTableSymbolSourceTest, FindSymbols) { .Build(); ResourceTableSymbolSource symbol_source(table.get()); - EXPECT_NE(nullptr, symbol_source.FindByName(test::ParseNameOrDie("android:id/foo"))); - EXPECT_NE(nullptr, symbol_source.FindByName(test::ParseNameOrDie("android:id/bar"))); + EXPECT_THAT(symbol_source.FindByName(test::ParseNameOrDie("android:id/foo")), NotNull()); + EXPECT_THAT(symbol_source.FindByName(test::ParseNameOrDie("android:id/bar")), NotNull()); std::unique_ptr<SymbolTable::Symbol> s = symbol_source.FindByName(test::ParseNameOrDie("android:attr/foo")); - ASSERT_NE(nullptr, s); - EXPECT_NE(nullptr, s->attribute); + ASSERT_THAT(s, NotNull()); + EXPECT_THAT(s->attribute, NotNull()); } TEST(ResourceTableSymbolSourceTest, FindPrivateAttrSymbol) { @@ -49,8 +57,8 @@ TEST(ResourceTableSymbolSourceTest, FindPrivateAttrSymbol) { ResourceTableSymbolSource symbol_source(table.get()); std::unique_ptr<SymbolTable::Symbol> s = symbol_source.FindByName(test::ParseNameOrDie("android:attr/foo")); - ASSERT_NE(nullptr, s); - EXPECT_NE(nullptr, s->attribute); + ASSERT_THAT(s, NotNull()); + EXPECT_THAT(s->attribute, NotNull()); } TEST(SymbolTableTest, FindByName) { @@ -64,8 +72,52 @@ TEST(SymbolTableTest, FindByName) { SymbolTable symbol_table(&mangler); symbol_table.AppendSource(util::make_unique<ResourceTableSymbolSource>(table.get())); - EXPECT_NE(nullptr, symbol_table.FindByName(test::ParseNameOrDie("id/foo"))); - EXPECT_NE(nullptr, symbol_table.FindByName(test::ParseNameOrDie("com.android.lib:id/foo"))); + EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("id/foo")), NotNull()); + EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.lib:id/foo")), NotNull()); +} + +TEST(SymbolTableTest, FindByNameWhenSymbolIsMangledInResTable) { + using namespace android; + + std::unique_ptr<IAaptContext> context = + test::ContextBuilder() + .SetCompilationPackage("com.android.app") + .SetPackageId(0x7f) + .SetPackageType(PackageType::kApp) + .SetMinSdkVersion(SDK_LOLLIPOP_MR1) + .SetNameManglerPolicy(NameManglerPolicy{"com.android.app"}) + .Build(); + + // Create a ResourceTable with a mangled resource, simulating a static library being merged into + // the main application package. + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .AddSimple("com.android.app:id/" + NameMangler::MangleEntry("com.android.lib", "foo"), + ResourceId(0x7f020000)) + .AddSimple("com.android.app:id/bar", ResourceId(0x7f020001)) + .Build(); + + BigBuffer buffer(1024u); + TableFlattener flattener({}, &buffer); + ASSERT_TRUE(flattener.Consume(context.get(), table.get())); + + std::unique_ptr<uint8_t[]> data = util::Copy(buffer); + + // Construct the test AssetManager. + auto asset_manager_source = util::make_unique<AssetManagerSymbolSource>(); + ResTable& res_table = const_cast<ResTable&>( + asset_manager_source->GetAssetManager()->getResources(false /*required*/)); + ASSERT_THAT(res_table.add(data.get(), buffer.size()), Eq(NO_ERROR)); + + SymbolTable symbol_table(context->GetNameMangler()); + symbol_table.AppendSource(std::move(asset_manager_source)); + + EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.lib:id/foo")), NotNull()); + EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.app:id/bar")), NotNull()); + + EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.app:id/foo")), IsNull()); + EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.lib:id/bar")), IsNull()); + EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.other:id/foo")), IsNull()); } } // namespace aapt |