Performance improvements in AssetManager

Change the implementation of getLocales() to iterate the set of
configurations using a templated method, instead of using the result
of getConfigurations().

Also remove the check for AndroidManifest.xml when adding an asset path.
This is unneccessary.

Bug:28625993
Change-Id: I16de5da598d0c371421d1dc8eee054dce9baf53a
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index cf4ff82..12a6b0f 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1924,6 +1924,10 @@
 
     void print_value(const Package* pkg, const Res_value& value) const;
 
+    template <typename Func>
+    void forEachConfiguration(bool ignoreMipmap, bool ignoreAndroidPackage,
+                              bool includeSystemConfigs, const Func& f) const;
+
     mutable Mutex               mLock;
 
     // Mutex that controls access to the list of pre-filtered configurations
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 715c875..f50cff4 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -66,7 +66,6 @@
 static const char* kAppZipName = NULL; //"classes.jar";
 static const char* kSystemAssets = "framework/framework-res.apk";
 static const char* kResourceCache = "resource-cache";
-static const char* kAndroidManifest = "AndroidManifest.xml";
 
 static const char* kExcludeExtension = ".EXCLUDE";
 
@@ -203,16 +202,6 @@
     ALOGV("In %p Asset %s path: %s", this,
          ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string());
 
-    // Check that the path has an AndroidManifest.xml
-    Asset* manifestAsset = const_cast<AssetManager*>(this)->openNonAssetInPathLocked(
-            kAndroidManifest, Asset::ACCESS_BUFFER, ap);
-    if (manifestAsset == NULL) {
-        // This asset path does not contain any resources.
-        delete manifestAsset;
-        return false;
-    }
-    delete manifestAsset;
-
     ap.isSystemAsset = isSystemAsset;
     mAssetPaths.add(ap);
 
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 36b1f4b..d447a38 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -5822,10 +5822,11 @@
     return a.compare(b) < 0;
 }
 
-void ResTable::getConfigurations(Vector<ResTable_config>* configs, bool ignoreMipmap,
-        bool ignoreAndroidPackage, bool includeSystemConfigs) const {
+template <typename Func>
+void ResTable::forEachConfiguration(bool ignoreMipmap, bool ignoreAndroidPackage,
+                                    bool includeSystemConfigs, const Func& f) const {
     const size_t packageCount = mPackageGroups.size();
-    String16 android("android");
+    const String16 android("android");
     for (size_t i = 0; i < packageCount; i++) {
         const PackageGroup* packageGroup = mPackageGroups[i];
         if (ignoreAndroidPackage && android == packageGroup->name) {
@@ -5853,42 +5854,47 @@
                     memset(&cfg, 0, sizeof(ResTable_config));
                     cfg.copyFromDtoH(config->config);
 
-                    auto iter = std::lower_bound(configs->begin(), configs->end(), cfg,
-                                                 compareResTableConfig);
-                    if (iter == configs->end() || iter->compare(cfg) != 0) {
-                        configs->insertAt(cfg, std::distance(configs->begin(), iter));
-                    }
+                    f(cfg);
                 }
             }
         }
     }
 }
 
+void ResTable::getConfigurations(Vector<ResTable_config>* configs, bool ignoreMipmap,
+                                 bool ignoreAndroidPackage, bool includeSystemConfigs) const {
+    auto func = [&](const ResTable_config& cfg) {
+        const auto beginIter = configs->begin();
+        const auto endIter = configs->end();
+
+        auto iter = std::lower_bound(beginIter, endIter, cfg, compareResTableConfig);
+        if (iter == endIter || iter->compare(cfg) != 0) {
+            configs->insertAt(cfg, std::distance(beginIter, iter));
+        }
+    };
+    forEachConfiguration(ignoreMipmap, ignoreAndroidPackage, includeSystemConfigs, func);
+}
+
 static bool compareString8AndCString(const String8& str, const char* cStr) {
     return strcmp(str.string(), cStr) < 0;
 }
 
-void ResTable::getLocales(Vector<String8>* locales, bool includeSystemLocales) const
-{
-    Vector<ResTable_config> configs;
-    ALOGV("calling getConfigurations");
-    getConfigurations(&configs,
-            false /* ignoreMipmap */,
-            false /* ignoreAndroidPackage */,
-            includeSystemLocales /* includeSystemConfigs */);
-    ALOGV("called getConfigurations size=%d", (int)configs.size());
-    const size_t I = configs.size();
-
+void ResTable::getLocales(Vector<String8>* locales, bool includeSystemLocales) const {
     char locale[RESTABLE_MAX_LOCALE_LEN];
-    for (size_t i=0; i<I; i++) {
-        configs[i].getBcp47Locale(locale);
 
-        auto iter = std::lower_bound(locales->begin(), locales->end(), locale,
-                                     compareString8AndCString);
-        if (iter == locales->end() || strcmp(iter->string(), locale) != 0) {
-            locales->insertAt(String8(locale), std::distance(locales->begin(), iter));
+    forEachConfiguration(false, false, includeSystemLocales, [&](const ResTable_config& cfg) {
+        if (cfg.locale != 0) {
+            cfg.getBcp47Locale(locale);
+
+            const auto beginIter = locales->begin();
+            const auto endIter = locales->end();
+
+            auto iter = std::lower_bound(beginIter, endIter, locale, compareString8AndCString);
+            if (iter == endIter || strcmp(iter->string(), locale) != 0) {
+                locales->insertAt(String8(locale), std::distance(beginIter, iter));
+            }
         }
-    }
+    });
 }
 
 StringPoolRef::StringPoolRef(const ResStringPool* pool, uint32_t index)