New command line tool 'idmap'

Introduce a new tool 'idmap' to handle generation and verification of
idmap files. The tool is modelled on 'dexopt', and is intended to be
used similarly, notably by 'installd'.
See cmds/idmap/idmap.cpp for further documentation on 'idmap'.

Note: this commit is interdependent on a commit in project build/ to add
'idmap' to PRODUCT_PACKAGES.

Note: the changes to androidfw are only stubs. The actual implementation
will be provided in Runtime resource overlay, iteration 2.

Change-Id: I7131b74ece1e46c8a9c0a31d103e686aa07da2bb
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index a010957..e0c6183 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -69,6 +69,7 @@
  */
 class AssetManager : public AAssetManager {
 public:
+    static const char* RESOURCES_FILENAME;
     typedef enum CacheMode {
         CACHE_UNKNOWN = 0,
         CACHE_OFF,          // don't try to cache file locations
@@ -218,6 +219,13 @@
      */
     void getLocales(Vector<String8>* locales) const;
 
+    /**
+     * Generate idmap data to translate resources IDs between a package and a
+     * corresponding overlay package.
+     */
+    bool createIdmap(const char* targetApkPath, const char* overlayApkPath,
+        uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, uint32_t* outSize);
+
 private:
     struct asset_path
     {
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 6799766..7779f7f 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1545,9 +1545,19 @@
     // Return value: on success: NO_ERROR; caller is responsible for free-ing
     // outData (using free(3)). On failure, any status_t value other than
     // NO_ERROR; the caller should not free outData.
-    status_t createIdmap(const ResTable& overlay, uint32_t originalCrc, uint32_t overlayCrc,
+    status_t createIdmap(const ResTable& overlay, uint32_t targetCrc, uint32_t overlayCrc,
                          void** outData, size_t* outSize) const;
 
+    status_t createIdmap(const ResTable& overlay,
+            uint32_t targetCrc, uint32_t overlayCrc,
+            const char* targetPath, const char* overlayPath,
+            void** outData, uint32_t* outSize) const
+    {
+        (void)targetPath;
+        (void)overlayPath;
+        return createIdmap(overlay, targetCrc, overlayCrc, outData, outSize);
+    }
+
     enum {
         IDMAP_HEADER_SIZE_BYTES = 3 * sizeof(uint32_t),
     };
@@ -1556,7 +1566,18 @@
     // This function only requires the idmap header (the first
     // IDMAP_HEADER_SIZE_BYTES) bytes of an idmap file.
     static bool getIdmapInfo(const void* idmap, size_t size,
-                             uint32_t* pOriginalCrc, uint32_t* pOverlayCrc);
+                             uint32_t* pTargetCrc, uint32_t* pOverlayCrc);
+
+    static bool getIdmapInfo(const void* idmap, size_t size,
+            uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
+            String8* pTargetPath, String8* pOverlayPath)
+    {
+        if (*pTargetPath)
+            *pTargetPath = String8();
+        if (*pOverlayPath)
+            *pOverlayPath = String8();
+        return getIdmapInfo(idmap, size, pTargetCrc, pOverlayCrc);
+    }
 
     void print(bool inclValues) const;
     static String8 normalizeForOutput(const char* input);
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 08328d0..251d47b 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -83,6 +83,8 @@
 
 static volatile int32_t gCount = 0;
 
+const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
+
 namespace {
     // Transform string /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
     String8 idmapPathForPackagePath(const String8& pkgPath)
@@ -239,6 +241,29 @@
     return true;
 }
 
+bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath,
+        uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, uint32_t* outSize)
+{
+    AutoMutex _l(mLock);
+    const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) };
+    ResTable tables[2];
+
+    for (int i = 0; i < 2; ++i) {
+        asset_path ap;
+        ap.type = kFileTypeRegular;
+        ap.path = paths[i];
+        Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
+        if (ass == NULL) {
+            ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
+            return false;
+        }
+        tables[i].add(ass, (void*)1, false);
+    }
+
+    return tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
+            targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
+}
+
 bool AssetManager::isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
                                       const String8& idmapPath)
 {
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 72d331c..609ad19 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -5368,7 +5368,7 @@
                 | (0x00ff0000 & ((typeIndex+1)<<16))
                 | (0x0000ffff & (entryIndex));
             resource_name resName;
-            if (!this->getResourceName(resID, true, &resName)) {
+            if (!this->getResourceName(resID, false, &resName)) {
                 ALOGW("idmap: resource 0x%08x has spec but lacks values, skipping\n", resID);
                 // add dummy value, or trimming leading/trailing zeroes later will fail
                 vector.push(0);