summaryrefslogtreecommitdiff
path: root/tools/aapt2/java
diff options
context:
space:
mode:
authorRyan Mitchell <rtmitchell@google.com>2018-07-12 17:16:40 -0700
committerRyan Mitchell <rtmitchell@google.com>2018-07-13 11:19:56 -0700
commit23cc5d5dbecf34c205af40761ca762f3258f341f (patch)
treee137bef17cabb6139826fc2fc790217bac035755 /tools/aapt2/java
parent53208af20d501b892b9cc9971033a9f2e2d7cf35 (diff)
AAPT2: Fix R.java for styleable in different package
When generating the R.java file, attributes of styleables do not always have package names on them. This caused a problem where when an apk that was previously linked and that also contained a declare-styleable is linked again to an AndroidManifest.xml with a different package name, styleable attributes' resource symbols could not be looked up correctly. This change does not rename the resources but makes sure that the java generator finds the attribute symbols correctly. Bug: 110877419 Test: Created a test in aapt2_tests and verified correct behavior of repro example from bug Change-Id: Ib99d84cbe44dadca86603bc610ad3f4e09e3fb11
Diffstat (limited to 'tools/aapt2/java')
-rw-r--r--tools/aapt2/java/JavaClassGenerator.cpp17
-rw-r--r--tools/aapt2/java/JavaClassGenerator_test.cpp49
2 files changed, 63 insertions, 3 deletions
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index db1561e17f16..d1a70a75a44e 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -256,9 +256,20 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res
styleable_attr.field_name =
TransformNestedAttr(attr.name.value(), array_field_name, package_name_to_generate);
+ Reference ref = attr;
+ if (attr.name.value().package.empty()) {
+
+ // If the resource does not have a package name, set the package to the unmangled package name
+ // of the styleable declaration because attributes without package names would have been
+ // declared in the same package as the styleable.
+ ref.name = ResourceName(package_name_to_generate, ref.name.value().type,
+ ref.name.value().entry);
+ }
+
// Look up the symbol so that we can write out in the comments what are possible legal values
// for this attribute.
- const SymbolTable::Symbol* symbol = context_->GetExternalSymbols()->FindByReference(attr);
+ const SymbolTable::Symbol* symbol = context_->GetExternalSymbols()->FindByReference(ref);
+
if (symbol && symbol->attribute) {
// Copy the symbol data structure because the returned instance can be destroyed.
styleable_attr.symbol = *symbol;
@@ -303,7 +314,7 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res
const ResourceName& attr_name = entry.attr_ref->name.value();
styleable_comment << "<tr><td><code>{@link #" << entry.field_name << " "
<< (!attr_name.package.empty() ? attr_name.package
- : context_->GetCompilationPackage())
+ : package_name_to_generate)
<< ":" << attr_name.entry << "}</code></td>";
// Only use the comment up until the first '.'. This is to stay compatible with
@@ -374,7 +385,7 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res
StringPiece package_name = attr_name.package;
if (package_name.empty()) {
- package_name = context_->GetCompilationPackage();
+ package_name = package_name_to_generate;
}
std::unique_ptr<IntMember> index_member =
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 10a97d84f59d..fa208be120ed 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -107,6 +107,55 @@ TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
EXPECT_THAT(output, Not(HasSubstr("com_foo$two")));
}
+TEST(JavaClassGeneratorTest, StyleableAttributesWithDifferentPackageName) {
+ std::unique_ptr<ResourceTable> table =
+ test::ResourceTableBuilder()
+ .SetPackageId("android", 0x01)
+ .SetPackageId("app", 0x7f)
+ .AddValue("app:attr/foo", ResourceId(0x7f010000),
+ test::AttributeBuilder().Build())
+ .AddValue("app:attr/bar", ResourceId(0x7f010001),
+ test::AttributeBuilder().Build())
+ .AddValue("android:attr/baz", ResourceId(0x01010000),
+ test::AttributeBuilder().Build())
+ .AddValue("app:styleable/MyStyleable", ResourceId(0x7f030000),
+ test::StyleableBuilder()
+ .AddItem("app:attr/foo", ResourceId(0x7f010000))
+ .AddItem("attr/bar", ResourceId(0x7f010001))
+ .AddItem("android:attr/baz", ResourceId(0x01010000))
+ .Build())
+ .Build();
+
+ std::unique_ptr<IAaptContext> context =
+ test::ContextBuilder()
+ .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+ .SetNameManglerPolicy(NameManglerPolicy{"custom"})
+ .SetCompilationPackage("custom")
+ .Build();
+ JavaClassGenerator generator(context.get(), table.get(), {});
+
+ std::string output;
+ StringOutputStream out(&output);
+ EXPECT_TRUE(generator.Generate("app", &out));
+ out.Flush();
+
+ EXPECT_THAT(output, Not(HasSubstr("public static final int baz=0x01010000;")));
+ EXPECT_THAT(output, HasSubstr("public static final int foo=0x7f010000;"));
+ EXPECT_THAT(output, HasSubstr("public static final int bar=0x7f010001;"));
+
+ EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_android_baz=0;"));
+ EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_foo=1;"));
+ EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_bar=2;"));
+
+ EXPECT_THAT(output, HasSubstr("@link #MyStyleable_android_baz android:baz"));
+ EXPECT_THAT(output, HasSubstr("@link #MyStyleable_foo app:foo"));
+ EXPECT_THAT(output, HasSubstr("@link #MyStyleable_bar app:bar"));
+
+ EXPECT_THAT(output, HasSubstr("@link android.R.attr#baz"));
+ EXPECT_THAT(output, HasSubstr("@link app.R.attr#foo"));
+ EXPECT_THAT(output, HasSubstr("@link app.R.attr#bar"));
+}
+
TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()