Merge "Do not look for R.class of overlays"

This commit is contained in:
TreeHugger Robot
2019-11-14 19:04:48 +00:00
committed by Android (Google) Code Review
10 changed files with 126 additions and 105 deletions

View File

@@ -1215,7 +1215,8 @@ public final class LoadedApk {
}
// Rewrite the R 'constants' for all library apks.
SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
false, false);
final int N = packageIdentifiers.size();
for (int i = 0; i < N; i++) {
final int id = packageIdentifiers.keyAt(i);

View File

@@ -1491,9 +1491,17 @@ public final class AssetManager implements AutoCloseable {
*/
@UnsupportedAppUsage
public SparseArray<String> getAssignedPackageIdentifiers() {
return getAssignedPackageIdentifiers(true, true);
}
/**
* @hide
*/
public SparseArray<String> getAssignedPackageIdentifiers(boolean includeOverlays,
boolean includeLoaders) {
synchronized (this) {
ensureValidLocked();
return nativeGetAssignedPackageIdentifiers(mObject);
return nativeGetAssignedPackageIdentifiers(mObject, includeOverlays, includeLoaders);
}
}
@@ -1557,7 +1565,7 @@ public final class AssetManager implements AutoCloseable {
int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout,
int uiMode, int colorMode, int majorVersion);
private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers(
long ptr);
long ptr, boolean includeOverlays, boolean includeLoaders);
// File native methods.
private static native @Nullable String[] nativeList(long ptr, @NonNull String path)

View File

@@ -556,7 +556,9 @@ static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin
assetmanager->SetConfiguration(configuration);
}
static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr,
jboolean includeOverlays,
jboolean includeLoaders) {
ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
jobject sparse_array =
@@ -567,6 +569,10 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/
return nullptr;
}
// Optionally exclude overlays and loaders.
uint64_t exclusion_flags = ((includeOverlays) ? 0U : PROPERTY_OVERLAY)
| ((includeLoaders) ? 0U : PROPERTY_LOADER);
assetmanager->ForEachPackage([&](const std::string& package_name, uint8_t package_id) -> bool {
jstring jpackage_name = env->NewStringUTF(package_name.c_str());
if (jpackage_name == nullptr) {
@@ -577,7 +583,8 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/
env->CallVoidMethod(sparse_array, gSparseArrayOffsets.put, static_cast<jint>(package_id),
jpackage_name);
return true;
});
}, exclusion_flags);
return sparse_array;
}
@@ -1591,7 +1598,7 @@ static const JNINativeMethod gAssetManagerMethods[] = {
{"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;Z)V", (void*)NativeSetApkAssets},
{"nativeSetConfiguration", "(JIILjava/lang/String;IIIIIIIIIIIIIII)V",
(void*)NativeSetConfiguration},
{"nativeGetAssignedPackageIdentifiers", "(J)Landroid/util/SparseArray;",
{"nativeGetAssignedPackageIdentifiers", "(JZZ)Landroid/util/SparseArray;",
(void*)NativeGetAssignedPackageIdentifiers},
// AssetManager file methods.

View File

@@ -43,20 +43,22 @@ static const std::string kResourcesArsc("resources.arsc");
ApkAssets::ApkAssets(ZipArchiveHandle unmanaged_handle,
const std::string& path,
time_t last_mod_time,
bool for_loader)
package_property_t property_flags)
: zip_handle_(unmanaged_handle, ::CloseArchive), path_(path), last_mod_time_(last_mod_time),
for_loader_(for_loader) {
property_flags_(property_flags) {
}
std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path, bool system,
bool for_loader) {
return LoadImpl({} /*fd*/, path, nullptr, nullptr, system, false /*load_as_shared_library*/,
for_loader);
package_property_t flags = (system ? PROPERTY_SYSTEM : 0U) |
(for_loader ? PROPERTY_LOADER : 0U);
return LoadImpl({} /*fd*/, path, nullptr, nullptr, flags);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadAsSharedLibrary(const std::string& path,
bool system) {
return LoadImpl({} /*fd*/, path, nullptr, nullptr, system, true /*load_as_shared_library*/);
package_property_t flags = PROPERTY_DYNAMIC | (system ? PROPERTY_SYSTEM : 0U);
return LoadImpl({} /*fd*/, path, nullptr, nullptr, flags);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
@@ -74,27 +76,33 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap
LOG(ERROR) << "failed to load IDMAP " << idmap_path;
return {};
}
return LoadImpl({} /*fd*/, loaded_idmap->OverlayApkPath(), std::move(idmap_asset),
std::move(loaded_idmap), system, true /*load_as_shared_library*/);
return LoadImpl({} /*fd*/, loaded_idmap->OverlayApkPath(),
std::move(idmap_asset),
std::move(loaded_idmap),
PROPERTY_OVERLAY | (system ? PROPERTY_SYSTEM : 0U));
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadFromFd(unique_fd fd,
const std::string& friendly_name,
bool system, bool force_shared_lib,
bool for_loader) {
package_property_t flags = (system ? PROPERTY_SYSTEM : 0U) |
(force_shared_lib ? PROPERTY_DYNAMIC : 0U) |
(for_loader ? PROPERTY_LOADER : 0U);
return LoadImpl(std::move(fd), friendly_name, nullptr /*idmap_asset*/, nullptr /*loaded_idmap*/,
system, force_shared_lib, for_loader);
flags);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadArsc(const std::string& path,
bool for_loader) {
return LoadArscImpl({} /*fd*/, path, for_loader);
return LoadArscImpl({} /*fd*/, path, for_loader ? PROPERTY_LOADER : 0U);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadArsc(unique_fd fd,
const std::string& friendly_name,
bool for_loader) {
return LoadArscImpl(std::move(fd), friendly_name, for_loader);
return LoadArscImpl(std::move(fd), friendly_name, for_loader ? PROPERTY_LOADER : 0U);
}
std::unique_ptr<Asset> ApkAssets::CreateAssetFromFile(const std::string& path) {
@@ -120,8 +128,7 @@ std::unique_ptr<Asset> ApkAssets::CreateAssetFromFile(const std::string& path) {
std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
unique_fd fd, const std::string& path, std::unique_ptr<Asset> idmap_asset,
std::unique_ptr<const LoadedIdmap> loaded_idmap, bool system, bool load_as_shared_library,
bool for_loader) {
std::unique_ptr<const LoadedIdmap> loaded_idmap, package_property_t property_flags) {
::ZipArchiveHandle unmanaged_handle;
int32_t result;
if (fd >= 0) {
@@ -141,7 +148,7 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
// Wrap the handle in a unique_ptr so it gets automatically closed.
std::unique_ptr<ApkAssets>
loaded_apk(new ApkAssets(unmanaged_handle, path, last_mod_time, for_loader));
loaded_apk(new ApkAssets(unmanaged_handle, path, last_mod_time, property_flags));
// Find the resource table.
::ZipEntry entry;
@@ -170,9 +177,8 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
const StringPiece data(
reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
loaded_apk->resources_asset_->getLength());
loaded_apk->loaded_arsc_ =
LoadedArsc::Load(data, loaded_apk->loaded_idmap_.get(), system, load_as_shared_library,
for_loader);
loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, loaded_apk->loaded_idmap_.get(),
property_flags);
if (loaded_apk->loaded_arsc_ == nullptr) {
LOG(ERROR) << "Failed to load '" << kResourcesArsc << "' in APK '" << path << "'.";
return {};
@@ -184,7 +190,7 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
std::unique_ptr<const ApkAssets> ApkAssets::LoadArscImpl(unique_fd fd,
const std::string& path,
bool for_loader) {
package_property_t property_flags) {
std::unique_ptr<Asset> resources_asset;
if (fd >= 0) {
@@ -201,13 +207,14 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadArscImpl(unique_fd fd,
time_t last_mod_time = getFileModDate(path.c_str());
std::unique_ptr<ApkAssets> loaded_apk(new ApkAssets(nullptr, path, last_mod_time, for_loader));
std::unique_ptr<ApkAssets> loaded_apk(
new ApkAssets(nullptr, path, last_mod_time, property_flags));
loaded_apk->resources_asset_ = std::move(resources_asset);
const StringPiece data(
reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
loaded_apk->resources_asset_->getLength());
loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, nullptr, false, false, for_loader);
loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, nullptr, property_flags);
if (loaded_apk->loaded_arsc_ == nullptr) {
LOG(ERROR) << "Failed to load '" << kResourcesArsc << path;
return {};
@@ -320,8 +327,8 @@ bool ApkAssets::ForEachFile(const std::string& root_path,
}
bool ApkAssets::IsUpToDate() const {
// Loaders are invalidated by the app, not the system, so assume up to date
if (for_loader_) {
if (IsLoader()) {
// Loaders are invalidated by the app, not the system, so assume up to date.
return true;
}

View File

@@ -44,8 +44,8 @@ static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_
}
OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
: data_header_(loaded_idmap->data_header_),
idmap_string_pool_(loaded_idmap->string_pool_.get()) { };
: data_header_(loaded_idmap->data_header_),
idmap_string_pool_(loaded_idmap->string_pool_.get()) { };
OverlayStringPool::~OverlayStringPool() {
uninit();
@@ -188,11 +188,12 @@ LoadedIdmap::LoadedIdmap(const Idmap_header* header,
const Idmap_data_header* data_header,
const Idmap_target_entry* target_entries,
const Idmap_overlay_entry* overlay_entries,
ResStringPool* string_pool) : header_(header),
data_header_(data_header),
target_entries_(target_entries),
overlay_entries_(overlay_entries),
string_pool_(string_pool) {
ResStringPool* string_pool)
: header_(header),
data_header_(data_header),
target_entries_(target_entries),
overlay_entries_(overlay_entries),
string_pool_(string_pool) {
size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),
arraysize(header_->overlay_path));
@@ -264,7 +265,7 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_da
}
}
// Can't use make_unique because LoadedImpl constructor is private.
// Can't use make_unique because LoadedIdmap constructor is private.
std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
new LoadedIdmap(header, data_header, target_entries, overlay_entries,
idmap_string_pool.release()));

View File

@@ -397,9 +397,7 @@ const LoadedPackage* LoadedArsc::GetPackageById(uint8_t package_id) const {
}
std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
bool system,
bool load_as_shared_library,
bool for_loader) {
package_property_t property_flags) {
ATRACE_NAME("LoadedPackage::Load");
std::unique_ptr<LoadedPackage> loaded_package(new LoadedPackage());
@@ -413,17 +411,24 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
return {};
}
loaded_package->system_ = system;
if ((property_flags & PROPERTY_SYSTEM) != 0) {
loaded_package->property_flags_ |= PROPERTY_SYSTEM;
}
if ((property_flags & PROPERTY_LOADER) != 0) {
loaded_package->property_flags_ |= PROPERTY_LOADER;
}
if ((property_flags & PROPERTY_OVERLAY) != 0) {
// Overlay resources must have an exclusive resource id space for referencing internal
// resources.
loaded_package->property_flags_ |= PROPERTY_OVERLAY | PROPERTY_DYNAMIC;
}
loaded_package->package_id_ = dtohl(header->id);
if (loaded_package->package_id_ == 0 ||
(loaded_package->package_id_ == kAppPackageId && load_as_shared_library)) {
// Package ID of 0 means this is a shared library.
loaded_package->dynamic_ = true;
}
if (for_loader) {
loaded_package->custom_loader_ = true;
(loaded_package->package_id_ == kAppPackageId && (property_flags & PROPERTY_DYNAMIC) != 0)) {
loaded_package->property_flags_ |= PROPERTY_DYNAMIC;
}
if (header->header.headerSize >= sizeof(ResTable_package)) {
@@ -677,7 +682,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
}
bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
bool load_as_shared_library, bool for_loader) {
package_property_t property_flags) {
const ResTable_header* header = chunk.header<ResTable_header>();
if (header == nullptr) {
LOG(ERROR) << "RES_TABLE_TYPE too small.";
@@ -720,7 +725,7 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
packages_seen++;
std::unique_ptr<const LoadedPackage> loaded_package =
LoadedPackage::Load(child_chunk, system_, load_as_shared_library, for_loader);
LoadedPackage::Load(child_chunk, property_flags);
if (!loaded_package) {
return false;
}
@@ -744,24 +749,18 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const StringPiece& data,
const LoadedIdmap* loaded_idmap,
bool system,
bool load_as_shared_library,
bool for_loader) {
package_property_t property_flags) {
ATRACE_NAME("LoadedArsc::Load");
// Not using make_unique because the constructor is private.
std::unique_ptr<LoadedArsc> loaded_arsc(new LoadedArsc());
loaded_arsc->system_ = system;
ChunkIterator iter(data.data(), data.size());
while (iter.HasNext()) {
const Chunk chunk = iter.Next();
switch (chunk.type()) {
case RES_TABLE_TYPE:
if (!loaded_arsc->LoadTable(chunk,
loaded_idmap,
load_as_shared_library,
for_loader)) {
if (!loaded_arsc->LoadTable(chunk, loaded_idmap, property_flags)) {
return {};
}
break;

View File

@@ -76,10 +76,10 @@ class ApkAssets {
// Takes ownership of the file descriptor.
static std::unique_ptr<const ApkAssets> LoadArsc(base::unique_fd fd,
const std::string& friendly_name,
bool resource_loader = false);
bool for_loader = false);
// Creates a totally empty ApkAssets with no resources table and no file entries.
static std::unique_ptr<const ApkAssets> LoadEmpty(bool resource_loader = false);
static std::unique_ptr<const ApkAssets> LoadEmpty(bool for_loader = false);
std::unique_ptr<Asset> Open(const std::string& path,
Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const;
@@ -100,12 +100,12 @@ class ApkAssets {
return loaded_idmap_.get();
}
inline bool IsOverlay() const {
return idmap_asset_.get() != nullptr;
inline bool IsLoader() const {
return (property_flags_ & PROPERTY_LOADER) != 0;
}
inline bool IsLoader() const {
return for_loader_;
inline bool IsOverlay() const {
return (property_flags_ & PROPERTY_OVERLAY) != 0;
}
bool IsUpToDate() const;
@@ -119,24 +119,23 @@ class ApkAssets {
static std::unique_ptr<const ApkAssets> LoadImpl(base::unique_fd fd, const std::string& path,
std::unique_ptr<Asset> idmap_asset,
std::unique_ptr<const LoadedIdmap> loaded_idmap,
bool system, bool load_as_shared_library,
bool resource_loader = false);
package_property_t property_flags);
static std::unique_ptr<const ApkAssets> LoadArscImpl(base::unique_fd fd,
const std::string& path,
bool resource_loader = false);
package_property_t property_flags);
ApkAssets(ZipArchiveHandle unmanaged_handle,
const std::string& path,
time_t last_mod_time,
bool for_loader = false);
package_property_t property_flags);
using ZipArchivePtr = std::unique_ptr<ZipArchive, void (*)(ZipArchiveHandle)>;
ZipArchivePtr zip_handle_;
const std::string path_;
time_t last_mod_time_;
bool for_loader_;
package_property_t property_flags_ = 0U;
std::unique_ptr<Asset> resources_asset_;
std::unique_ptr<Asset> idmap_asset_;
std::unique_ptr<const LoadedArsc> loaded_arsc_;

View File

@@ -263,10 +263,13 @@ class AssetManager2 {
// Creates a new Theme from this AssetManager.
std::unique_ptr<Theme> NewTheme();
void ForEachPackage(const std::function<bool(const std::string&, uint8_t)> func) const {
void ForEachPackage(const std::function<bool(const std::string&, uint8_t)> func,
package_property_t excluded_property_flags = 0U) const {
for (const PackageGroup& package_group : package_groups_) {
if (!func(package_group.packages_.front().loaded_package_->GetPackageName(),
package_group.dynamic_ref_table->mAssignedPackageId)) {
const auto loaded_package = package_group.packages_.front().loaded_package_;
if ((loaded_package->GetPropertyFlags() & excluded_property_flags) == 0U
&& !func(loaded_package->GetPackageName(),
package_group.dynamic_ref_table->mAssignedPackageId)) {
return;
}
}

View File

@@ -69,6 +69,14 @@ struct TypeSpec {
}
};
using package_property_t = uint32_t;
enum : package_property_t {
PROPERTY_DYNAMIC = 1,
PROPERTY_LOADER = 2,
PROPERTY_OVERLAY = 4,
PROPERTY_SYSTEM = 8,
};
// TypeSpecPtr points to a block of memory that holds a TypeSpec struct, followed by an array of
// ResTable_type pointers.
// TypeSpecPtr is a managed pointer that knows how to delete itself.
@@ -131,9 +139,8 @@ class LoadedPackage {
return iterator(this, resource_ids_.size() + 1, 0);
}
static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk, bool system,
bool load_as_shared_library,
bool load_as_custom_loader);
static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
package_property_t property_flags);
~LoadedPackage();
@@ -170,17 +177,26 @@ class LoadedPackage {
// Returns true if this package is dynamic (shared library) and needs to have an ID assigned.
inline bool IsDynamic() const {
return dynamic_;
return (property_flags_ & PROPERTY_DYNAMIC) != 0;
}
// Returns true if this package is a Runtime Resource Overlay.
inline bool IsOverlay() const {
return (property_flags_ & PROPERTY_OVERLAY) != 0;
}
// Returns true if this package originates from a system provided resource.
inline bool IsSystem() const {
return system_;
return (property_flags_ & PROPERTY_SYSTEM) != 0;
}
// Returns true if this package is a custom loader and should behave like an overlay
// Returns true if this package is a custom loader and should behave like an overlay.
inline bool IsCustomLoader() const {
return custom_loader_;
return (property_flags_ & PROPERTY_LOADER) != 0;
}
inline package_property_t GetPropertyFlags() const {
return property_flags_;
}
// Returns the map of package name to package ID used in this LoadedPackage. At runtime, a
@@ -248,12 +264,10 @@ class LoadedPackage {
ResStringPool type_string_pool_;
ResStringPool key_string_pool_;
std::string package_name_;
bool defines_overlayable_ = false;
int package_id_ = -1;
int type_id_offset_ = 0;
bool dynamic_ = false;
bool system_ = false;
bool custom_loader_ = false;
bool defines_overlayable_ = false;
package_property_t property_flags_ = 0U;
ByteBucketArray<TypeSpecPtr> type_specs_;
ByteBucketArray<uint32_t> resource_ids_;
@@ -274,9 +288,7 @@ class LoadedArsc {
// ID.
static std::unique_ptr<const LoadedArsc> Load(const StringPiece& data,
const LoadedIdmap* loaded_idmap = nullptr,
bool system = false,
bool load_as_shared_library = false,
bool for_loader = false);
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();
@@ -296,28 +308,15 @@ class LoadedArsc {
return packages_;
}
// Returns true if this is a system provided resource.
inline bool IsSystem() const {
return system_;
}
private:
DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
LoadedArsc() = default;
bool LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library,
bool for_loader);
static std::unique_ptr<const LoadedArsc> LoadData(std::unique_ptr<LoadedArsc>& loaded_arsc,
const char* data,
size_t length,
const LoadedIdmap* loaded_idmap = nullptr,
bool load_as_shared_library = false,
bool for_loader = false);
bool LoadTable(
const Chunk& chunk, const LoadedIdmap* loaded_idmap, package_property_t property_flags);
std::unique_ptr<ResStringPool> global_string_pool_ = util::make_unique<ResStringPool>();
std::vector<std::unique_ptr<const LoadedPackage>> packages_;
bool system_ = false;
};
} // namespace android

View File

@@ -144,8 +144,7 @@ TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
"resources.arsc", &contents));
std::unique_ptr<const LoadedArsc> loaded_arsc =
LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, false /*system*/,
true /*load_as_shared_library*/);
LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, PROPERTY_DYNAMIC);
ASSERT_THAT(loaded_arsc, NotNull());
const auto& packages = loaded_arsc->GetPackages();
@@ -227,9 +226,7 @@ TEST(LoadedArscTest, LoadOverlayable) {
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlayable/overlayable.apk",
"resources.arsc", &contents));
std::unique_ptr<const LoadedArsc> loaded_arsc =
LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, false /*system*/,
false /*load_as_shared_library*/);
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
ASSERT_THAT(loaded_arsc, NotNull());
const LoadedPackage* package = loaded_arsc->GetPackageById(
@@ -346,7 +343,7 @@ TEST(LoadedArscTest, LoadCustomLoader) {
asset->getLength());
std::unique_ptr<const LoadedArsc> loaded_arsc =
LoadedArsc::Load(data, nullptr, false, false, true);
LoadedArsc::Load(data, nullptr, PROPERTY_LOADER);
ASSERT_THAT(loaded_arsc, NotNull());
const LoadedPackage* package =