Move AssetsProvider to native layer

Querying in the native layer for assets provided through
AssetsProviders does not currently work. This change refactors the
AssetProvider API to return a file descriptor that is read in the
native layer and can bubble up to the java layer.

This change also removes the InputStream API to favor of developers
using memfd_create.

Bug: 142716192
Test: atest ResourceLoaderValuesTest
Change-Id: I1a7eca0994c3b7cc32008d9a72bf91086ff0e816
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index f5bf84f..202651d 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -144,8 +144,8 @@
   }
 
  protected:
-    std::unique_ptr<Asset> OpenInternal(
-        const std::string& path, Asset::AccessMode mode, bool* file_exists) const override {
+  std::unique_ptr<Asset> OpenInternal(
+      const std::string& path, Asset::AccessMode mode, bool* file_exists) const override {
     if (file_exists) {
       *file_exists = false;
     }
@@ -292,49 +292,91 @@
   DISALLOW_COPY_AND_ASSIGN(EmptyAssetsProvider);
 };
 
-std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path,
-                                                 const package_property_t flags) {
+// AssetProvider implementation
+class MultiAssetsProvider : public AssetsProvider {
+ public:
+  ~MultiAssetsProvider() override = default;
+
+  static std::unique_ptr<const AssetsProvider> Create(
+      std::unique_ptr<const AssetsProvider> child, std::unique_ptr<const AssetsProvider> parent) {
+    CHECK(parent != nullptr) << "parent provider must not be null";
+    return (!child) ? std::move(parent)
+                    : std::unique_ptr<const AssetsProvider>(new MultiAssetsProvider(
+                        std::move(child), std::move(parent)));
+  }
+
+  bool ForEachFile(const std::string& root_path,
+                   const std::function<void(const StringPiece&, FileType)>& f) const override {
+    // TODO: Only call the function once for files defined in the parent and child
+    return child_->ForEachFile(root_path, f) && parent_->ForEachFile(root_path, f);
+  }
+
+ protected:
+  std::unique_ptr<Asset> OpenInternal(
+      const std::string& path, Asset::AccessMode mode, bool* file_exists) const override {
+    auto asset = child_->Open(path, mode, file_exists);
+    return (asset) ? std::move(asset) : parent_->Open(path, mode, file_exists);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MultiAssetsProvider);
+
+  MultiAssetsProvider(std::unique_ptr<const AssetsProvider> child,
+                      std::unique_ptr<const AssetsProvider> parent)
+                      : child_(std::move(child)), parent_(std::move(parent)) { }
+
+  std::unique_ptr<const AssetsProvider> child_;
+  std::unique_ptr<const AssetsProvider> parent_;
+};
+
+// Opens the archive using the file path. Calling CloseArchive on the zip handle will close the
+// file.
+std::unique_ptr<const ApkAssets> ApkAssets::Load(
+    const std::string& path, const package_property_t flags,
+    std::unique_ptr<const AssetsProvider> override_asset) {
   auto assets = ZipAssetsProvider::Create(path);
-  return (assets) ? LoadImpl(std::move(assets), path, nullptr /*idmap_asset*/,
-                             nullptr /*loaded_idmap*/, flags)
+  return (assets) ? LoadImpl(std::move(assets), path, flags, std::move(override_asset))
                   : nullptr;
 }
 
-std::unique_ptr<const ApkAssets> ApkAssets::LoadFromFd(unique_fd fd,
-                                                       const std::string& friendly_name,
-                                                       const package_property_t flags,
-                                                       const off64_t offset,
-                                                       const off64_t length) {
+// Opens the archive using the file file descriptor with the specified file offset and read length.
+// If the `assume_ownership` parameter is 'true' calling CloseArchive will close the file.
+std::unique_ptr<const ApkAssets> ApkAssets::LoadFromFd(
+    unique_fd fd, const std::string& friendly_name, const package_property_t flags,
+    std::unique_ptr<const AssetsProvider> override_asset, const off64_t offset,
+    const off64_t length) {
   CHECK(length >= kUnknownLength) << "length must be greater than or equal to " << kUnknownLength;
   CHECK(length != kUnknownLength || offset == 0) << "offset must be 0 if length is "
                                                  << kUnknownLength;
+
   auto assets = ZipAssetsProvider::Create(std::move(fd), friendly_name, offset, length);
-  return (assets) ? LoadImpl(std::move(assets), friendly_name, nullptr /*idmap_asset*/,
-                             nullptr /*loaded_idmap*/, flags)
+  return (assets) ? LoadImpl(std::move(assets), friendly_name, flags, std::move(override_asset))
                   : nullptr;
 }
 
-std::unique_ptr<const ApkAssets> ApkAssets::LoadTable(const std::string& path,
-                                                      const package_property_t flags) {
-  auto resources_asset = CreateAssetFromFile(path);
-  return (resources_asset) ? LoadTableImpl(std::move(resources_asset), path, flags)
-                           : nullptr;
+std::unique_ptr<const ApkAssets> ApkAssets::LoadTable(
+    const std::string& path, const package_property_t flags,
+    std::unique_ptr<const AssetsProvider> override_asset) {
+
+  auto assets = CreateAssetFromFile(path);
+  return (assets) ? LoadTableImpl(std::move(assets), path, flags, std::move(override_asset))
+                  : nullptr;
 }
 
-std::unique_ptr<const ApkAssets> ApkAssets::LoadTableFromFd(unique_fd fd,
-                                                            const std::string& friendly_name,
-                                                            const package_property_t flags,
-                                                            const off64_t offset,
-                                                            const off64_t length) {
-  auto resources_asset = CreateAssetFromFd(std::move(fd), nullptr /* path */, offset, length);
-  return (resources_asset) ? LoadTableImpl(std::move(resources_asset), friendly_name, flags)
-                           : nullptr;
+std::unique_ptr<const ApkAssets> ApkAssets::LoadTableFromFd(
+    unique_fd fd, const std::string& friendly_name, const package_property_t flags,
+    std::unique_ptr<const AssetsProvider> override_asset, const off64_t offset,
+    const off64_t length) {
+
+  auto assets = CreateAssetFromFd(std::move(fd), nullptr /* path */, offset, length);
+  return (assets) ? LoadTableImpl(std::move(assets), friendly_name, flags,
+                                  std::move(override_asset))
+                  : nullptr;
 }
 
 std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
                                                         const package_property_t flags) {
   CHECK((flags & PROPERTY_LOADER) == 0U) << "Cannot load RROs through loaders";
-
   std::unique_ptr<Asset> idmap_asset = CreateAssetFromFile(idmap_path);
   if (idmap_asset == nullptr) {
     return {};
@@ -351,23 +393,28 @@
   
   auto overlay_path = loaded_idmap->OverlayApkPath();
   auto assets = ZipAssetsProvider::Create(overlay_path);
-  return (assets) ? LoadImpl(std::move(assets), overlay_path, std::move(idmap_asset),
-                             std::move(loaded_idmap), flags | PROPERTY_OVERLAY)
+  return (assets) ? LoadImpl(std::move(assets), overlay_path, flags | PROPERTY_OVERLAY,
+                             nullptr /* override_asset */, std::move(idmap_asset),
+                             std::move(loaded_idmap))
                   : nullptr;
 }
 
-std::unique_ptr<const ApkAssets> ApkAssets::LoadFromDir(const std::string& path,
-                                                        const package_property_t flags) {
+std::unique_ptr<const ApkAssets> ApkAssets::LoadFromDir(
+    const std::string& path, const package_property_t flags,
+    std::unique_ptr<const AssetsProvider> override_asset) {
+
   auto assets = DirectoryAssetsProvider::Create(path);
-  return (assets) ? LoadImpl(std::move(assets), path, nullptr /*idmap_asset*/,
-                             nullptr /*loaded_idmap*/, flags)
+  return (assets) ? LoadImpl(std::move(assets), path, flags, std::move(override_asset))
                   : nullptr;
 }
 
-std::unique_ptr<const ApkAssets> ApkAssets::LoadEmpty(const package_property_t flags) {
-  std::unique_ptr<ApkAssets> loaded_apk(new ApkAssets(
-      std::unique_ptr<AssetsProvider>(new EmptyAssetsProvider()), "empty" /* path */,
-                                      -1 /* last_mod-time */, flags));
+std::unique_ptr<const ApkAssets> ApkAssets::LoadEmpty(
+    const package_property_t flags, std::unique_ptr<const AssetsProvider> override_asset) {
+
+  auto assets = (override_asset) ? std::move(override_asset)
+                                 : std::unique_ptr<const AssetsProvider>(new EmptyAssetsProvider());
+  std::unique_ptr<ApkAssets> loaded_apk(new ApkAssets(std::move(assets), "empty" /* path */,
+                                                      -1 /* last_mod-time */, flags));
   loaded_apk->loaded_arsc_ = LoadedArsc::CreateEmpty();
   // Need to force a move for mingw32.
   return std::move(loaded_apk);
@@ -413,27 +460,30 @@
                                           Asset::AccessMode::ACCESS_RANDOM);
 }
 
-std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<const AssetsProvider> assets,
-                                                     const std::string& path,
-                                                     std::unique_ptr<Asset> idmap_asset,
-                                                     std::unique_ptr<const LoadedIdmap> idmap,
-                                                     package_property_t property_flags) {
+std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
+    std::unique_ptr<const AssetsProvider> assets, const std::string& path,
+    package_property_t property_flags, std::unique_ptr<const AssetsProvider> override_assets,
+    std::unique_ptr<Asset> idmap_asset, std::unique_ptr<const LoadedIdmap> idmap) {
+
   const time_t last_mod_time = getFileModDate(path.c_str());
 
+  // Open the resource table via mmap unless it is compressed. This logic is taken care of by Open.
+  bool resources_asset_exists = false;
+  auto resources_asset_ = assets->Open(kResourcesArsc, Asset::AccessMode::ACCESS_BUFFER,
+                                       &resources_asset_exists);
+  
+  assets = MultiAssetsProvider::Create(std::move(override_assets), std::move(assets));
+
   // Wrap the handle in a unique_ptr so it gets automatically closed.
   std::unique_ptr<ApkAssets>
       loaded_apk(new ApkAssets(std::move(assets), path, last_mod_time, property_flags));
 
-  // Open the resource table via mmap unless it is compressed. This logic is taken care of by Open.
-  bool resources_asset_exists = false;
-  loaded_apk->resources_asset_ = loaded_apk->assets_provider_->Open(
-      kResourcesArsc, Asset::AccessMode::ACCESS_BUFFER, &resources_asset_exists);
-
   if (!resources_asset_exists) {
     loaded_apk->loaded_arsc_ = LoadedArsc::CreateEmpty();
     return std::move(loaded_apk);
   }
 
+  loaded_apk->resources_asset_ = std::move(resources_asset_);
   if (!loaded_apk->resources_asset_) {
     LOG(ERROR) << "Failed to open '" << kResourcesArsc << "' in APK '" << path << "'.";
     return {};
@@ -457,14 +507,17 @@
   return std::move(loaded_apk);
 }
 
-std::unique_ptr<const ApkAssets> ApkAssets::LoadTableImpl(std::unique_ptr<Asset> resources_asset,
-                                                          const std::string& path,
-                                                          package_property_t property_flags) {
+std::unique_ptr<const ApkAssets> ApkAssets::LoadTableImpl(
+    std::unique_ptr<Asset> resources_asset, const std::string& path,
+    package_property_t property_flags, std::unique_ptr<const AssetsProvider> override_assets) {
+
   const time_t last_mod_time = getFileModDate(path.c_str());
 
+  auto assets = (override_assets) ? std::move(override_assets)
+                                  : std::unique_ptr<AssetsProvider>(new EmptyAssetsProvider());
+
   std::unique_ptr<ApkAssets> loaded_apk(
-      new ApkAssets(std::unique_ptr<AssetsProvider>(new EmptyAssetsProvider()), path, last_mod_time,
-                    property_flags));
+      new ApkAssets(std::move(assets), path, last_mod_time, property_flags));
   loaded_apk->resources_asset_ = std::move(resources_asset);
 
   const StringPiece data(