Merge "AAPT2: Add workaround for non-standard package IDs" into oc-dev
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a18381b..5c9a01f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -21085,7 +21085,7 @@
*/
@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
- if (id < 0) {
+ if (id == NO_ID) {
return null;
}
return findViewTraversal(id);
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 09840a5..f661f29b 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -6664,6 +6664,10 @@
return NO_ERROR;
}
+void DynamicRefTable::addMapping(uint8_t buildPackageId, uint8_t runtimePackageId) {
+ mLookupTable[buildPackageId] = runtimePackageId;
+}
+
status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const {
uint32_t res = *resId;
size_t packageId = Res_GETPACKAGE(res) + 1;
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 306ff9a..7a6e37d 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1610,6 +1610,8 @@
// the given package.
status_t addMapping(const String16& packageName, uint8_t packageId);
+ void addMapping(uint8_t buildPackageId, uint8_t runtimePackageId);
+
// Performs the actual conversion of build-time resource ID to run-time
// resource ID.
status_t lookupResourceId(uint32_t* resId) const;
diff --git a/tests/FeatureSplit/feature1/AndroidManifest.xml b/tests/FeatureSplit/feature1/AndroidManifest.xml
index 42619b6..b87361f 100644
--- a/tests/FeatureSplit/feature1/AndroidManifest.xml
+++ b/tests/FeatureSplit/feature1/AndroidManifest.xml
@@ -16,7 +16,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.split.feature"
- featureName="feature1">
+ featureSplit="feature1">
<uses-sdk android:minSdkVersion="21" />
diff --git a/tests/FeatureSplit/feature1/res/layout/included.xml b/tests/FeatureSplit/feature1/res/layout/included.xml
new file mode 100644
index 0000000..c64bdb7
--- /dev/null
+++ b/tests/FeatureSplit/feature1/res/layout/included.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
diff --git a/tests/FeatureSplit/feature1/res/layout/main.xml b/tests/FeatureSplit/feature1/res/layout/main.xml
new file mode 100644
index 0000000..dbea42a
--- /dev/null
+++ b/tests/FeatureSplit/feature1/res/layout/main.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <include layout="@layout/included"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</FrameLayout>
diff --git a/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java b/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java
index def1339..61ac9df 100644
--- a/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java
+++ b/tests/FeatureSplit/feature1/src/com/android/test/split/feature/one/One.java
@@ -15,17 +15,16 @@
*/
package com.android.test.split.feature.one;
-import com.android.test.split.feature.ActivityMain;
-
+import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
-public class One extends ActivityMain {
+public class One extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ((TextView) findViewById(com.android.test.split.feature.R.id.text))
- .setText(R.string.feature_string);
+ setContentView(R.layout.main);
+ ((TextView) findViewById(R.id.text)).setText(R.string.feature_string);
}
}
diff --git a/tests/FeatureSplit/feature2/AndroidManifest.xml b/tests/FeatureSplit/feature2/AndroidManifest.xml
index b50044a..abd0b5e 100644
--- a/tests/FeatureSplit/feature2/AndroidManifest.xml
+++ b/tests/FeatureSplit/feature2/AndroidManifest.xml
@@ -16,7 +16,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.split.feature"
- featureName="feature2">
+ featureSplit="feature2">
<uses-sdk android:minSdkVersion="21" />
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 60b01e3..b872ebb 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -274,7 +274,13 @@
if (!attr.namespace_uri.empty()) {
std::cerr << attr.namespace_uri << ":";
}
- std::cerr << attr.name << "=" << attr.value << "\n";
+ std::cerr << attr.name;
+
+ if (attr.compiled_attribute) {
+ std::cerr << "(" << attr.compiled_attribute.value().id.value_or_default(ResourceId(0x0))
+ << ")";
+ }
+ std::cerr << "=" << attr.value << "\n";
}
const size_t previous_size = prefix_.size();
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index d44b3e0..f4d0226 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -573,10 +573,17 @@
// Write the ResTable header.
ChunkWriter table_writer(buffer_);
- ResTable_header* table_header =
- table_writer.StartChunk<ResTable_header>(RES_TABLE_TYPE);
+ ResTable_header* table_header = table_writer.StartChunk<ResTable_header>(RES_TABLE_TYPE);
table_header->packageCount = util::HostToDevice32(table->packages.size());
+ // Write a self mapping entry for this package if the ID is non-standard (0x7f).
+ if (context->GetPackageType() == PackageType::kApp) {
+ const uint8_t package_id = context->GetPackageId();
+ if (package_id != kFrameworkPackageId && package_id != kAppPackageId) {
+ table->included_packages_[package_id] = context->GetCompilationPackage();
+ }
+ }
+
// Flatten the values string pool.
StringPool::FlattenUtf8(table_writer.buffer(), table->string_pool);
diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp
index 8dff3a2..6d1350d 100644
--- a/tools/aapt2/flatten/TableFlattener_test.cpp
+++ b/tools/aapt2/flatten/TableFlattener_test.cpp
@@ -400,7 +400,7 @@
const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1);
ASSERT_NE(nullptr, dynamic_ref_table);
- const KeyedVector<String16, uint8_t> entries = dynamic_ref_table->entries();
+ const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table->entries();
ssize_t idx = entries.indexOfKey(android::String16("lib_one"));
ASSERT_GE(idx, 0);
@@ -411,6 +411,26 @@
EXPECT_EQ(0x03u, entries.valueAt(idx));
}
+TEST_F(TableFlattenerTest, PackageWithNonStandardIdHasDynamicRefTable) {
+ std::unique_ptr<IAaptContext> context =
+ test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x80).Build();
+ std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
+ .SetPackageId("app", 0x80)
+ .AddSimple("app:id/foo", ResourceId(0x80010000))
+ .Build();
+
+ ResTable result;
+ ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result));
+
+ const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1);
+ ASSERT_NE(nullptr, dynamic_ref_table);
+
+ const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table->entries();
+ ssize_t idx = entries.indexOfKey(android::String16("app"));
+ ASSERT_GE(idx, 0);
+ EXPECT_EQ(0x80u, entries.valueAt(idx));
+}
+
TEST_F(TableFlattenerTest, LongPackageNameIsTruncated) {
std::string kPackageName(256, 'F');
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index 494d9d2..f0613e7 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -35,13 +35,16 @@
.SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
.AddSymbolSource(
test::StaticSymbolSourceBuilder()
- .AddSymbol("android:attr/id", ResourceId(0x010100d0),
- test::AttributeBuilder().Build())
+ .AddPublicSymbol("android:attr/id", ResourceId(0x010100d0),
+ test::AttributeBuilder().Build())
.AddSymbol("com.app.test:id/id", ResourceId(0x7f020000))
.AddPublicSymbol("android:attr/paddingStart", ResourceId(0x010103b3),
test::AttributeBuilder().Build())
.AddPublicSymbol("android:attr/colorAccent", ResourceId(0x01010435),
test::AttributeBuilder().Build())
+ .AddSymbol("com.app.test.feature:id/foo", ResourceId(0x80020000))
+ .AddSymbol("com.app.test.feature:attr/foo", ResourceId(0x80010000),
+ test::AttributeBuilder().Build())
.Build())
.Build();
}
@@ -65,7 +68,7 @@
}
protected:
- std::unique_ptr<IAaptContext> context_;
+ std::unique_ptr<test::Context> context_;
};
TEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) {
@@ -218,14 +221,10 @@
EXPECT_EQ(tree.indexOfStyle(), 1);
}
-/*
- * The device ResXMLParser in libandroidfw differentiates between empty
- * namespace and null
- * namespace.
- */
+// The device ResXMLParser in libandroidfw differentiates between empty namespace and null
+// namespace.
TEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) {
- std::unique_ptr<xml::XmlResource> doc =
- test::BuildXmlDom("<View package=\"android\"/>");
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom("<View package=\"android\"/>");
android::ResXMLTree tree;
ASSERT_TRUE(Flatten(doc.get(), &tree));
@@ -261,4 +260,44 @@
EXPECT_NE(nullptr, tree.getAttributeStringValue(idx, &len));
}
+TEST_F(XmlFlattenerTest, FlattenNonStandardPackageId) {
+ context_->SetCompilationPackage("com.app.test.feature");
+ context_->SetPackageId(0x80);
+ context_->SetNameManglerPolicy({"com.app.test.feature"});
+
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
+ <View xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@id/foo"
+ app:foo="@id/foo" />)EOF");
+
+ XmlReferenceLinker linker;
+ ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
+
+ // The tree needs a custom DynamicRefTable since it is not using a standard app ID (0x7f).
+ android::DynamicRefTable dynamic_ref_table;
+ dynamic_ref_table.addMapping(0x80, 0x80);
+
+ android::ResXMLTree tree(&dynamic_ref_table);
+ ASSERT_TRUE(Flatten(doc.get(), &tree));
+
+ while (tree.next() != android::ResXMLTree::START_TAG) {
+ ASSERT_NE(android::ResXMLTree::BAD_DOCUMENT, tree.getEventType());
+ ASSERT_NE(android::ResXMLTree::END_DOCUMENT, tree.getEventType());
+ }
+
+ ssize_t idx;
+
+ idx = tree.indexOfAttribute(xml::kSchemaAndroid, "id");
+ ASSERT_GE(idx, 0);
+ EXPECT_EQ(idx, tree.indexOfID());
+ EXPECT_EQ(ResourceId(0x010100d0), ResourceId(tree.getAttributeNameResID(idx)));
+
+ idx = tree.indexOfAttribute(xml::kSchemaAuto, "foo");
+ ASSERT_GE(idx, 0);
+ EXPECT_EQ(ResourceId(0x80010000), ResourceId(tree.getAttributeNameResID(idx)));
+ EXPECT_EQ(android::Res_value::TYPE_REFERENCE, tree.getAttributeDataType(idx));
+ EXPECT_EQ(ResourceId(0x80020000), tree.getAttributeData(idx));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index 29d1838..0564db0 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -52,15 +52,27 @@
return compilation_package_.value();
}
+ void SetCompilationPackage(const android::StringPiece& package) {
+ compilation_package_ = package.to_string();
+ }
+
uint8_t GetPackageId() override {
CHECK(bool(package_id_)) << "package ID not set";
return package_id_.value();
}
+ void SetPackageId(uint8_t package_id) {
+ package_id_ = package_id;
+ }
+
NameMangler* GetNameMangler() override {
return &name_mangler_;
}
+ void SetNameManglerPolicy(const NameManglerPolicy& policy) {
+ name_mangler_ = NameMangler(policy);
+ }
+
bool IsVerbose() override {
return false;
}