summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/jni/android_content_res_ApkAssets.cpp94
-rw-r--r--libs/androidfw/Android.bp1
-rwxr-xr-xlibs/androidfw/ApkAssets.cpp564
-rw-r--r--libs/androidfw/AssetsProvider.cpp398
-rw-r--r--libs/androidfw/Idmap.cpp4
-rw-r--r--libs/androidfw/LoadedArsc.cpp13
-rw-r--r--libs/androidfw/include/androidfw/ApkAssets.h180
-rw-r--r--libs/androidfw/include/androidfw/Asset.h4
-rw-r--r--libs/androidfw/include/androidfw/AssetsProvider.h185
-rw-r--r--libs/androidfw/include/androidfw/Idmap.h4
-rw-r--r--libs/androidfw/include/androidfw/LoadedArsc.h15
-rw-r--r--libs/androidfw/tests/Idmap_test.cpp8
-rw-r--r--libs/androidfw/tests/LoadedArsc_test.cpp6
-rw-r--r--startop/view_compiler/apk_layout_compiler.cc2
14 files changed, 821 insertions, 657 deletions
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 66753e4fc2ee..f1998a583a21 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -47,6 +47,7 @@ static struct assetfiledescriptor_offsets_t {
static struct assetsprovider_offsets_t {
jclass classObject;
jmethodID loadAssetFd;
+ jmethodID toString;
} gAssetsProviderOffsets;
static struct {
@@ -72,9 +73,22 @@ enum : format_type_t {
class LoaderAssetsProvider : public AssetsProvider {
public:
static std::unique_ptr<AssetsProvider> Create(JNIEnv* env, jobject assets_provider) {
- return (!assets_provider) ? nullptr
+ return (!assets_provider) ? EmptyAssetsProvider::Create()
: std::unique_ptr<AssetsProvider>(new LoaderAssetsProvider(
- env->NewGlobalRef(assets_provider)));
+ env, assets_provider));
+ }
+
+ bool ForEachFile(const std::string& /* root_path */,
+ const std::function<void(const StringPiece&, FileType)>& /* f */) const {
+ return true;
+ }
+
+ const std::string& GetDebugName() const override {
+ return debug_name_;
+ }
+
+ bool IsUpToDate() const override {
+ return true;
}
~LoaderAssetsProvider() override {
@@ -142,20 +156,26 @@ class LoaderAssetsProvider : public AssetsProvider {
*file_exists = true;
}
- return ApkAssets::CreateAssetFromFd(base::unique_fd(fd),
- nullptr /* path */,
- static_cast<off64_t>(mOffset),
- static_cast<off64_t>(mLength));
+ return AssetsProvider::CreateAssetFromFd(base::unique_fd(fd),
+ nullptr /* path */,
+ static_cast<off64_t>(mOffset),
+ static_cast<off64_t>(mLength));
}
private:
DISALLOW_COPY_AND_ASSIGN(LoaderAssetsProvider);
- explicit LoaderAssetsProvider(jobject assets_provider)
- : assets_provider_(assets_provider) { }
+ explicit LoaderAssetsProvider(JNIEnv* env, jobject assets_provider) {
+ assets_provider_ = env->NewGlobalRef(assets_provider);
+ auto string_result = static_cast<jstring>(env->CallObjectMethod(
+ assets_provider_, gAssetsProviderOffsets.toString));
+ ScopedUtfChars str(env, string_result);
+ debug_name_ = std::string(str.c_str(), str.size());
+ }
// The global reference to the AssetsProvider
jobject assets_provider_;
+ std::string debug_name_;
};
static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t format,
@@ -170,18 +190,26 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma
auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider);
std::unique_ptr<const ApkAssets> apk_assets;
switch (format) {
- case FORMAT_APK:
- apk_assets = ApkAssets::Load(path.c_str(), property_flags, std::move(loader_assets));
+ case FORMAT_APK: {
+ auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
+ ZipAssetsProvider::Create(path.c_str()));
+ apk_assets = ApkAssets::Load(std::move(assets), property_flags);
break;
+ }
case FORMAT_IDMAP:
apk_assets = ApkAssets::LoadOverlay(path.c_str(), property_flags);
break;
case FORMAT_ARSC:
- apk_assets = ApkAssets::LoadTable(path.c_str(), property_flags, std::move(loader_assets));
+ apk_assets = ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFile(path.c_str()),
+ std::move(loader_assets),
+ property_flags);
break;
- case FORMAT_DIRECTORY:
- apk_assets = ApkAssets::LoadFromDir(path.c_str(), property_flags, std::move(loader_assets));
+ case FORMAT_DIRECTORY: {
+ auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
+ DirectoryAssetsProvider::Create(path.c_str()));
+ apk_assets = ApkAssets::Load(std::move(assets), property_flags);
break;
+ }
default:
const std::string error_msg = base::StringPrintf("Unsupported format type %d", format);
jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str());
@@ -221,13 +249,17 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t
auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider);
std::unique_ptr<const ApkAssets> apk_assets;
switch (format) {
- case FORMAT_APK:
- apk_assets = ApkAssets::LoadFromFd(std::move(dup_fd), friendly_name_utf8.c_str(),
- property_flags, std::move(loader_assets));
+ case FORMAT_APK: {
+ auto assets = MultiAssetsProvider::Create(
+ std::move(loader_assets),
+ ZipAssetsProvider::Create(std::move(dup_fd), friendly_name_utf8.c_str()));
+ apk_assets = ApkAssets::Load(std::move(assets), property_flags);
break;
+ }
case FORMAT_ARSC:
- apk_assets = ApkAssets::LoadTableFromFd(std::move(dup_fd), friendly_name_utf8.c_str(),
- property_flags, std::move(loader_assets));
+ apk_assets = ApkAssets::LoadTable(
+ AssetsProvider::CreateAssetFromFd(std::move(dup_fd), nullptr /* path */),
+ std::move(loader_assets), property_flags);
break;
default:
const std::string error_msg = base::StringPrintf("Unsupported format type %d", format);
@@ -282,17 +314,20 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_
auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider);
std::unique_ptr<const ApkAssets> apk_assets;
switch (format) {
- case FORMAT_APK:
- apk_assets = ApkAssets::LoadFromFd(std::move(dup_fd), friendly_name_utf8.c_str(),
- property_flags, std::move(loader_assets),
- static_cast<off64_t>(offset),
- static_cast<off64_t>(length));
+ case FORMAT_APK: {
+ auto assets = MultiAssetsProvider::Create(
+ std::move(loader_assets),
+ ZipAssetsProvider::Create(std::move(dup_fd), friendly_name_utf8.c_str(),
+ static_cast<off64_t>(offset), static_cast<off64_t>(length)));
+ apk_assets = ApkAssets::Load(std::move(assets), property_flags);
break;
+ }
case FORMAT_ARSC:
- apk_assets = ApkAssets::LoadTableFromFd(std::move(dup_fd), friendly_name_utf8.c_str(),
- property_flags, std::move(loader_assets),
- static_cast<off64_t>(offset),
- static_cast<off64_t>(length));
+ apk_assets = ApkAssets::LoadTable(
+ AssetsProvider::CreateAssetFromFd(std::move(dup_fd), nullptr /* path */,
+ static_cast<off64_t>(offset),
+ static_cast<off64_t>(length)),
+ std::move(loader_assets), property_flags);
break;
default:
const std::string error_msg = base::StringPrintf("Unsupported format type %d", format);
@@ -310,8 +345,7 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_
}
static jlong NativeLoadEmpty(JNIEnv* env, jclass /*clazz*/, jint flags, jobject assets_provider) {
- auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider);
- auto apk_assets = ApkAssets::LoadEmpty(flags, std::move(loader_assets));
+ auto apk_assets = ApkAssets::Load(LoaderAssetsProvider::Create(env, assets_provider), flags);
return reinterpret_cast<jlong>(apk_assets.release());
}
@@ -458,6 +492,8 @@ int register_android_content_res_ApkAssets(JNIEnv* env) {
gAssetsProviderOffsets.loadAssetFd = GetMethodIDOrDie(
env, gAssetsProviderOffsets.classObject, "loadAssetFd",
"(Ljava/lang/String;I)Landroid/content/res/AssetFileDescriptor;");
+ gAssetsProviderOffsets.toString = GetMethodIDOrDie(
+ env, gAssetsProviderOffsets.classObject, "toString", "()Ljava/lang/String;");
jclass parcelFd = FindClassOrDie(env, "android/os/ParcelFileDescriptor");
gParcelFileDescriptorOffsets.detachFd = GetMethodIDOrDie(env, parcelFd, "detachFd", "()I");
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index b54f7d81274c..4b4284a0c745 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -41,6 +41,7 @@ cc_library {
"AssetDir.cpp",
"AssetManager.cpp",
"AssetManager2.cpp",
+ "AssetsProvider.cpp",
"AttributeResolution.cpp",
"ChunkIterator.cpp",
"ConfigDescription.cpp",
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 011a0de8031f..ca5981c0dd5c 100755
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -16,533 +16,145 @@
#include "androidfw/ApkAssets.h"
-#include <algorithm>
-
#include "android-base/errors.h"
-#include "android-base/file.h"
#include "android-base/logging.h"
-#include "android-base/stringprintf.h"
-#include "android-base/unique_fd.h"
-#include "android-base/utf8.h"
-#include "utils/Compat.h"
-#include "ziparchive/zip_archive.h"
-
-#include "androidfw/Asset.h"
-#include "androidfw/Idmap.h"
-#include "androidfw/misc.h"
-#include "androidfw/Util.h"
namespace android {
using base::SystemErrorCodeToString;
using base::unique_fd;
-static const std::string kResourcesArsc("resources.arsc");
-
-ApkAssets::ApkAssets(std::unique_ptr<const AssetsProvider> assets_provider,
- std::string path,
- time_t last_mod_time,
- package_property_t property_flags)
- : assets_provider_(std::move(assets_provider)),
- path_(std::move(path)),
- last_mod_time_(last_mod_time),
- property_flags_(property_flags) {
-}
-
-// Provides asset files from a zip file.
-class ZipAssetsProvider : public AssetsProvider {
- public:
- ~ZipAssetsProvider() override = default;
-
- static std::unique_ptr<const AssetsProvider> Create(const std::string& path) {
- ::ZipArchiveHandle unmanaged_handle;
- const int32_t result = ::OpenArchive(path.c_str(), &unmanaged_handle);
- if (result != 0) {
- LOG(ERROR) << "Failed to open APK '" << path << "' " << ::ErrorCodeString(result);
- ::CloseArchive(unmanaged_handle);
- return {};
- }
-
- return std::unique_ptr<AssetsProvider>(new ZipAssetsProvider(path, path, unmanaged_handle));
- }
-
- static std::unique_ptr<const AssetsProvider> Create(
- unique_fd fd, const std::string& friendly_name, const off64_t offset = 0,
- const off64_t length = ApkAssets::kUnknownLength) {
-
- ::ZipArchiveHandle unmanaged_handle;
- const int32_t result = (length == ApkAssets::kUnknownLength)
- ? ::OpenArchiveFd(fd.release(), friendly_name.c_str(), &unmanaged_handle)
- : ::OpenArchiveFdRange(fd.release(), friendly_name.c_str(), &unmanaged_handle, length,
- offset);
-
- if (result != 0) {
- LOG(ERROR) << "Failed to open APK '" << friendly_name << "' through FD with offset " << offset
- << " and length " << length << ": " << ::ErrorCodeString(result);
- ::CloseArchive(unmanaged_handle);
- return {};
- }
-
- return std::unique_ptr<AssetsProvider>(new ZipAssetsProvider({}, friendly_name,
- unmanaged_handle));
- }
-
- // Iterate over all files and directories within the zip. The order of iteration is not
- // guaranteed to be the same as the order of elements in the central directory but is stable for a
- // given zip file.
- bool ForEachFile(const std::string& root_path,
- const std::function<void(const StringPiece&, FileType)>& f) const override {
- // If this is a resource loader from an .arsc, there will be no zip handle
- if (zip_handle_ == nullptr) {
- return false;
- }
-
- std::string root_path_full = root_path;
- if (root_path_full.back() != '/') {
- root_path_full += '/';
- }
-
- void* cookie;
- if (::StartIteration(zip_handle_.get(), &cookie, root_path_full, "") != 0) {
- return false;
- }
-
- std::string name;
- ::ZipEntry entry{};
-
- // We need to hold back directories because many paths will contain them and we want to only
- // surface one.
- std::set<std::string> dirs{};
-
- int32_t result;
- while ((result = ::Next(cookie, &entry, &name)) == 0) {
- StringPiece full_file_path(name);
- StringPiece leaf_file_path = full_file_path.substr(root_path_full.size());
-
- if (!leaf_file_path.empty()) {
- auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/');
- if (iter != leaf_file_path.end()) {
- std::string dir =
- leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string();
- dirs.insert(std::move(dir));
- } else {
- f(leaf_file_path, kFileTypeRegular);
- }
- }
- }
- ::EndIteration(cookie);
-
- // Now present the unique directories.
- for (const std::string& dir : dirs) {
- f(dir, kFileTypeDirectory);
- }
-
- // -1 is end of iteration, anything else is an error.
- return result == -1;
- }
-
- protected:
- std::unique_ptr<Asset> OpenInternal(
- const std::string& path, Asset::AccessMode mode, bool* file_exists) const override {
- if (file_exists) {
- *file_exists = false;
- }
-
- ::ZipEntry entry;
- int32_t result = ::FindEntry(zip_handle_.get(), path, &entry);
- if (result != 0) {
- return {};
- }
-
- if (file_exists) {
- *file_exists = true;
- }
-
- const int fd = ::GetFileDescriptor(zip_handle_.get());
- const off64_t fd_offset = ::GetFileDescriptorOffset(zip_handle_.get());
- incfs::IncFsFileMap asset_map;
- if (entry.method == kCompressDeflated) {
- if (!asset_map.Create(fd, entry.offset + fd_offset, entry.compressed_length, GetPath())) {
- LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << friendly_name_ << "'";
- return {};
- }
-
- std::unique_ptr<Asset> asset =
- Asset::createFromCompressedMap(std::move(asset_map), entry.uncompressed_length, mode);
- if (asset == nullptr) {
- LOG(ERROR) << "Failed to decompress '" << path << "' in APK '" << friendly_name_ << "'";
- return {};
- }
- return asset;
- }
-
- if (!asset_map.Create(fd, entry.offset + fd_offset, entry.uncompressed_length, GetPath())) {
- LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << friendly_name_ << "'";
- return {};
- }
-
- unique_fd ufd;
- if (!GetPath()) {
- // If the `path` is not set, create a new `fd` for the new Asset to own in order to create
- // new file descriptors using Asset::openFileDescriptor. If the path is set, it will be used
- // to create new file descriptors.
- ufd = unique_fd(dup(fd));
- if (!ufd.ok()) {
- LOG(ERROR) << "Unable to dup fd '" << path << "' in APK '" << friendly_name_ << "'";
- return {};
- }
- }
-
- auto asset = Asset::createFromUncompressedMap(std::move(asset_map), mode, std::move(ufd));
- if (asset == nullptr) {
- LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << friendly_name_ << "'";
- return {};
- }
- return asset;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ZipAssetsProvider);
-
- explicit ZipAssetsProvider(std::string path,
- std::string friendly_name,
- ZipArchiveHandle unmanaged_handle)
- : zip_handle_(unmanaged_handle, ::CloseArchive),
- path_(std::move(path)),
- friendly_name_(std::move(friendly_name)) { }
-
- const char* GetPath() const {
- return path_.empty() ? nullptr : path_.c_str();
- }
-
- using ZipArchivePtr = std::unique_ptr<ZipArchive, void (*)(ZipArchiveHandle)>;
- ZipArchivePtr zip_handle_;
- std::string path_;
- std::string friendly_name_;
-};
-
-class DirectoryAssetsProvider : AssetsProvider {
- public:
- ~DirectoryAssetsProvider() override = default;
-
- static std::unique_ptr<const AssetsProvider> Create(const std::string& path) {
- struct stat sb{};
- const int result = stat(path.c_str(), &sb);
- if (result == -1) {
- LOG(ERROR) << "Failed to find directory '" << path << "'.";
- return nullptr;
- }
-
- if (!S_ISDIR(sb.st_mode)) {
- LOG(ERROR) << "Path '" << path << "' is not a directory.";
- return nullptr;
- }
-
- return std::unique_ptr<AssetsProvider>(new DirectoryAssetsProvider(path));
- }
-
- protected:
- std::unique_ptr<Asset> OpenInternal(
- const std::string& path, Asset::AccessMode /* mode */, bool* file_exists) const override {
- const std::string resolved_path = ResolvePath(path);
- if (file_exists) {
- struct stat sb{};
- const int result = stat(resolved_path.c_str(), &sb);
- *file_exists = result != -1 && S_ISREG(sb.st_mode);
- }
-
- return ApkAssets::CreateAssetFromFile(resolved_path);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DirectoryAssetsProvider);
-
- explicit DirectoryAssetsProvider(std::string path) : path_(std::move(path)) { }
-
- inline std::string ResolvePath(const std::string& path) const {
- return base::StringPrintf("%s%c%s", path_.c_str(), OS_PATH_SEPARATOR, path.c_str());
- }
-
- const std::string path_;
-};
-
-// AssetProvider implementation that does not provide any assets. Used for ApkAssets::LoadEmpty.
-class EmptyAssetsProvider : public AssetsProvider {
- public:
- EmptyAssetsProvider() = default;
- ~EmptyAssetsProvider() override = default;
-
- protected:
- std::unique_ptr<Asset> OpenInternal(const std::string& /*path */,
- Asset::AccessMode /* mode */,
- bool* file_exists) const override {
- if (file_exists) {
- *file_exists = false;
- }
- return nullptr;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(EmptyAssetsProvider);
-};
-
-// 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, flags, std::move(override_asset))
- : nullptr;
+constexpr const char* kResourcesArsc = "resources.arsc";
+
+ApkAssets::ApkAssets(std::unique_ptr<Asset> resources_asset,
+ std::unique_ptr<LoadedArsc> loaded_arsc,
+ std::unique_ptr<AssetsProvider> assets,
+ package_property_t property_flags,
+ std::unique_ptr<Asset> idmap_asset,
+ std::unique_ptr<LoadedIdmap> loaded_idmap)
+ : resources_asset_(std::move(resources_asset)),
+ loaded_arsc_(std::move(loaded_arsc)),
+ assets_provider_(std::move(assets)),
+ property_flags_(property_flags),
+ idmap_asset_(std::move(idmap_asset)),
+ loaded_idmap_(std::move(loaded_idmap)) {}
+
+std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path, package_property_t flags) {
+ return Load(ZipAssetsProvider::Create(path), flags);
}
-// 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, flags, std::move(override_asset))
- : nullptr;
+std::unique_ptr<ApkAssets> ApkAssets::LoadFromFd(base::unique_fd fd,
+ const std::string& debug_name,
+ package_property_t flags,
+ off64_t offset,
+ off64_t len) {
+ return Load(ZipAssetsProvider::Create(std::move(fd), debug_name, offset, len), flags);
}
-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<ApkAssets> ApkAssets::Load(std::unique_ptr<AssetsProvider> assets,
+ package_property_t flags) {
+ return LoadImpl(std::move(assets), flags, nullptr /* idmap_asset */, nullptr /* loaded_idmap */);
}
-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<ApkAssets> ApkAssets::LoadTable(std::unique_ptr<Asset> resources_asset,
+ std::unique_ptr<AssetsProvider> assets,
+ package_property_t flags) {
+ if (resources_asset == nullptr) {
+ return {};
+ }
+ return LoadImpl(std::move(resources_asset), std::move(assets), flags, nullptr /* idmap_asset */,
+ nullptr /* loaded_idmap */);
}
-std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
- const package_property_t flags) {
+std::unique_ptr<ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
+ package_property_t flags) {
CHECK((flags & PROPERTY_LOADER) == 0U) << "Cannot load RROs through loaders";
- std::unique_ptr<Asset> idmap_asset = CreateAssetFromFile(idmap_path);
+ auto idmap_asset = AssetsProvider::CreateAssetFromFile(idmap_path);
if (idmap_asset == nullptr) {
+ LOG(ERROR) << "failed to read IDMAP " << idmap_path;
return {};
}
- const StringPiece idmap_data(
- reinterpret_cast<const char*>(idmap_asset->getBuffer(true /*wordAligned*/)),
- static_cast<size_t>(idmap_asset->getLength()));
- std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(idmap_path, idmap_data);
+ StringPiece idmap_data(reinterpret_cast<const char*>(idmap_asset->getBuffer(true /* aligned */)),
+ static_cast<size_t>(idmap_asset->getLength()));
+ auto loaded_idmap = LoadedIdmap::Load(idmap_path, idmap_data);
if (loaded_idmap == nullptr) {
LOG(ERROR) << "failed to load IDMAP " << idmap_path;
return {};
}
-
- auto overlay_path = std::string(loaded_idmap->OverlayApkPath());
- auto assets = ZipAssetsProvider::Create(overlay_path);
- 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 AssetsProvider> override_asset) {
-
- auto assets = DirectoryAssetsProvider::Create(path);
- 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<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);
-}
-std::unique_ptr<Asset> ApkAssets::CreateAssetFromFile(const std::string& path) {
- unique_fd fd(base::utf8::open(path.c_str(), O_RDONLY | O_BINARY | O_CLOEXEC));
- if (!fd.ok()) {
- LOG(ERROR) << "Failed to open file '" << path << "': " << SystemErrorCodeToString(errno);
+ const std::string overlay_path(loaded_idmap->OverlayApkPath());
+ auto overlay_assets = ZipAssetsProvider::Create(overlay_path);
+ if (overlay_assets == nullptr) {
return {};
}
- return CreateAssetFromFd(std::move(fd), path.c_str());
+ return LoadImpl(std::move(overlay_assets), flags | PROPERTY_OVERLAY, std::move(idmap_asset),
+ std::move(loaded_idmap));
}
-std::unique_ptr<Asset> ApkAssets::CreateAssetFromFd(base::unique_fd fd,
- const char* path,
- off64_t offset,
- 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;
- if (length == kUnknownLength) {
- length = lseek64(fd, 0, SEEK_END);
- if (length < 0) {
- LOG(ERROR) << "Failed to get size of file '" << ((path) ? path : "anon") << "': "
- << SystemErrorCodeToString(errno);
- return {};
- }
- }
-
- incfs::IncFsFileMap file_map;
- if (!file_map.Create(fd, offset, static_cast<size_t>(length), path)) {
- LOG(ERROR) << "Failed to mmap file '" << ((path) ? path : "anon") << "': "
- << SystemErrorCodeToString(errno);
+std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> assets,
+ package_property_t property_flags,
+ std::unique_ptr<Asset> idmap_asset,
+ std::unique_ptr<LoadedIdmap> loaded_idmap) {
+ if (assets == nullptr) {
return {};
}
- // If `path` is set, do not pass ownership of the `fd` to the new Asset since
- // Asset::openFileDescriptor can use `path` to create new file descriptors.
- return Asset::createFromUncompressedMap(std::move(file_map),
- Asset::AccessMode::ACCESS_RANDOM,
- (path) ? base::unique_fd(-1) : std::move(fd));
-}
-
-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));
-
- 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 << "'.";
+ auto resources_asset = assets->Open(kResourcesArsc, Asset::AccessMode::ACCESS_BUFFER,
+ &resources_asset_exists);
+ if (resources_asset == nullptr && resources_asset_exists) {
+ LOG(ERROR) << "Failed to open '" << kResourcesArsc << "' in APK '" << assets->GetDebugName()
+ << "'.";
return {};
}
- // Must retain ownership of the IDMAP Asset so that all pointers to its mmapped data remain valid.
- loaded_apk->idmap_asset_ = std::move(idmap_asset);
- loaded_apk->loaded_idmap_ = std::move(idmap);
+ return LoadImpl(std::move(resources_asset), std::move(assets), property_flags,
+ std::move(idmap_asset), std::move(loaded_idmap));
+}
- const auto data = loaded_apk->resources_asset_->getIncFsBuffer(true /* aligned */);
- const size_t length = loaded_apk->resources_asset_->getLength();
- if (!data || length == 0) {
- LOG(ERROR) << "Failed to read '" << kResourcesArsc << "' data in APK '" << path << "'.";
+std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset,
+ std::unique_ptr<AssetsProvider> assets,
+ package_property_t property_flags,
+ std::unique_ptr<Asset> idmap_asset,
+ std::unique_ptr<LoadedIdmap> loaded_idmap) {
+ if (assets == nullptr ) {
return {};
}
- loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, length, loaded_apk->loaded_idmap_.get(),
- property_flags);
- if (!loaded_apk->loaded_arsc_) {
- LOG(ERROR) << "Failed to load '" << kResourcesArsc << "' in APK '" << path << "'.";
- return {};
+ std::unique_ptr<LoadedArsc> loaded_arsc;
+ if (resources_asset != nullptr) {
+ const auto data = resources_asset->getIncFsBuffer(true /* aligned */);
+ const size_t length = resources_asset->getLength();
+ if (!data || length == 0) {
+ LOG(ERROR) << "Failed to read resources table in APK '" << assets->GetDebugName() << "'.";
+ return {};
+ }
+ loaded_arsc = LoadedArsc::Load(data, length, loaded_idmap.get(), property_flags);
+ } else {
+ loaded_arsc = LoadedArsc::CreateEmpty();
}
- // Need to force a move for mingw32.
- 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 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::move(assets), path, last_mod_time, property_flags));
- loaded_apk->resources_asset_ = std::move(resources_asset);
-
- const auto data = loaded_apk->resources_asset_->getIncFsBuffer(true /* aligned */);
- const size_t length = loaded_apk->resources_asset_->getLength();
- if (!data || length == 0) {
- LOG(ERROR) << "Failed to read resources table data in '" << path << "'.";
+ if (loaded_arsc == nullptr) {
+ LOG(ERROR) << "Failed to load resources table in APK '" << assets->GetDebugName() << "'.";
return {};
}
- loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, length, nullptr /* loaded_idmap */,
- property_flags);
- if (loaded_apk->loaded_arsc_ == nullptr) {
- LOG(ERROR) << "Failed to read resources table in '" << path << "'.";
- return {};
- }
+ return std::unique_ptr<ApkAssets>(new ApkAssets(std::move(resources_asset),
+ std::move(loaded_arsc), std::move(assets),
+ property_flags, std::move(idmap_asset),
+ std::move(loaded_idmap)));
+}
- // Need to force a move for mingw32.
- return std::move(loaded_apk);
+const std::string& ApkAssets::GetPath() const {
+ return assets_provider_->GetDebugName();
}
bool ApkAssets::IsUpToDate() const {
- if (IsLoader()) {
- // Loaders are invalidated by the app, not the system, so assume they are up to date.
- return true;
- }
- return (!loaded_idmap_ || loaded_idmap_->IsUpToDate()) &&
- last_mod_time_ == getFileModDate(path_.c_str());
+ // Loaders are invalidated by the app, not the system, so assume they are up to date.
+ return IsLoader() || ((!loaded_idmap_ || loaded_idmap_->IsUpToDate())
+ && assets_provider_->IsUpToDate());
}
-
} // namespace android
diff --git a/libs/androidfw/AssetsProvider.cpp b/libs/androidfw/AssetsProvider.cpp
new file mode 100644
index 000000000000..23cacf88a6db
--- /dev/null
+++ b/libs/androidfw/AssetsProvider.cpp
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "androidfw/AssetsProvider.h"
+
+#include <sys/stat.h>
+
+#include <android-base/errors.h>
+#include <android-base/stringprintf.h>
+#include <android-base/utf8.h>
+#include <ziparchive/zip_archive.h>
+
+namespace android {
+namespace {
+constexpr const char* kEmptyDebugString = "<empty>";
+} // namespace
+
+std::unique_ptr<Asset> AssetsProvider::Open(const std::string& path, Asset::AccessMode mode,
+ bool* file_exists) const {
+ return OpenInternal(path, mode, file_exists);
+}
+
+std::unique_ptr<Asset> AssetsProvider::CreateAssetFromFile(const std::string& path) {
+ base::unique_fd fd(base::utf8::open(path.c_str(), O_RDONLY | O_CLOEXEC));
+ if (!fd.ok()) {
+ LOG(ERROR) << "Failed to open file '" << path << "': " << base::SystemErrorCodeToString(errno);
+ return {};
+ }
+
+ return CreateAssetFromFd(std::move(fd), path.c_str());
+}
+
+std::unique_ptr<Asset> AssetsProvider::CreateAssetFromFd(base::unique_fd fd,
+ const char* path,
+ off64_t offset,
+ 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;
+ if (length == kUnknownLength) {
+ length = lseek64(fd, 0, SEEK_END);
+ if (length < 0) {
+ LOG(ERROR) << "Failed to get size of file '" << ((path) ? path : "anon") << "': "
+ << base::SystemErrorCodeToString(errno);
+ return {};
+ }
+ }
+
+ incfs::IncFsFileMap file_map;
+ if (!file_map.Create(fd, offset, static_cast<size_t>(length), path)) {
+ LOG(ERROR) << "Failed to mmap file '" << ((path != nullptr) ? path : "anon") << "': "
+ << base::SystemErrorCodeToString(errno);
+ return {};
+ }
+
+ // If `path` is set, do not pass ownership of the `fd` to the new Asset since
+ // Asset::openFileDescriptor can use `path` to create new file descriptors.
+ return Asset::createFromUncompressedMap(std::move(file_map),
+ Asset::AccessMode::ACCESS_RANDOM,
+ (path != nullptr) ? base::unique_fd(-1) : std::move(fd));
+}
+
+ZipAssetsProvider::PathOrDebugName::PathOrDebugName(std::string&& value, bool is_path)
+ : value_(std::forward<std::string>(value)), is_path_(is_path) {}
+
+const std::string* ZipAssetsProvider::PathOrDebugName::GetPath() const {
+ return is_path_ ? &value_ : nullptr;
+}
+
+const std::string& ZipAssetsProvider::PathOrDebugName::GetDebugName() const {
+ return value_;
+}
+
+ZipAssetsProvider::ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path,
+ time_t last_mod_time)
+ : zip_handle_(handle, ::CloseArchive),
+ name_(std::forward<PathOrDebugName>(path)),
+ last_mod_time_(last_mod_time) {}
+
+std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path) {
+ ZipArchiveHandle handle;
+ if (int32_t result = OpenArchive(path.c_str(), &handle); result != 0) {
+ LOG(ERROR) << "Failed to open APK '" << path << "' " << ::ErrorCodeString(result);
+ CloseArchive(handle);
+ return {};
+ }
+
+ struct stat sb{.st_mtime = -1};
+ if (stat(path.c_str(), &sb) < 0) {
+ // Stat requires execute permissions on all directories path to the file. If the process does
+ // not have execute permissions on this file, allow the zip to be opened but IsUpToDate() will
+ // always have to return true.
+ LOG(WARNING) << "Failed to stat file '" << path << "': "
+ << base::SystemErrorCodeToString(errno);
+ }
+
+ return std::unique_ptr<ZipAssetsProvider>(
+ new ZipAssetsProvider(handle, PathOrDebugName{std::move(path),
+ true /* is_path */}, sb.st_mtime));
+}
+
+std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
+ std::string friendly_name,
+ off64_t offset,
+ off64_t len) {
+ ZipArchiveHandle handle;
+ const int released_fd = fd.release();
+ const int32_t result = (len == AssetsProvider::kUnknownLength)
+ ? ::OpenArchiveFd(released_fd, friendly_name.c_str(), &handle)
+ : ::OpenArchiveFdRange(released_fd, friendly_name.c_str(), &handle, len, offset);
+
+ if (result != 0) {
+ LOG(ERROR) << "Failed to open APK '" << friendly_name << "' through FD with offset " << offset
+ << " and length " << len << ": " << ::ErrorCodeString(result);
+ CloseArchive(handle);
+ return {};
+ }
+
+ struct stat sb{.st_mtime = -1};
+ if (fstat(released_fd, &sb) < 0) {
+ // Stat requires execute permissions on all directories path to the file. If the process does
+ // not have execute permissions on this file, allow the zip to be opened but IsUpToDate() will
+ // always have to return true.
+ LOG(WARNING) << "Failed to fstat file '" << friendly_name << "': "
+ << base::SystemErrorCodeToString(errno);
+ }
+
+ return std::unique_ptr<ZipAssetsProvider>(
+ new ZipAssetsProvider(handle, PathOrDebugName{std::move(friendly_name),
+ false /* is_path */}, sb.st_mtime));
+}
+
+std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
+ Asset::AccessMode mode,
+ bool* file_exists) const {
+ if (file_exists != nullptr) {
+ *file_exists = false;
+ }
+
+ ZipEntry entry;
+ if (FindEntry(zip_handle_.get(), path, &entry) != 0) {
+ return {};
+ }
+
+ if (file_exists != nullptr) {
+ *file_exists = true;
+ }
+
+ const int fd = GetFileDescriptor(zip_handle_.get());
+ const off64_t fd_offset = GetFileDescriptorOffset(zip_handle_.get());
+ incfs::IncFsFileMap asset_map;
+ if (entry.method == kCompressDeflated) {
+ if (!asset_map.Create(fd, entry.offset + fd_offset, entry.compressed_length,
+ name_.GetDebugName().c_str())) {
+ LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName()
+ << "'";
+ return {};
+ }
+
+ std::unique_ptr<Asset> asset =
+ Asset::createFromCompressedMap(std::move(asset_map), entry.uncompressed_length, mode);
+ if (asset == nullptr) {
+ LOG(ERROR) << "Failed to decompress '" << path << "' in APK '" << name_.GetDebugName()
+ << "'";
+ return {};
+ }
+ return asset;
+ }
+
+ if (!asset_map.Create(fd, entry.offset + fd_offset, entry.uncompressed_length,
+ name_.GetDebugName().c_str())) {
+ LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName() << "'";
+ return {};
+ }
+
+ base::unique_fd ufd;
+ if (name_.GetPath() == nullptr) {
+ // If the zip name does not represent a path, create a new `fd` for the new Asset to own in
+ // order to create new file descriptors using Asset::openFileDescriptor. If the zip name is a
+ // path, it will be used to create new file descriptors.
+ ufd = base::unique_fd(dup(fd));
+ if (!ufd.ok()) {
+ LOG(ERROR) << "Unable to dup fd '" << path << "' in APK '" << name_.GetDebugName() << "'";
+ return {};
+ }
+ }
+
+ auto asset = Asset::createFromUncompressedMap(std::move(asset_map), mode, std::move(ufd));
+ if (asset == nullptr) {
+ LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName() << "'";
+ return {};
+ }
+ return asset;
+}
+
+bool ZipAssetsProvider::ForEachFile(const std::string& root_path,
+ const std::function<void(const StringPiece&, FileType)>& f)
+ const {
+ std::string root_path_full = root_path;
+ if (root_path_full.back() != '/') {
+ root_path_full += '/';
+ }
+
+ void* cookie;
+ if (StartIteration(zip_handle_.get(), &cookie, root_path_full, "") != 0) {
+ return false;
+ }
+
+ std::string name;
+ ::ZipEntry entry{};
+
+ // We need to hold back directories because many paths will contain them and we want to only
+ // surface one.
+ std::set<std::string> dirs{};
+
+ int32_t result;
+ while ((result = Next(cookie, &entry, &name)) == 0) {
+ StringPiece full_file_path(name);
+ StringPiece leaf_file_path = full_file_path.substr(root_path_full.size());
+
+ if (!leaf_file_path.empty()) {
+ auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/');
+ if (iter != leaf_file_path.end()) {
+ std::string dir =
+ leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string();
+ dirs.insert(std::move(dir));
+ } else {
+ f(leaf_file_path, kFileTypeRegular);
+ }
+ }
+ }
+ EndIteration(cookie);
+
+ // Now present the unique directories.
+ for (const std::string& dir : dirs) {
+ f(dir, kFileTypeDirectory);
+ }
+
+ // -1 is end of iteration, anything else is an error.
+ return result == -1;
+}
+
+const std::string& ZipAssetsProvider::GetDebugName() const {
+ return name_.GetDebugName();
+}
+
+bool ZipAssetsProvider::IsUpToDate() const {
+ struct stat sb{};
+ if (fstat(GetFileDescriptor(zip_handle_.get()), &sb) < 0) {
+ // If fstat fails on the zip archive, return true so the zip archive the resource system does
+ // attempt to refresh the ApkAsset.
+ return true;
+ }
+ return last_mod_time_ == sb.st_mtime;
+}
+
+DirectoryAssetsProvider::DirectoryAssetsProvider(std::string&& path, time_t last_mod_time)
+ : dir_(std::forward<std::string>(path)), last_mod_time_(last_mod_time) {}
+
+std::unique_ptr<DirectoryAssetsProvider> DirectoryAssetsProvider::Create(std::string path) {
+ struct stat sb{};
+ const int result = stat(path.c_str(), &sb);
+ if (result == -1) {
+ LOG(ERROR) << "Failed to find directory '" << path << "'.";
+ return nullptr;
+ }
+
+ if (!S_ISDIR(sb.st_mode)) {
+ LOG(ERROR) << "Path '" << path << "' is not a directory.";
+ return nullptr;
+ }
+
+ if (path[path.size() - 1] != OS_PATH_SEPARATOR) {
+ path += OS_PATH_SEPARATOR;
+ }
+
+ return std::unique_ptr<DirectoryAssetsProvider>(new DirectoryAssetsProvider(std::move(path),
+ sb.st_mtime));
+}
+
+std::unique_ptr<Asset> DirectoryAssetsProvider::OpenInternal(const std::string& path,
+ Asset::AccessMode /* mode */,
+ bool* file_exists) const {
+ const std::string resolved_path = dir_ + path;
+ if (file_exists != nullptr) {
+ struct stat sb{};
+ *file_exists = (stat(resolved_path.c_str(), &sb) != -1) && S_ISREG(sb.st_mode);
+ }
+
+ return CreateAssetFromFile(resolved_path);
+}
+
+bool DirectoryAssetsProvider::ForEachFile(
+ const std::string& /* root_path */,
+ const std::function<void(const StringPiece&, FileType)>& /* f */)
+ const {
+ return true;
+}
+
+const std::string& DirectoryAssetsProvider::GetDebugName() const {
+ return dir_;
+}
+
+bool DirectoryAssetsProvider::IsUpToDate() const {
+ struct stat sb{};
+ if (stat(dir_.c_str(), &sb) < 0) {
+ // If stat fails on the zip archive, return true so the zip archive the resource system does
+ // attempt to refresh the ApkAsset.
+ return true;
+ }
+ return last_mod_time_ == sb.st_mtime;
+}
+
+MultiAssetsProvider::MultiAssetsProvider(std::unique_ptr<AssetsProvider>&& primary,
+ std::unique_ptr<AssetsProvider>&& secondary)
+ : primary_(std::forward<std::unique_ptr<AssetsProvider>>(primary)),
+ secondary_(std::forward<std::unique_ptr<AssetsProvider>>(secondary)) {
+ if (primary_->GetDebugName() == kEmptyDebugString) {
+ debug_name_ = secondary_->GetDebugName();
+ } else if (secondary_->GetDebugName() == kEmptyDebugString) {
+ debug_name_ = primary_->GetDebugName();
+ } else {
+ debug_name_ = primary_->GetDebugName() + " and " + secondary_->GetDebugName();
+ }
+}
+
+std::unique_ptr<AssetsProvider> MultiAssetsProvider::Create(
+ std::unique_ptr<AssetsProvider>&& primary, std::unique_ptr<AssetsProvider>&& secondary) {
+ if (primary == nullptr || secondary == nullptr) {
+ return nullptr;
+ }
+ return std::unique_ptr<MultiAssetsProvider>(new MultiAssetsProvider(std::move(primary),
+ std::move(secondary)));
+}
+
+std::unique_ptr<Asset> MultiAssetsProvider::OpenInternal(const std::string& path,
+ Asset::AccessMode mode,
+ bool* file_exists) const {
+ auto asset = primary_->Open(path, mode, file_exists);
+ return (asset) ? std::move(asset) : secondary_->Open(path, mode, file_exists);
+}
+
+bool MultiAssetsProvider::ForEachFile(const std::string& root_path,
+ const std::function<void(const StringPiece&, FileType)>& f)
+ const {
+ return primary_->ForEachFile(root_path, f) && secondary_->ForEachFile(root_path, f);
+}
+
+const std::string& MultiAssetsProvider::GetDebugName() const {
+ return debug_name_;
+}
+
+bool MultiAssetsProvider::IsUpToDate() const {
+ return primary_->IsUpToDate() && secondary_->IsUpToDate();
+}
+
+std::unique_ptr<AssetsProvider> EmptyAssetsProvider::Create() {
+ return std::make_unique<EmptyAssetsProvider>();
+}
+
+std::unique_ptr<Asset> EmptyAssetsProvider::OpenInternal(const std::string& /* path */,
+ Asset::AccessMode /* mode */,
+ bool* file_exists) const {
+ if (file_exists) {
+ *file_exists = false;
+ }
+ return nullptr;
+}
+
+bool EmptyAssetsProvider::ForEachFile(
+ const std::string& /* root_path */,
+ const std::function<void(const StringPiece&, FileType)>& /* f */) const {
+ return true;
+}
+
+const std::string& EmptyAssetsProvider::GetDebugName() const {
+ const static std::string kEmpty = kEmptyDebugString;
+ return kEmpty;
+}
+
+bool EmptyAssetsProvider::IsUpToDate() const {
+ return true;
+}
+
+} // namespace android \ No newline at end of file
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index adb383f95d40..f216f55771c2 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -257,8 +257,8 @@ LoadedIdmap::LoadedIdmap(std::string&& idmap_path,
target_apk_path_(target_apk_path),
idmap_last_mod_time_(getFileModDate(idmap_path_.data())) {}
-std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path,
- const StringPiece& idmap_data) {
+std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path,
+ const StringPiece& idmap_data) {
ATRACE_CALL();
size_t data_size = idmap_data.size();
auto data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data());
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 996b42426282..2a70f0d6a804 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -767,10 +767,10 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
return true;
}
-std::unique_ptr<const LoadedArsc> LoadedArsc::Load(incfs::map_ptr<void> data,
- const size_t length,
- const LoadedIdmap* loaded_idmap,
- const package_property_t property_flags) {
+std::unique_ptr<LoadedArsc> LoadedArsc::Load(incfs::map_ptr<void> data,
+ const size_t length,
+ const LoadedIdmap* loaded_idmap,
+ const package_property_t property_flags) {
ATRACE_NAME("LoadedArsc::Load");
// Not using make_unique because the constructor is private.
@@ -799,11 +799,10 @@ std::unique_ptr<const LoadedArsc> LoadedArsc::Load(incfs::map_ptr<void> data,
}
}
- // Need to force a move for mingw32.
- return std::move(loaded_arsc);
+ return loaded_arsc;
}
-std::unique_ptr<const LoadedArsc> LoadedArsc::CreateEmpty() {
+std::unique_ptr<LoadedArsc> LoadedArsc::CreateEmpty() {
return std::unique_ptr<LoadedArsc>(new LoadedArsc());
}
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index e57490aab2d8..d0019ed6be30 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -24,104 +24,49 @@
#include "android-base/unique_fd.h"
#include "androidfw/Asset.h"
+#include "androidfw/AssetsProvider.h"
#include "androidfw/Idmap.h"
#include "androidfw/LoadedArsc.h"
#include "androidfw/misc.h"
-struct ZipArchive;
-typedef ZipArchive* ZipArchiveHandle;
-
namespace android {
-class LoadedIdmap;
-
-// Interface for retrieving assets provided by an ApkAssets.
-class AssetsProvider {
+// Holds an APK.
+class ApkAssets {
public:
- virtual ~AssetsProvider() = default;
- // Opens a file for reading.
- std::unique_ptr<Asset> Open(const std::string& path,
- Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM,
- bool* file_exists = nullptr) const {
- return OpenInternal(path, mode, file_exists);
- }
+ // Creates an ApkAssets from a path on device.
+ static std::unique_ptr<ApkAssets> Load(const std::string& path,
+ package_property_t flags = 0U);
- // Iterate over all files and directories provided by the zip. The order of iteration is stable.
- virtual bool ForEachFile(const std::string& /* path */,
- const std::function<void(const StringPiece&, FileType)>& /* f */) const {
- return true;
- }
+ // Creates an ApkAssets from an open file descriptor.
+ static std::unique_ptr<ApkAssets> LoadFromFd(base::unique_fd fd,
+ const std::string& debug_name,
+ package_property_t flags = 0U,
+ off64_t offset = 0,
+ off64_t len = AssetsProvider::kUnknownLength);
- protected:
- AssetsProvider() = default;
+ // Creates an ApkAssets from an AssetProvider.
+ // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed.
+ static std::unique_ptr<ApkAssets> Load(std::unique_ptr<AssetsProvider> assets,
+ package_property_t flags = 0U);
- virtual std::unique_ptr<Asset> OpenInternal(const std::string& path,
- Asset::AccessMode mode,
- bool* file_exists) const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AssetsProvider);
-};
-
-class ZipAssetsProvider;
-
-// Holds an APK.
-class ApkAssets {
- public:
- // This means the data extends to the end of the file.
- static constexpr off64_t kUnknownLength = -1;
-
- // Creates an ApkAssets.
- // If `system` is true, the package is marked as a system package, and allows some functions to
- // filter out this package when computing what configurations/resources are available.
- static std::unique_ptr<const ApkAssets> Load(
- const std::string& path, package_property_t flags = 0U,
- std::unique_ptr<const AssetsProvider> override_asset = nullptr);
-
- // Creates an ApkAssets from the given file descriptor, and takes ownership of the file
- // descriptor. The `friendly_name` is some name that will be used to identify the source of
- // this ApkAssets in log messages and other debug scenarios.
- // If `length` equals kUnknownLength, offset must equal 0; otherwise, the apk data will be read
- // using the `offset` into the file descriptor and will be `length` bytes long.
- static std::unique_ptr<const ApkAssets> LoadFromFd(
- base::unique_fd fd, const std::string& friendly_name, package_property_t flags = 0U,
- std::unique_ptr<const AssetsProvider> override_asset = nullptr, off64_t offset = 0,
- off64_t length = kUnknownLength);
-
- // Creates an ApkAssets from the given path which points to a resources.arsc.
- static std::unique_ptr<const ApkAssets> LoadTable(
- const std::string& path, package_property_t flags = 0U,
- std::unique_ptr<const AssetsProvider> override_asset = nullptr);
-
- // Creates an ApkAssets from the given file descriptor which points to an resources.arsc, and
- // takes ownership of the file descriptor.
- // If `length` equals kUnknownLength, offset must equal 0; otherwise, the .arsc data will be read
- // using the `offset` into the file descriptor and will be `length` bytes long.
- static std::unique_ptr<const ApkAssets> LoadTableFromFd(
- base::unique_fd fd, const std::string& friendly_name, package_property_t flags = 0U,
- std::unique_ptr<const AssetsProvider> override_asset = nullptr, off64_t offset = 0,
- off64_t length = kUnknownLength);
+ // Creates an ApkAssets from the given asset file representing a resources.arsc.
+ static std::unique_ptr<ApkAssets> LoadTable(std::unique_ptr<Asset> resources_asset,
+ std::unique_ptr<AssetsProvider> assets,
+ package_property_t flags = 0U);
// Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay
// data.
- static std::unique_ptr<const ApkAssets> LoadOverlay(const std::string& idmap_path,
- package_property_t flags = 0U);
-
- // Creates an ApkAssets from the directory path. File-based resources are read within the
- // directory as if the directory is an APK.
- static std::unique_ptr<const ApkAssets> LoadFromDir(
- const std::string& path, package_property_t flags = 0U,
- std::unique_ptr<const AssetsProvider> override_asset = nullptr);
-
- // Creates a totally empty ApkAssets with no resources table and no file entries.
- static std::unique_ptr<const ApkAssets> LoadEmpty(
- package_property_t flags = 0U,
- std::unique_ptr<const AssetsProvider> override_asset = nullptr);
-
- const std::string& GetPath() const {
- return path_;
- }
+ static std::unique_ptr<ApkAssets> LoadOverlay(const std::string& idmap_path,
+ package_property_t flags = 0U);
+
+ // TODO(177101983): Remove all uses of GetPath for checking whether two ApkAssets are the same.
+ // With the introduction of ResourcesProviders, not all ApkAssets have paths. This could cause
+ // bugs when path is used for comparison because multiple ApkAssets could have the same "firendly
+ // name". Use pointer equality instead. ResourceManager caches and reuses ApkAssets so the
+ // same asset should have the same pointer.
+ const std::string& GetPath() const;
const AssetsProvider* GetAssetsProvider() const {
return assets_provider_.get();
@@ -146,53 +91,40 @@ class ApkAssets {
// Returns whether the resources.arsc is allocated in RAM (not mmapped).
bool IsTableAllocated() const {
- return resources_asset_ && resources_asset_->isAllocated();
+ return resources_asset_ != nullptr && resources_asset_->isAllocated();
}
bool IsUpToDate() const;
- // Creates an Asset from a file on disk.
- static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path);
-
- // Creates an Asset from a file descriptor.
- //
- // The asset takes ownership of the file descriptor. If `length` equals kUnknownLength, offset
- // must equal 0; otherwise, the asset data will be read using the `offset` into the file
- // descriptor and will be `length` bytes long.
- static std::unique_ptr<Asset> CreateAssetFromFd(base::unique_fd fd,
- const char* path,
- off64_t offset = 0,
- off64_t length = kUnknownLength);
private:
- DISALLOW_COPY_AND_ASSIGN(ApkAssets);
-
- static std::unique_ptr<const ApkAssets> LoadImpl(
- std::unique_ptr<const AssetsProvider> assets, const std::string& path,
- package_property_t property_flags,
- std::unique_ptr<const AssetsProvider> override_assets = nullptr,
- std::unique_ptr<Asset> idmap_asset = nullptr,
- std::unique_ptr<const LoadedIdmap> idmap = nullptr);
-
- static std::unique_ptr<const ApkAssets> LoadTableImpl(
- std::unique_ptr<Asset> resources_asset, const std::string& path,
- package_property_t property_flags,
- std::unique_ptr<const AssetsProvider> override_assets = nullptr);
-
- ApkAssets(std::unique_ptr<const AssetsProvider> assets_provider,
- std::string path,
- time_t last_mod_time,
- package_property_t property_flags);
-
- std::unique_ptr<const AssetsProvider> assets_provider_;
- const std::string path_;
- time_t last_mod_time_;
- package_property_t property_flags_ = 0U;
+ static std::unique_ptr<ApkAssets> LoadImpl(std::unique_ptr<AssetsProvider> assets,
+ package_property_t property_flags,
+ std::unique_ptr<Asset> idmap_asset,
+ std::unique_ptr<LoadedIdmap> loaded_idmap);
+
+ static std::unique_ptr<ApkAssets> LoadImpl(std::unique_ptr<Asset> resources_asset,
+ std::unique_ptr<AssetsProvider> assets,
+ package_property_t property_flags,
+ std::unique_ptr<Asset> idmap_asset,
+ std::unique_ptr<LoadedIdmap> loaded_idmap);
+
+ ApkAssets(std::unique_ptr<Asset> resources_asset,
+ std::unique_ptr<LoadedArsc> loaded_arsc,
+ std::unique_ptr<AssetsProvider> assets,
+ package_property_t property_flags,
+ std::unique_ptr<Asset> idmap_asset,
+ std::unique_ptr<LoadedIdmap> loaded_idmap);
+
std::unique_ptr<Asset> resources_asset_;
+ std::unique_ptr<LoadedArsc> loaded_arsc_;
+
+ std::unique_ptr<AssetsProvider> assets_provider_;
+ package_property_t property_flags_ = 0U;
+
std::unique_ptr<Asset> idmap_asset_;
- std::unique_ptr<const LoadedArsc> loaded_arsc_;
- std::unique_ptr<const LoadedIdmap> loaded_idmap_;
+ std::unique_ptr<LoadedIdmap> loaded_idmap_;
};
-} // namespace android
+} // namespace android
-#endif /* APKASSETS_H_ */
+#endif // APKASSETS_H_ \ No newline at end of file
diff --git a/libs/androidfw/include/androidfw/Asset.h b/libs/androidfw/include/androidfw/Asset.h
index 80bae20f3419..40c91a6fcbf5 100644
--- a/libs/androidfw/include/androidfw/Asset.h
+++ b/libs/androidfw/include/androidfw/Asset.h
@@ -167,8 +167,8 @@ protected:
private:
/* AssetManager needs access to our "create" functions */
friend class AssetManager;
- friend class ApkAssets;
- friend class ZipAssetsProvider;
+ friend struct ZipAssetsProvider;
+ friend struct AssetsProvider;
/*
* Create the asset from a named file on disk.
diff --git a/libs/androidfw/include/androidfw/AssetsProvider.h b/libs/androidfw/include/androidfw/AssetsProvider.h
new file mode 100644
index 000000000000..7b06947f45aa
--- /dev/null
+++ b/libs/androidfw/include/androidfw/AssetsProvider.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROIDFW_ASSETSPROVIDER_H
+#define ANDROIDFW_ASSETSPROVIDER_H
+
+#include <memory>
+#include <string>
+
+#include "android-base/macros.h"
+#include "android-base/unique_fd.h"
+
+#include "androidfw/Asset.h"
+#include "androidfw/Idmap.h"
+#include "androidfw/LoadedArsc.h"
+#include "androidfw/misc.h"
+
+struct ZipArchive;
+
+namespace android {
+
+// Interface responsible for opening and iterating through asset files.
+struct AssetsProvider {
+ static constexpr off64_t kUnknownLength = -1;
+
+ // Opens a file for reading. If `file_exists` is not null, it will be set to `true` if the file
+ // exists. This is useful for determining if the file exists but was unable to be opened due to
+ // an I/O error.
+ std::unique_ptr<Asset> Open(const std::string& path,
+ Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM,
+ bool* file_exists = nullptr) const;
+
+ // Iterate over all files and directories provided by the interface. The order of iteration is
+ // stable.
+ virtual bool ForEachFile(const std::string& path,
+ const std::function<void(const StringPiece&, FileType)>& f) const = 0;
+
+ // Retrieves a name that represents the interface. This may or may not be the path of the
+ // interface source.
+ WARN_UNUSED virtual const std::string& GetDebugName() const = 0;
+
+ // Returns whether the interface provides the most recent version of its files.
+ WARN_UNUSED virtual bool IsUpToDate() const = 0;
+
+ // Creates an Asset from a file on disk.
+ static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path);
+
+ // Creates an Asset from a file descriptor.
+ //
+ // The asset takes ownership of the file descriptor. If `length` equals kUnknownLength, offset
+ // must equal 0; otherwise, the asset data will be read using the `offset` into the file
+ // descriptor and will be `length` bytes long.
+ static std::unique_ptr<Asset> CreateAssetFromFd(base::unique_fd fd,
+ const char* path,
+ off64_t offset = 0,
+ off64_t length = AssetsProvider::kUnknownLength);
+
+ virtual ~AssetsProvider() = default;
+ protected:
+ virtual std::unique_ptr<Asset> OpenInternal(const std::string& path, Asset::AccessMode mode,
+ bool* file_exists) const = 0;
+};
+
+// Supplies assets from a zip archive.
+struct ZipAssetsProvider : public AssetsProvider {
+ static std::unique_ptr<ZipAssetsProvider> Create(std::string path);
+ static std::unique_ptr<ZipAssetsProvider> Create(base::unique_fd fd,
+ std::string friendly_name,
+ off64_t offset = 0,
+ off64_t len = kUnknownLength);
+
+ bool ForEachFile(const std::string& root_path,
+ const std::function<void(const StringPiece&, FileType)>& f) const override;
+
+ WARN_UNUSED const std::string& GetDebugName() const override;
+ WARN_UNUSED bool IsUpToDate() const override;
+
+ ~ZipAssetsProvider() override = default;
+ protected:
+ std::unique_ptr<Asset> OpenInternal(const std::string& path, Asset::AccessMode mode,
+ bool* file_exists) const override;
+
+ private:
+ struct PathOrDebugName;
+ ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path, time_t last_mod_time);
+
+ struct PathOrDebugName {
+ PathOrDebugName(std::string&& value, bool is_path);
+
+ // Retrieves the path or null if this class represents a debug name.
+ WARN_UNUSED const std::string* GetPath() const;
+
+ // Retrieves a name that represents the interface. This may or may not represent a path.
+ WARN_UNUSED const std::string& GetDebugName() const;
+
+ private:
+ std::string value_;
+ bool is_path_;
+ };
+
+ std::unique_ptr<ZipArchive, void (*)(ZipArchive*)> zip_handle_;
+ PathOrDebugName name_;
+ time_t last_mod_time_;
+};
+
+// Supplies assets from a root directory.
+struct DirectoryAssetsProvider : public AssetsProvider {
+ static std::unique_ptr<DirectoryAssetsProvider> Create(std::string root_dir);
+
+ bool ForEachFile(const std::string& path,
+ const std::function<void(const StringPiece&, FileType)>& f) const override;
+
+ WARN_UNUSED const std::string& GetDebugName() const override;
+ WARN_UNUSED bool IsUpToDate() const override;
+
+ ~DirectoryAssetsProvider() override = default;
+ protected:
+ std::unique_ptr<Asset> OpenInternal(const std::string& path,
+ Asset::AccessMode mode,
+ bool* file_exists) const override;
+
+ private:
+ explicit DirectoryAssetsProvider(std::string&& path, time_t last_mod_time);
+ std::string dir_;
+ time_t last_mod_time_;
+};
+
+// Supplies assets from a `primary` asset provider and falls back to supplying assets from the
+// `secondary` asset provider if the asset cannot be found in the `primary`.
+struct MultiAssetsProvider : public AssetsProvider {
+ static std::unique_ptr<AssetsProvider> Create(std::unique_ptr<AssetsProvider>&& primary,
+ std::unique_ptr<AssetsProvider>&& secondary);
+
+ bool ForEachFile(const std::string& root_path,
+ const std::function<void(const StringPiece&, FileType)>& f) const override;
+
+ WARN_UNUSED const std::string& GetDebugName() const override;
+ WARN_UNUSED bool IsUpToDate() const override;
+
+ ~MultiAssetsProvider() override = default;
+ protected:
+ std::unique_ptr<Asset> OpenInternal(
+ const std::string& path, Asset::AccessMode mode, bool* file_exists) const override;
+
+ private:
+ MultiAssetsProvider(std::unique_ptr<AssetsProvider>&& primary,
+ std::unique_ptr<AssetsProvider>&& secondary);
+
+ std::unique_ptr<AssetsProvider> primary_;
+ std::unique_ptr<AssetsProvider> secondary_;
+ std::string debug_name_;
+};
+
+// Does not provide any assets.
+struct EmptyAssetsProvider : public AssetsProvider {
+ static std::unique_ptr<AssetsProvider> Create();
+
+ bool ForEachFile(const std::string& path,
+ const std::function<void(const StringPiece&, FileType)>& f) const override;
+
+ WARN_UNUSED const std::string& GetDebugName() const override;
+ WARN_UNUSED bool IsUpToDate() const override;
+
+ ~EmptyAssetsProvider() override = default;
+ protected:
+ std::unique_ptr<Asset> OpenInternal(const std::string& path, Asset::AccessMode mode,
+ bool* file_exists) const override;
+};
+
+} // namespace android
+
+#endif /* ANDROIDFW_ASSETSPROVIDER_H */
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index fd9a8d13e0c6..0ded79309bc1 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -149,8 +149,8 @@ class IdmapResMap {
class LoadedIdmap {
public:
// Loads an IDMAP from a chunk of memory. Returns nullptr if the IDMAP data was malformed.
- static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_path,
- const StringPiece& idmap_data);
+ static std::unique_ptr<LoadedIdmap> Load(const StringPiece& idmap_path,
+ const StringPiece& idmap_data);
// Returns the path to the IDMAP.
std::string_view IdmapPath() const {
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 891fb90d8eeb..d9225cd812ef 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -300,17 +300,14 @@ class LoadedArsc {
public:
// Load a resource table from memory pointed to by `data` of size `len`.
// The lifetime of `data` must out-live the LoadedArsc returned from this method.
- // If `system` is set to true, the LoadedArsc is considered as a system provided resource.
- // If `load_as_shared_library` is set to true, the application package (0x7f) is treated
- // as a shared library (0x00). When loaded into an AssetManager, the package will be assigned an
- // ID.
- static std::unique_ptr<const LoadedArsc> Load(incfs::map_ptr<void> data,
- size_t length,
- const LoadedIdmap* loaded_idmap = nullptr,
- package_property_t property_flags = 0U);
+
+ static std::unique_ptr<LoadedArsc> Load(incfs::map_ptr<void> data,
+ size_t length,
+ const LoadedIdmap* loaded_idmap = nullptr,
+ package_property_t property_flags = 0U);
// Create an empty LoadedArsc. This is used when an APK has no resources.arsc.
- static std::unique_ptr<const LoadedArsc> CreateEmpty();
+ static std::unique_ptr<LoadedArsc> CreateEmpty();
// Returns the string pool where all string resource values
// (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index 3f0c7cbc8ffc..b43491548e2b 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -27,6 +27,8 @@
#include "data/overlayable/R.h"
#include "data/system/R.h"
+using ::testing::NotNull;
+
namespace overlay = com::android::overlay;
namespace overlayable = com::android::overlayable;
@@ -195,7 +197,11 @@ TEST_F(IdmapTest, OverlaidResourceHasSameName) {
}
TEST_F(IdmapTest, OverlayLoaderInterop) {
- auto loader_assets = ApkAssets::LoadTable("loader/resources.arsc", PROPERTY_LOADER);
+ auto asset = AssetsProvider::CreateAssetFromFile(GetTestDataPath() + "/loader/resources.arsc");
+ ASSERT_THAT(asset, NotNull());
+
+ auto loader_assets = ApkAssets::LoadTable(std::move(asset), EmptyAssetsProvider::Create(),
+ PROPERTY_LOADER);
AssetManager2 asset_manager;
asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(),
overlay_assets_.get()});
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 9aa363495131..f356c8130080 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -339,10 +339,8 @@ TEST(LoadedArscTest, GetOverlayableMap) {
}
TEST(LoadedArscTest, LoadCustomLoader) {
- std::string contents;
-
- std::unique_ptr<Asset>
- asset = ApkAssets::CreateAssetFromFile(GetTestDataPath() + "/loader/resources.arsc");
+ auto asset = AssetsProvider::CreateAssetFromFile(GetTestDataPath() + "/loader/resources.arsc");
+ ASSERT_THAT(asset, NotNull());
const StringPiece data(
reinterpret_cast<const char*>(asset->getBuffer(true /*wordAligned*/)),
diff --git a/startop/view_compiler/apk_layout_compiler.cc b/startop/view_compiler/apk_layout_compiler.cc
index eaa3e04cc814..5cb0c171e06f 100644
--- a/startop/view_compiler/apk_layout_compiler.cc
+++ b/startop/view_compiler/apk_layout_compiler.cc
@@ -80,7 +80,7 @@ bool CanCompileLayout(ResXMLParser* parser) {
}
namespace {
-void CompileApkAssetsLayouts(const std::unique_ptr<const android::ApkAssets>& assets,
+void CompileApkAssetsLayouts(const std::unique_ptr<android::ApkAssets>& assets,
CompilationTarget target, std::ostream& target_out) {
android::AssetManager2 resources;
resources.SetApkAssets({assets.get()});