AssetManager2: Add other support methods

- Add GetResourceConfigurations()
- Add GetResourceLocales()
- Add ResolveReference()
- Add stub for GetResourceId()
- Change LoadedArsc and ApkAssets factory method to return const

Test: make libandroidfw_tests
Change-Id: Ia797dc9381a523b1a3e7029048a413e544730379
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index d2eff65..542a125 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -18,6 +18,8 @@
 
 #include "androidfw/AssetManager2.h"
 
+#include <set>
+
 #include "android-base/logging.h"
 #include "android-base/stringprintf.h"
 #include "utils/ByteOrder.h"
@@ -143,6 +145,36 @@
   }
 }
 
+std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
+                                                                   bool exclude_mipmap) {
+  ATRACE_CALL();
+  std::set<ResTable_config> configurations;
+  for (const PackageGroup& package_group : package_groups_) {
+    for (const LoadedPackage* package : package_group.packages_) {
+      if (exclude_system && package->IsSystem()) {
+        continue;
+      }
+      package->CollectConfigurations(exclude_mipmap, &configurations);
+    }
+  }
+  return configurations;
+}
+
+std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
+                                                        bool merge_equivalent_languages) {
+  ATRACE_CALL();
+  std::set<std::string> locales;
+  for (const PackageGroup& package_group : package_groups_) {
+    for (const LoadedPackage* package : package_group.packages_) {
+      if (exclude_system && package->IsSystem()) {
+        continue;
+      }
+      package->CollectLocales(merge_equivalent_languages, &locales);
+    }
+  }
+  return locales;
+}
+
 std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, Asset::AccessMode mode) {
   const std::string new_path = "assets/" + filename;
   return OpenNonAsset(new_path, mode);
@@ -325,8 +357,15 @@
   if (dtohl(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) {
     if (!may_be_bag) {
       LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid);
+      return kInvalidCookie;
     }
-    return kInvalidCookie;
+
+    // Create a reference since we can't represent this complex type as a Res_value.
+    out_value->dataType = Res_value::TYPE_REFERENCE;
+    out_value->data = resid;
+    *out_selected_config = config;
+    *out_flags = flags;
+    return cookie;
   }
 
   const Res_value* device_value = reinterpret_cast<const Res_value*>(
@@ -341,6 +380,37 @@
   return cookie;
 }
 
+ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
+                                                ResTable_config* in_out_selected_config,
+                                                uint32_t* in_out_flags,
+                                                ResTable_ref* out_last_reference) {
+  ATRACE_CALL();
+  constexpr const int kMaxIterations = 20;
+
+  out_last_reference->ident = 0u;
+  for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE &&
+                              in_out_value->data != 0u && iteration < kMaxIterations;
+       iteration++) {
+    if (out_last_reference != nullptr) {
+      out_last_reference->ident = in_out_value->data;
+    }
+    uint32_t new_flags = 0u;
+    cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/,
+                         in_out_value, in_out_selected_config, &new_flags);
+    if (cookie == kInvalidCookie) {
+      return kInvalidCookie;
+    }
+    if (in_out_flags != nullptr) {
+      *in_out_flags |= new_flags;
+    }
+    if (out_last_reference->ident == in_out_value->data) {
+      // This reference can't be resolved, so exit now and let the caller deal with it.
+      return cookie;
+    }
+  }
+  return cookie;
+}
+
 const ResolvedBag* AssetManager2::GetBag(uint32_t resid) {
   ATRACE_CALL();
 
@@ -501,6 +571,15 @@
   return result;
 }
 
+uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
+                                      const std::string& fallback_type,
+                                      const std::string& fallback_package) {
+  (void)resource_name;
+  (void)fallback_type;
+  (void)fallback_package;
+  return 0u;
+}
+
 void AssetManager2::InvalidateCaches(uint32_t diff) {
   if (diff == 0xffffffffu) {
     // Everything must go.