Add generation of dependency file for .ap_ package

Make Aapt generate a dependency file in the same directory as the
output ap_ file if the --generate-dependencies flag is set.
This dependency file can then be read by the ant exec loop task
to see whether to repackage resources.

Change-Id: I763679414daf76369700aa599c26dcf78d4de099
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 9c5a514..864d47e 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1685,7 +1685,7 @@
         sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir));
         AaptGroupEntry group;
         count = assetAaptDir->slurpFullTree(bundle, assetRoot, group,
-                                            String8(), mFullResPaths);
+                                            String8(), mFullAssetPaths);
         if (count < 0) {
             totalCount = count;
             goto bail;
@@ -1759,7 +1759,7 @@
          * guarantees about ordering, so we're okay with an inorder search
          * using whatever order the OS happens to hand back to us.
          */
-        count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullResPaths);
+        count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullAssetPaths);
         if (count < 0) {
             /* failure; report error and remove archive */
             totalCount = count;
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index cdde5ad..9fafab4 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -550,6 +550,10 @@
     inline void
         setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; }
 
+    inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; }
+    inline void
+        setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; }
+
 private:
     String8 mPackage;
     SortedVector<AaptGroupEntry> mGroupEntries;
@@ -565,6 +569,7 @@
     KeyedVector<String8, sp<ResourceTypeSet> >* mRes;
 
     sp<FilePathStore> mFullResPaths;
+    sp<FilePathStore> mFullAssetPaths;
 };
 
 #endif // __AAPT_ASSETS_H
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 89f45df..8447d74 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -1390,10 +1390,13 @@
     // Load the assets.
     assets = new AaptAssets();
 
-    // Set up the resource gathering in assets if we're trying to make R.java
+    // Set up the resource gathering in assets if we're going to generate
+    // dependency files
     if (bundle->getGenDependencies()) {
-        sp<FilePathStore> pathStore = new FilePathStore;
-        assets->setFullResPaths(pathStore);
+        sp<FilePathStore> resPathStore = new FilePathStore;
+        assets->setFullResPaths(resPathStore);
+        sp<FilePathStore> assetPathStore = new FilePathStore;
+        assets->setFullAssetPaths(assetPathStore);
     }
 
     err = assets->slurpFromArgs(bundle);
@@ -1420,9 +1423,16 @@
     }
 
     if (bundle->getGenDependencies()) {
-        dependencyFile = String8(bundle->getRClassDir());
+        if (outputAPKFile) {
+            dependencyFile = String8(outputAPKFile);
+            // Strip the extension and add new one
+            dependencyFile = dependencyFile.getBasePath();
+            dependencyFile.append(".d");
+        } else {
+            dependencyFile = String8(bundle->getRClassDir());
+            dependencyFile.appendPath("R.d");
+        }
         // Make sure we have a clean dependency file to start with
-        dependencyFile.appendPath("R.d");
         fp = fopen(dependencyFile, "w");
         fclose(fp);
     }
@@ -1460,19 +1470,6 @@
         }
     }
 
-    if (bundle->getGenDependencies()) {
-        // Now that writeResourceSymbols has taken care of writing the
-        // dependency targets to the dependencyFile, we'll write the
-        // pre-requisites.
-        fp = fopen(dependencyFile, "a+");
-        fprintf(fp, " : ");
-        err = writeDependencyPreReqs(bundle, assets, fp);
-
-        // Also manually add the AndroidManifeset since it's a non-asset
-        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
-        fclose(fp);
-    }
-
     // Write out the ProGuard file
     err = writeProguardFile(bundle, assets);
     if (err < 0) {
@@ -1488,6 +1485,18 @@
         }
     }
 
+    if (bundle->getGenDependencies()) {
+        // Now that writeResourceSymbols or writeAPK has taken care of writing
+        // the targets to our dependency file, we'll write the prereqs
+        fp = fopen(dependencyFile, "a+");
+        fprintf(fp, " : ");
+        bool includeRaw = (outputAPKFile != NULL);
+        err = writeDependencyPreReqs(bundle, assets, fp, includeRaw);
+        // Also manually add the AndroidManifeset since it's a non-asset
+        fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
+        fclose(fp);
+    }
+
     retVal = 0;
 bail:
     if (SourcePos::hasErrors()) {
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 8edb5b5..9887268 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -148,7 +148,7 @@
         "   --extra-packages\n"
         "       generate R.java for libraries. Separate libraries with ':'.\n"
         "   --generate-dependencies\n"
-        "       generate a dependency file for R.java.\n"
+        "       generate dependency files in the same directories for R.java and resource package\n"
         "   --auto-add-overlay\n"
         "       Automatically add resources that are only in overlays.\n"
         "   --rename-manifest-package\n"
diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h
index 1df1144..9674c5d 100644
--- a/tools/aapt/Main.h
+++ b/tools/aapt/Main.h
@@ -46,5 +46,6 @@
 String8 getAttribute(const ResXMLTree& tree, const char* ns,
                             const char* attr, String8* outError);
 
-status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp);
+status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets,
+                                FILE* fp, bool includeRaw);
 #endif // __MAIN_H
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index 999a5cf..6e2a25c 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -172,6 +172,16 @@
         }
     }
 
+    if (bundle->getGenDependencies()) {
+        // Add this file to the dependency file
+        String8 dependencyFile = outputFile.getBasePath();
+        dependencyFile.append(".d");
+
+        FILE* fp = fopen(dependencyFile.string(), "a");
+        fprintf(fp, "%s \\\n", outputFile.string());
+        fclose(fp);
+    }
+
     assert(result == NO_ERROR);
 
 bail:
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index a603314..6e86112 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -2187,15 +2187,26 @@
     return err;
 }
 
-status_t
-writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp)
+// Loops through the string paths and writes them to the file pointer
+// Each file path is written on its own line with a terminating backslash.
+status_t writePathsToFile(const sp<FilePathStore>& files, FILE* fp)
 {
     status_t deps = -1;
-    sp<FilePathStore> files = assets->getFullResPaths();
     for (size_t file_i = 0; file_i < files->size(); ++file_i) {
         // Add the full file path to the dependency file
         fprintf(fp, "%s \\\n", files->itemAt(file_i).string());
         deps++;
     }
     return deps;
-}
\ No newline at end of file
+}
+
+status_t
+writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp, bool includeRaw)
+{
+    status_t deps = -1;
+    deps += writePathsToFile(assets->getFullResPaths(), fp);
+    if (includeRaw) {
+        deps += writePathsToFile(assets->getFullAssetPaths(), fp);
+    }
+    return deps;
+}
diff --git a/tools/aapt/ZipFile.h b/tools/aapt/ZipFile.h
index 7877550..dbbd072 100644
--- a/tools/aapt/ZipFile.h
+++ b/tools/aapt/ZipFile.h
@@ -57,7 +57,7 @@
     /*
      * Open a new or existing archive.
      */
-    enum {
+    typedef enum {
         kOpenReadOnly   = 0x01,
         kOpenReadWrite  = 0x02,
         kOpenCreate     = 0x04,     // create if it doesn't exist