summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/jni/android_util_AssetManager.cpp4
-rw-r--r--libs/androidfw/Android.bp1
-rw-r--r--libs/androidfw/AssetManager2.cpp72
-rw-r--r--libs/androidfw/DynamicLibManager.cpp34
-rw-r--r--libs/androidfw/include/androidfw/AssetManager2.h7
-rw-r--r--libs/androidfw/include/androidfw/DynamicLibManager.h48
-rw-r--r--libs/androidfw/include/androidfw/MutexGuard.h3
-rw-r--r--libs/androidfw/tests/AssetManager2_test.cpp19
8 files changed, 168 insertions, 20 deletions
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index ff596b440867..062b886f54a1 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -220,8 +220,12 @@ static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& valu
// ----------------------------------------------------------------------------
+static std::unique_ptr<DynamicLibManager> sDynamicLibManager =
+ std::make_unique<DynamicLibManager>();
+
// Let the opaque type AAssetManager refer to a guarded AssetManager2 instance.
struct GuardedAssetManager : public ::AAssetManager {
+ GuardedAssetManager() : guarded_assetmanager(sDynamicLibManager.get()) {}
Guarded<AssetManager2> guarded_assetmanager;
};
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 87657191e901..3f2f3495ae8f 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -44,6 +44,7 @@ cc_library {
"AttributeResolution.cpp",
"ChunkIterator.cpp",
"ConfigDescription.cpp",
+ "DynamicLibManager.cpp",
"Idmap.cpp",
"LoadedArsc.cpp",
"Locale.cpp",
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index ca4143f3e215..2c6be41052e8 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -25,6 +25,7 @@
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
+#include "androidfw/DynamicLibManager.h"
#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"
#include "utils/ByteOrder.h"
@@ -66,7 +67,12 @@ struct FindEntryResult {
StringPoolRef entry_string_ref;
};
-AssetManager2::AssetManager2() {
+AssetManager2::AssetManager2() : dynamic_lib_manager_(std::make_unique<DynamicLibManager>()) {
+ memset(&configuration_, 0, sizeof(configuration_));
+}
+
+AssetManager2::AssetManager2(DynamicLibManager* dynamic_lib_manager)
+ : dynamic_lib_manager_(dynamic_lib_manager) {
memset(&configuration_, 0, sizeof(configuration_));
}
@@ -85,24 +91,44 @@ void AssetManager2::BuildDynamicRefTable() {
package_groups_.clear();
package_ids_.fill(0xff);
- // A mapping from apk assets path to the runtime package id of its first loaded package.
+ // 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();
+ });
+
std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
+ std::unordered_map<std::string, uint8_t> package_name_package_ids;
+
+ // Assign stable package ids to application packages.
+ uint8_t next_available_package_id = 0U;
+ for (const auto& apk_assets : sorted_apk_assets) {
+ for (const auto& package : apk_assets->GetLoadedArsc()->GetPackages()) {
+ uint8_t package_id = package->GetPackageId();
+ if (package->IsOverlay()) {
+ package_id = GetDynamicLibManager()->FindUnassignedId(next_available_package_id);
+ next_available_package_id = package_id + 1;
+ } else if (package->IsDynamic()) {
+ package_id = GetDynamicLibManager()->GetAssignedId(package->GetPackageName());
+ }
- // 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];
- const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc();
+ // Map the path of the apk assets to the package id of its first loaded package.
+ apk_assets_package_ids[apk_assets->GetPath()] = package_id;
- 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;
- if (package->IsDynamic()) {
- package_id = next_package_id++;
- } else {
- package_id = package->GetPackageId();
- }
+ // Map the package name of the package to the first loaded package with that package id.
+ package_name_package_ids[package->GetPackageName()] = package_id;
+ }
+ }
+
+ const int apk_assets_count = apk_assets_.size();
+ for (int i = 0; i < apk_assets_count; i++) {
+ const auto& apk_assets = apk_assets_[i];
+ for (const auto& package : apk_assets->GetLoadedArsc()->GetPackages()) {
+ const auto package_id_entry = package_name_package_ids.find(package->GetPackageName());
+ CHECK(package_id_entry != package_name_package_ids.end())
+ << "no package id assgined to package " << package->GetPackageName();
+ const uint8_t package_id = package_id_entry->second;
// Add the mapping for package ID to index if not present.
uint8_t idx = package_ids_[package_id];
@@ -123,7 +149,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));
@@ -153,8 +179,6 @@ void AssetManager2::BuildDynamicRefTable() {
package_group->dynamic_ref_table->mEntries.replaceValueFor(
package_name, static_cast<uint8_t>(entry.package_id));
}
-
- apk_assets_package_ids.insert(std::make_pair(apk_assets->GetPath(), package_id));
}
}
@@ -1279,6 +1303,16 @@ uint8_t AssetManager2::GetAssignedPackageId(const LoadedPackage* package) const
return 0;
}
+DynamicLibManager* AssetManager2::GetDynamicLibManager() const {
+ auto dynamic_lib_manager =
+ std::get_if<std::unique_ptr<DynamicLibManager>>(&dynamic_lib_manager_);
+ if (dynamic_lib_manager) {
+ return (*dynamic_lib_manager).get();
+ } else {
+ return *std::get_if<DynamicLibManager*>(&dynamic_lib_manager_);
+ }
+}
+
std::unique_ptr<Theme> AssetManager2::NewTheme() {
return std::unique_ptr<Theme>(new Theme(this));
}
diff --git a/libs/androidfw/DynamicLibManager.cpp b/libs/androidfw/DynamicLibManager.cpp
new file mode 100644
index 000000000000..895b7695bf26
--- /dev/null
+++ b/libs/androidfw/DynamicLibManager.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 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/DynamicLibManager.h"
+
+namespace android {
+
+uint8_t DynamicLibManager::GetAssignedId(const std::string& library_package_name) {
+ auto lib_entry = shared_lib_package_ids_.find(library_package_name);
+ if (lib_entry != shared_lib_package_ids_.end()) {
+ return lib_entry->second;
+ }
+
+ return shared_lib_package_ids_[library_package_name] = next_package_id_++;
+}
+
+uint8_t DynamicLibManager::FindUnassignedId(uint8_t start_package_id) {
+ return (start_package_id < next_package_id_) ? next_package_id_ : start_package_id;
+}
+
+} // namespace android
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 00cbbcad56e6..b2cec2a42994 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -27,6 +27,7 @@
#include "androidfw/ApkAssets.h"
#include "androidfw/Asset.h"
#include "androidfw/AssetManager.h"
+#include "androidfw/DynamicLibManager.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
@@ -94,6 +95,7 @@ class AssetManager2 {
};
AssetManager2();
+ explicit AssetManager2(DynamicLibManager* dynamic_lib_manager);
// Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets
// are not owned by the AssetManager, and must have a longer lifetime.
@@ -371,6 +373,8 @@ class AssetManager2 {
// Retrieve the assigned package id of the package if loaded into this AssetManager
uint8_t GetAssignedPackageId(const LoadedPackage* package) const;
+ DynamicLibManager* GetDynamicLibManager() 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_;
@@ -389,6 +393,9 @@ class AssetManager2 {
// may need to be purged.
ResTable_config configuration_;
+ // Component responsible for assigning package ids to shared libraries.
+ std::variant<std::unique_ptr<DynamicLibManager>, DynamicLibManager*> dynamic_lib_manager_;
+
// Cached set of bags. These are cached because they can inherit keys from parent bags,
// which involves some calculation.
std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_;
diff --git a/libs/androidfw/include/androidfw/DynamicLibManager.h b/libs/androidfw/include/androidfw/DynamicLibManager.h
new file mode 100644
index 000000000000..1ff7079573d2
--- /dev/null
+++ b/libs/androidfw/include/androidfw/DynamicLibManager.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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_DYNAMICLIBMANAGER_H
+#define ANDROIDFW_DYNAMICLIBMANAGER_H
+
+#include <string>
+#include <unordered_map>
+
+#include "android-base/macros.h"
+
+namespace android {
+
+// Manages assigning resource ids for dynamic resources.
+class DynamicLibManager {
+ public:
+ DynamicLibManager() = default;
+
+ // Retrieves the assigned package id for the library.
+ uint8_t GetAssignedId(const std::string& library_package_name);
+
+ // Queries in ascending order for the first available package id that is not currently assigned to
+ // a library.
+ uint8_t FindUnassignedId(uint8_t start_package_id);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DynamicLibManager);
+
+ uint8_t next_package_id_ = 0x02;
+ std::unordered_map<std::string, uint8_t> shared_lib_package_ids_;
+};
+
+} // namespace android
+
+#endif //ANDROIDFW_DYNAMICLIBMANAGER_H
diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h
index 64924f433245..8891512958f0 100644
--- a/libs/androidfw/include/androidfw/MutexGuard.h
+++ b/libs/androidfw/include/androidfw/MutexGuard.h
@@ -47,7 +47,8 @@ class Guarded {
static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer");
public:
- explicit Guarded() : guarded_() {
+ template <typename ...Args>
+ explicit Guarded(Args&& ...args) : guarded_(std::forward<Args>(args)...) {
}
template <typename U = T>
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index b3190be8caf1..2f6f3dfcaf1c 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -214,6 +214,25 @@ TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) {
EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
}
+TEST_F(AssetManager2Test, AssignsUnchangingPackageIdToSharedLibrary) {
+ DynamicLibManager lib_manager;
+ AssetManager2 assetmanager(&lib_manager);
+ assetmanager.SetApkAssets(
+ {lib_one_assets_.get(), lib_two_assets_.get(), libclient_assets_.get()});
+
+ AssetManager2 assetmanager2(&lib_manager);
+ assetmanager2.SetApkAssets(
+ {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+
+ uint32_t res_id = assetmanager.GetResourceId("com.android.lib_one:string/foo");
+ ASSERT_NE(0U, res_id);
+
+ uint32_t res_id_2 = assetmanager2.GetResourceId("com.android.lib_one:string/foo");
+ ASSERT_NE(0U, res_id_2);
+
+ ASSERT_EQ(res_id, res_id_2);
+}
+
TEST_F(AssetManager2Test, GetSharedLibraryResourceName) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({lib_one_assets_.get()});