summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/androidfw/AssetManager2.cpp25
-rw-r--r--libs/androidfw/include/androidfw/AssetManager2.h6
-rw-r--r--libs/androidfw/tests/AssetManager2_test.cpp56
3 files changed, 62 insertions, 25 deletions
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 803828fc16c5..eaf452b5fa71 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -88,13 +88,24 @@ void AssetManager2::BuildDynamicRefTable() {
// A mapping from apk assets path to the runtime package id of its first loaded package.
std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
+ // Overlay resources are not directly referenced by an application so their resource ids
+ // can change throughout the application's lifetime. Assign overlay package ids last.
+ std::vector<const ApkAssets*> sorted_apk_assets(apk_assets_);
+ std::stable_partition(sorted_apk_assets.begin(), sorted_apk_assets.end(), [](const ApkAssets* a) {
+ return !a->IsOverlay();
+ });
+
+ // The assets cookie must map to the position of the apk assets in the unsorted apk assets list.
+ std::unordered_map<const ApkAssets*, ApkAssetsCookie> apk_assets_cookies;
+ apk_assets_cookies.reserve(apk_assets_.size());
+ for (size_t i = 0, n = apk_assets_.size(); i < n; i++) {
+ apk_assets_cookies[apk_assets_[i]] = static_cast<ApkAssetsCookie>(i);
+ }
+
// 0x01 is reserved for the android package.
int next_package_id = 0x02;
- const size_t apk_assets_count = apk_assets_.size();
- for (size_t i = 0; i < apk_assets_count; i++) {
- const ApkAssets* apk_assets = apk_assets_[i];
+ for (const ApkAssets* apk_assets : sorted_apk_assets) {
const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc();
-
for (const std::unique_ptr<const LoadedPackage>& package : loaded_arsc->GetPackages()) {
// Get the package ID or assign one if a shared library.
int package_id;
@@ -126,7 +137,7 @@ void AssetManager2::BuildDynamicRefTable() {
PackageGroup& target_package_group = package_groups_[target_idx];
- // Create a special dynamic reference table for the overlay to rewite references to
+ // Create a special dynamic reference table for the overlay to rewrite references to
// overlay resources as references to the target resources they overlay.
auto overlay_table = std::make_shared<OverlayDynamicRefTable>(
loaded_idmap->GetOverlayDynamicRefTable(target_package_id));
@@ -136,7 +147,7 @@ void AssetManager2::BuildDynamicRefTable() {
target_package_group.overlays_.push_back(
ConfiguredOverlay{loaded_idmap->GetTargetResourcesMap(target_package_id,
overlay_table.get()),
- static_cast<ApkAssetsCookie>(i)});
+ apk_assets_cookies[apk_assets]});
}
}
@@ -148,7 +159,7 @@ void AssetManager2::BuildDynamicRefTable() {
// Add the package and to the set of packages with the same ID.
package_group->packages_.push_back(ConfiguredPackage{package.get(), {}});
- package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i));
+ package_group->cookies_.push_back(apk_assets_cookies[apk_assets]);
// Add the package name -> build time ID mappings.
for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) {
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 00cbbcad56e6..e21abade99a4 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -124,6 +124,9 @@ class AssetManager2 {
// This may be nullptr if the APK represented by `cookie` has no resource table.
std::shared_ptr<const DynamicRefTable> GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
+ // Retrieve the assigned package id of the package if loaded into this AssetManager
+ uint8_t GetAssignedPackageId(const LoadedPackage* package) const;
+
// Returns a string representation of the overlayable API of a package.
bool GetOverlayablesToString(const android::StringPiece& package_name,
std::string* out) const;
@@ -368,9 +371,6 @@ class AssetManager2 {
// been seen while traversing bag parents.
const ResolvedBag* GetBag(uint32_t resid, std::vector<uint32_t>& child_resids);
- // Retrieve the assigned package id of the package if loaded into this AssetManager
- uint8_t GetAssignedPackageId(const LoadedPackage* package) const;
-
// The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must
// have a longer lifetime.
std::vector<const ApkAssets*> apk_assets_;
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 6054fa3338bd..8c255d16fe1f 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -17,9 +17,9 @@
#include "androidfw/AssetManager2.h"
#include "androidfw/AssetManager.h"
-#include "android-base/logging.h"
-
#include "TestHelpers.h"
+#include "android-base/file.h"
+#include "android-base/logging.h"
#include "androidfw/ResourceUtils.h"
#include "data/appaslib/R.h"
#include "data/basic/R.h"
@@ -45,37 +45,43 @@ namespace android {
class AssetManager2Test : public ::testing::Test {
public:
void SetUp() override {
- basic_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+ // Move to the test data directory so the idmap can locate the overlay APK.
+ std::string original_path = base::GetExecutableDirectory();
+ chdir(GetTestDataPath().c_str());
+
+ basic_assets_ = ApkAssets::Load("basic/basic.apk");
ASSERT_NE(nullptr, basic_assets_);
- basic_de_fr_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic_de_fr.apk");
+ basic_de_fr_assets_ = ApkAssets::Load("basic/basic_de_fr.apk");
ASSERT_NE(nullptr, basic_de_fr_assets_);
- style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+ style_assets_ = ApkAssets::Load("styles/styles.apk");
ASSERT_NE(nullptr, style_assets_);
- lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
+ lib_one_assets_ = ApkAssets::Load("lib_one/lib_one.apk");
ASSERT_NE(nullptr, lib_one_assets_);
- lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
+ lib_two_assets_ = ApkAssets::Load("lib_two/lib_two.apk");
ASSERT_NE(nullptr, lib_two_assets_);
- libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
+ libclient_assets_ = ApkAssets::Load("libclient/libclient.apk");
ASSERT_NE(nullptr, libclient_assets_);
- appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk",
- PROPERTY_DYNAMIC);
+ appaslib_assets_ = ApkAssets::Load("appaslib/appaslib.apk", PROPERTY_DYNAMIC);
ASSERT_NE(nullptr, appaslib_assets_);
- system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk",
- PROPERTY_SYSTEM);
+ system_assets_ = ApkAssets::Load("system/system.apk", PROPERTY_SYSTEM);
ASSERT_NE(nullptr, system_assets_);
- app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk");
+ app_assets_ = ApkAssets::Load("app/app.apk");
ASSERT_THAT(app_assets_, NotNull());
- overlayable_assets_ = ApkAssets::Load(GetTestDataPath() + "/overlayable/overlayable.apk");
+ overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap");
+ ASSERT_NE(nullptr, overlay_assets_);
+
+ overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");
ASSERT_THAT(overlayable_assets_, NotNull());
+ chdir(original_path.c_str());
}
protected:
@@ -88,6 +94,7 @@ class AssetManager2Test : public ::testing::Test {
std::unique_ptr<const ApkAssets> appaslib_assets_;
std::unique_ptr<const ApkAssets> system_assets_;
std::unique_ptr<const ApkAssets> app_assets_;
+ std::unique_ptr<const ApkAssets> overlay_assets_;
std::unique_ptr<const ApkAssets> overlayable_assets_;
};
@@ -216,6 +223,26 @@ TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) {
EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
}
+TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets(
+ {overlayable_assets_.get(), overlay_assets_.get(), lib_one_assets_.get()});
+
+ auto apk_assets = assetmanager.GetApkAssets();
+ ASSERT_EQ(3, apk_assets.size());
+ ASSERT_EQ(overlayable_assets_.get(), apk_assets[0]);
+ ASSERT_EQ(overlay_assets_.get(), apk_assets[1]);
+ ASSERT_EQ(lib_one_assets_.get(), apk_assets[2]);
+
+ auto get_first_package_id = [&assetmanager](const ApkAssets* apkAssets) -> uint8_t {
+ return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get());
+ };
+
+ ASSERT_EQ(get_first_package_id(overlayable_assets_.get()), 0x7f);
+ ASSERT_EQ(get_first_package_id(overlay_assets_.get()), 0x03);
+ ASSERT_EQ(get_first_package_id(lib_one_assets_.get()), 0x02);
+}
+
TEST_F(AssetManager2Test, GetSharedLibraryResourceName) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({lib_one_assets_.get()});
@@ -751,7 +778,6 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) {
ASSERT_EQ(api.find("not_overlayable"), std::string::npos);
ASSERT_NE(api.find("resource='com.android.overlayable:string/overlayable2' overlayable='OverlayableResources1' actor='overlay://theme' policy='0x0000000a'\n"),
std::string::npos);
-
}
} // namespace android