Merge "AAPT2: Remove the need for specifying package name in compile phase" into mnc-dev
diff --git a/tools/aapt2/BinaryResourceParser.cpp b/tools/aapt2/BinaryResourceParser.cpp
index 3559f43..4f1947a 100644
--- a/tools/aapt2/BinaryResourceParser.cpp
+++ b/tools/aapt2/BinaryResourceParser.cpp
@@ -116,9 +116,11 @@
 BinaryResourceParser::BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
                                            const std::shared_ptr<IResolver>& resolver,
                                            const Source& source,
+                                           const std::u16string& defaultPackage,
                                            const void* data,
                                            size_t len) :
-        mTable(table), mResolver(resolver), mSource(source), mData(data), mDataLen(len) {
+        mTable(table), mResolver(resolver), mSource(source), mDefaultPackage(defaultPackage),
+        mData(data), mDataLen(len) {
 }
 
 bool BinaryResourceParser::parse() {
@@ -177,6 +179,9 @@
             if (!type) {
                 return false;
             }
+            if (outSymbol->package.empty()) {
+                outSymbol->package = mTable->getPackage();
+            }
             outSymbol->type = *type;
 
             // Since we scan the symbol table in order, we can start looking for the
@@ -350,7 +355,22 @@
 
     size_t len = strnlen16(reinterpret_cast<const char16_t*>(packageHeader->name),
             sizeof(packageHeader->name) / sizeof(packageHeader->name[0]));
-    mTable->setPackage(StringPiece16(reinterpret_cast<const char16_t*>(packageHeader->name), len));
+    if (mTable->getPackage().empty() && len == 0) {
+        mTable->setPackage(mDefaultPackage);
+    } else if (len > 0) {
+        StringPiece16 thisPackage(reinterpret_cast<const char16_t*>(packageHeader->name), len);
+        if (mTable->getPackage().empty()) {
+            mTable->setPackage(thisPackage);
+        } else if (thisPackage != mTable->getPackage()) {
+            Logger::error(mSource)
+                    << "incompatible packages: "
+                    << mTable->getPackage()
+                    << " vs. "
+                    << thisPackage
+                    << std::endl;
+            return false;
+        }
+    }
 
     ResChunkPullParser parser(getChunkData(packageHeader->header),
                               getChunkDataLen(packageHeader->header));
diff --git a/tools/aapt2/BinaryResourceParser.h b/tools/aapt2/BinaryResourceParser.h
index 32876cd..3aab301 100644
--- a/tools/aapt2/BinaryResourceParser.h
+++ b/tools/aapt2/BinaryResourceParser.h
@@ -45,6 +45,7 @@
     BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
                          const std::shared_ptr<IResolver>& resolver,
                          const Source& source,
+                         const std::u16string& defaultPackage,
                          const void* data, size_t len);
 
     BinaryResourceParser(const BinaryResourceParser&) = delete; // No copy.
@@ -97,12 +98,12 @@
 
     const Source mSource;
 
+    // The package name of the resource table.
+    std::u16string mDefaultPackage;
+
     const void* mData;
     const size_t mDataLen;
 
-    // The package name of the resource table.
-    std::u16string mPackage;
-
     // The array of symbol entries. Each element points to an offset
     // in the table and an index into the symbol table string pool.
     const SymbolTable_entry* mSymbolEntries = nullptr;
diff --git a/tools/aapt2/Linker.cpp b/tools/aapt2/Linker.cpp
index f3f04a5..c37cc93 100644
--- a/tools/aapt2/Linker.cpp
+++ b/tools/aapt2/Linker.cpp
@@ -160,7 +160,7 @@
 void Linker::visit(Reference& reference, ValueVisitorArgs& a) {
     Args& args = static_cast<Args&>(a);
 
-    if (!reference.name.isValid()) {
+    if (reference.name.entry.empty()) {
         // We can't have a completely bad reference.
         if (!reference.id.isValid()) {
             Logger::error() << "srsly? " << args.referrer << std::endl;
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 41c229d..54a7329 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -756,8 +756,8 @@
                 zipFile->uncompress(entry));
         assert(uncompressedData);
 
-        BinaryResourceParser parser(table, resolver, source, uncompressedData.get(),
-                                    entry->getUncompressedLen());
+        BinaryResourceParser parser(table, resolver, source, options.appInfo.package, 
+                                    uncompressedData.get(), entry->getUncompressedLen());
         if (!parser.parse()) {
             return false;
         }
@@ -1085,50 +1085,47 @@
     }
 
     bool isStaticLib = false;
+    if (options.phase == AaptOptions::Phase::Link) {
+        flag::requiredFlag("--manifest", "AndroidManifest.xml of your app",
+                [&options](const StringPiece& arg) {
+                    options.manifest = Source{ arg.toString() };
+                });
+
+        flag::optionalFlag("-I", "add an Android APK to link against",
+                [&options](const StringPiece& arg) {
+                    options.libraries.push_back(Source{ arg.toString() });
+                });
+
+        flag::optionalFlag("--java", "directory in which to generate R.java",
+                [&options](const StringPiece& arg) {
+                    options.generateJavaClass = Source{ arg.toString() };
+                });
+
+        flag::optionalFlag("--proguard", "file in which to output proguard rules",
+                [&options](const StringPiece& arg) {
+                    options.generateProguardRules = Source{ arg.toString() };
+                });
+
+        flag::optionalSwitch("--static-lib", "generate a static Android library", true,
+                             &isStaticLib);
+
+        flag::optionalFlag("--binding", "Output directory for binding XML files",
+                [&options](const StringPiece& arg) {
+                    options.bindingOutput = Source{ arg.toString() };
+                });
+        flag::optionalSwitch("--no-version", "Disables automatic style and layout versioning",
+                             false, &options.versionStylesAndLayouts);
+    }
+
     if (options.phase == AaptOptions::Phase::Compile ||
             options.phase == AaptOptions::Phase::Link) {
-        if (options.phase == AaptOptions::Phase::Compile) {
-            flag::requiredFlag("--package", "Android package name",
-                    [&options](const StringPiece& arg) {
-                        options.appInfo.package = util::utf8ToUtf16(arg);
-                    });
-        } else if (options.phase == AaptOptions::Phase::Link) {
-            flag::requiredFlag("--manifest", "AndroidManifest.xml of your app",
-                    [&options](const StringPiece& arg) {
-                        options.manifest = Source{ arg.toString() };
-                    });
-
-            flag::optionalFlag("-I", "add an Android APK to link against",
-                    [&options](const StringPiece& arg) {
-                        options.libraries.push_back(Source{ arg.toString() });
-                    });
-
-            flag::optionalFlag("--java", "directory in which to generate R.java",
-                    [&options](const StringPiece& arg) {
-                        options.generateJavaClass = Source{ arg.toString() };
-                    });
-
-            flag::optionalFlag("--proguard", "file in which to output proguard rules",
-                    [&options](const StringPiece& arg) {
-                        options.generateProguardRules = Source{ arg.toString() };
-                    });
-
-            flag::optionalSwitch("--static-lib", "generate a static Android library", true,
-                                 &isStaticLib);
-
-            flag::optionalFlag("--binding", "Output directory for binding XML files",
-                    [&options](const StringPiece& arg) {
-                        options.bindingOutput = Source{ arg.toString() };
-                    });
-            flag::optionalSwitch("--no-version", "Disables automatic style and layout versioning",
-                                 false, &options.versionStylesAndLayouts);
-        }
-
         // Common flags for all steps.
         flag::requiredFlag("-o", "Output path", [&options](const StringPiece& arg) {
             options.output = Source{ arg.toString() };
         });
-    } else if (options.phase == AaptOptions::Phase::DumpStyleGraph) {
+    }
+
+    if (options.phase == AaptOptions::Phase::DumpStyleGraph) {
         flag::requiredFlag("--style", "Name of the style to dump",
                 [&options](const StringPiece& arg, std::string* outError) -> bool {
                     Reference styleReference;
@@ -1191,7 +1188,7 @@
                 zipFile->uncompress(entry));
         assert(uncompressedData);
 
-        BinaryResourceParser parser(table, resolver, source, uncompressedData.get(),
+        BinaryResourceParser parser(table, resolver, source, {}, uncompressedData.get(),
                                     entry->getUncompressedLen());
         if (!parser.parse()) {
             return false;
@@ -1223,16 +1220,17 @@
         if (!loadAppInfo(options.manifest, &options.appInfo)) {
             return false;
         }
-    }
 
-    // Verify we have some common options set.
-    if (options.appInfo.package.empty()) {
-        Logger::error() << "no package name specified." << std::endl;
-        return false;
+        if (options.appInfo.package.empty()) {
+            Logger::error() << "no package name specified." << std::endl;
+            return false;
+        }
     }
 
     // Every phase needs a resource table.
     std::shared_ptr<ResourceTable> table = std::make_shared<ResourceTable>();
+
+    // The package name is empty when in the compile phase.
     table->setPackage(options.appInfo.package);
     if (options.appInfo.package == u"android") {
         table->setPackageId(0x01);
diff --git a/tools/aapt2/TableFlattener.cpp b/tools/aapt2/TableFlattener.cpp
index 539c48f..b7c04f0 100644
--- a/tools/aapt2/TableFlattener.cpp
+++ b/tools/aapt2/TableFlattener.cpp
@@ -79,7 +79,7 @@
 
         // Write the key.
         if (!Res_INTERNALID(key.id.id) && !key.id.isValid()) {
-            assert(key.name.isValid());
+            assert(!key.name.entry.empty());
             mSymbols->push_back(std::make_pair(ResourceNameRef(key.name),
                     mOut->size() - sizeof(*outMapEntry)));
         }
@@ -284,13 +284,6 @@
 bool TableFlattener::flatten(BigBuffer* out, const ResourceTable& table) {
     const size_t beginning = out->size();
 
-    if (table.getPackage().size() == 0) {
-        Logger::error()
-                << "ResourceTable has no package name."
-                << std::endl;
-        return false;
-    }
-
     if (table.getPackageId() == ResourceTable::kUnsetPackageId) {
         Logger::error()
                 << "ResourceTable has no package ID set."
diff --git a/tools/aapt2/data/Makefile b/tools/aapt2/data/Makefile
index 3387135..91ff5fe 100644
--- a/tools/aapt2/data/Makefile
+++ b/tools/aapt2/data/Makefile
@@ -50,7 +50,7 @@
 # returns: out/values-v4.apk: res/values-v4/styles.xml res/values-v4/colors.xml
 define make-collect-rule
 $(LOCAL_OUT)/$1.apk: $(filter $(LOCAL_RESOURCE_DIR)/$1/%,$(PRIVATE_RESOURCES))
-	$(AAPT) compile --package $(LOCAL_PACKAGE) -o $$@ $$^
+	$(AAPT) compile -o $$@ $$^
 endef
 
 # Collect: out/values-v4.apk <- res/values-v4/styles.xml res/values-v4/colors.xml
diff --git a/tools/aapt2/data/lib/Makefile b/tools/aapt2/data/lib/Makefile
index 372c225..741be9a 100644
--- a/tools/aapt2/data/lib/Makefile
+++ b/tools/aapt2/data/lib/Makefile
@@ -48,7 +48,7 @@
 # returns: out/values-v4.apk: res/values-v4/styles.xml res/values-v4/colors.xml
 define make-collect-rule
 $(LOCAL_OUT)/$1.apk: $(filter $(LOCAL_RESOURCE_DIR)/$1/%,$(PRIVATE_RESOURCES))
-	$(AAPT) compile --package $(LOCAL_PACKAGE) -o $$@ $$^
+	$(AAPT) compile -o $$@ $$^
 endef
 
 # Collect: out/values-v4.apk <- res/values-v4/styles.xml res/values-v4/colors.xml