Add function to return path for last resolved resource

After an AssetManager.FindEntry call is made, either directly or from any of the resource entry calls, a stack of the steps taken to resolve the resource is saved. Those steps can be retrieved as a log later on by calling AssetManager.GetLastResourceResolution, which returns a formatted string of the resource ID/name and path taken, including the configs and package names of each step.

Logging and the saving of the steps to memory can be enabled/disabled with the @hide .setResourceResolutionLoggingEnabled() method on AssetManager.

Bug: 122374289

Test: cases for single and multi ApkAssets loaded
Test: case for no resolution made
Test: made test app to display log on device
Test: added debugging call to source and ran through on-device apps

Change-Id: I6a32b8d4020c3f8510032ff7f431510089fff43f
diff --git a/libs/androidfw/ResourceUtils.cpp b/libs/androidfw/ResourceUtils.cpp
index d63feb01..645984d 100644
--- a/libs/androidfw/ResourceUtils.cpp
+++ b/libs/androidfw/ResourceUtils.cpp
@@ -48,4 +48,65 @@
          !(has_type_separator && out_type->empty());
 }
 
+bool ToResourceName(StringPoolRef& type_string_ref,
+                    StringPoolRef& entry_string_ref,
+                    const LoadedPackage* package,
+                    AssetManager2::ResourceName* out_name) {
+  out_name->package = package->GetPackageName().data();
+  out_name->package_len = package->GetPackageName().size();
+
+  out_name->type = type_string_ref.string8(&out_name->type_len);
+  out_name->type16 = nullptr;
+  if (out_name->type == nullptr) {
+    out_name->type16 = type_string_ref.string16(&out_name->type_len);
+    if (out_name->type16 == nullptr) {
+      return false;
+    }
+  }
+
+  out_name->entry = entry_string_ref.string8(&out_name->entry_len);
+  out_name->entry16 = nullptr;
+  if (out_name->entry == nullptr) {
+    out_name->entry16 = entry_string_ref.string16(&out_name->entry_len);
+    if (out_name->entry16 == nullptr) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+std::string ToFormattedResourceString(AssetManager2::ResourceName* resource_name) {
+  std::string result;
+  if (resource_name->package != nullptr) {
+    result.append(resource_name->package, resource_name->package_len);
+  }
+
+  if (resource_name->type != nullptr || resource_name->type16 != nullptr) {
+    if (!result.empty()) {
+      result += ":";
+    }
+
+    if (resource_name->type != nullptr) {
+      result.append(resource_name->type, resource_name->type_len);
+    } else {
+      result += util::Utf16ToUtf8(StringPiece16(resource_name->type16, resource_name->type_len));
+    }
+  }
+
+  if (resource_name->entry != nullptr || resource_name->entry16 != nullptr) {
+    if (!result.empty()) {
+      result += "/";
+    }
+
+    if (resource_name->entry != nullptr) {
+      result.append(resource_name->entry, resource_name->entry_len);
+    } else {
+      result += util::Utf16ToUtf8(StringPiece16(resource_name->entry16, resource_name->entry_len));
+    }
+  }
+
+  return result;
+}
+
 }  // namespace android