summaryrefslogtreecommitdiff
path: root/libs/androidfw/include
diff options
context:
space:
mode:
Diffstat (limited to 'libs/androidfw/include')
-rw-r--r--libs/androidfw/include/androidfw/ApkAssets.h158
-rw-r--r--libs/androidfw/include/androidfw/Asset.h30
-rw-r--r--libs/androidfw/include/androidfw/AssetManager2.h128
-rw-r--r--libs/androidfw/include/androidfw/DisplayEventDispatcher.h51
-rw-r--r--libs/androidfw/include/androidfw/Idmap.h173
-rw-r--r--libs/androidfw/include/androidfw/LoadedArsc.h73
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h156
-rw-r--r--libs/androidfw/include/androidfw/Util.h7
8 files changed, 554 insertions, 222 deletions
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 49fc82bff11e..e57490aab2d8 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -24,6 +24,7 @@
#include "android-base/unique_fd.h"
#include "androidfw/Asset.h"
+#include "androidfw/Idmap.h"
#include "androidfw/LoadedArsc.h"
#include "androidfw/misc.h"
@@ -34,79 +35,162 @@ namespace android {
class LoadedIdmap;
+// Interface for retrieving assets provided by an ApkAssets.
+class AssetsProvider {
+ 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);
+ }
+
+ // 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;
+ }
+
+ protected:
+ AssetsProvider() = default;
+
+ 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, bool system = false);
+ 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, but forces any package with ID 0x7f to be loaded as a shared library.
- // 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> LoadAsSharedLibrary(const std::string& path,
- bool system = false);
+ // 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 an IDMAP, which contains the original APK path, and the overlay
// data.
- // 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> LoadOverlay(const std::string& idmap_path,
- bool system = false);
-
- // 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 `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.
- // If `force_shared_lib` is true, any package with ID 0x7f is loaded as a shared library.
- static std::unique_ptr<const ApkAssets> LoadFromFd(base::unique_fd fd,
- const std::string& friendly_name, bool system,
- bool force_shared_lib);
+ package_property_t flags = 0U);
- std::unique_ptr<Asset> Open(const std::string& path,
- Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const;
+ // 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);
- bool ForEachFile(const std::string& path,
- const std::function<void(const StringPiece&, FileType)>& f) const;
+ // 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);
- inline const std::string& GetPath() const {
+ const std::string& GetPath() const {
return path_;
}
+ const AssetsProvider* GetAssetsProvider() const {
+ return assets_provider_.get();
+ }
+
// This is never nullptr.
- inline const LoadedArsc* GetLoadedArsc() const {
+ const LoadedArsc* GetLoadedArsc() const {
return loaded_arsc_.get();
}
- inline bool IsOverlay() const {
- return idmap_asset_.get() != nullptr;
+ const LoadedIdmap* GetLoadedIdmap() const {
+ return loaded_idmap_.get();
+ }
+
+ bool IsLoader() const {
+ return (property_flags_ & PROPERTY_LOADER) != 0;
+ }
+
+ bool IsOverlay() const {
+ return loaded_idmap_ != nullptr;
+ }
+
+ // Returns whether the resources.arsc is allocated in RAM (not mmapped).
+ bool IsTableAllocated() const {
+ return resources_asset_ && 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(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);
-
- // Creates an Asset from any file on the file system.
- static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path);
+ 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);
- ApkAssets(ZipArchiveHandle unmanaged_handle, const std::string& path, time_t last_mod_time);
+ 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);
- using ZipArchivePtr = std::unique_ptr<ZipArchive, void(*)(ZipArchiveHandle)>;
+ ApkAssets(std::unique_ptr<const AssetsProvider> assets_provider,
+ std::string path,
+ time_t last_mod_time,
+ package_property_t property_flags);
- ZipArchivePtr zip_handle_;
+ std::unique_ptr<const AssetsProvider> assets_provider_;
const std::string path_;
time_t last_mod_time_;
+ 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_;
+ std::unique_ptr<const LoadedIdmap> loaded_idmap_;
};
} // namespace android
diff --git a/libs/androidfw/include/androidfw/Asset.h b/libs/androidfw/include/androidfw/Asset.h
index 9d12a35395c9..298509eb37a1 100644
--- a/libs/androidfw/include/androidfw/Asset.h
+++ b/libs/androidfw/include/androidfw/Asset.h
@@ -26,6 +26,7 @@
#include <memory>
+#include <android-base/unique_fd.h>
#include <utils/Compat.h>
#include <utils/Errors.h>
#include <utils/String8.h>
@@ -121,6 +122,11 @@ public:
*/
const char* getAssetSource(void) const { return mAssetSource.string(); }
+ /*
+ * Create the asset from a file descriptor.
+ */
+ static Asset* createFromFd(const int fd, const char* fileName, AccessMode mode);
+
protected:
/*
* Adds this Asset to the global Asset list for debugging and
@@ -153,6 +159,7 @@ private:
/* AssetManager needs access to our "create" functions */
friend class AssetManager;
friend class ApkAssets;
+ friend class ZipAssetsProvider;
/*
* Create the asset from a named file on disk.
@@ -197,8 +204,14 @@ private:
*/
static Asset* createFromUncompressedMap(FileMap* dataMap, AccessMode mode);
+ /*
+ * Create the asset from a memory-mapped file segment.
+ *
+ * The asset takes ownership of the FileMap and the file descriptor "fd". The file descriptor is
+ * used to request new file descriptors using "openFileDescriptor".
+ */
static std::unique_ptr<Asset> createFromUncompressedMap(std::unique_ptr<FileMap> dataMap,
- AccessMode mode);
+ base::unique_fd fd, AccessMode mode);
/*
* Create the asset from a memory-mapped file segment with compressed
@@ -251,9 +264,9 @@ public:
/*
* Use a memory-mapped region.
*
- * On success, the object takes ownership of "dataMap".
+ * On success, the object takes ownership of "dataMap" and "fd".
*/
- status_t openChunk(FileMap* dataMap);
+ status_t openChunk(FileMap* dataMap, base::unique_fd fd);
/*
* Standard Asset interfaces.
@@ -268,11 +281,12 @@ public:
virtual bool isAllocated(void) const { return mBuf != NULL; }
private:
- off64_t mStart; // absolute file offset of start of chunk
- off64_t mLength; // length of the chunk
- off64_t mOffset; // current local offset, 0 == mStart
- FILE* mFp; // for read/seek
- char* mFileName; // for opening
+ off64_t mStart; // absolute file offset of start of chunk
+ off64_t mLength; // length of the chunk
+ off64_t mOffset; // current local offset, 0 == mStart
+ FILE* mFp; // for read/seek
+ char* mFileName; // for opening
+ base::unique_fd mFd; // for opening file descriptors
/*
* To support getBuffer() we either need to read the entire thing into
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 1e2b36cb1703..30ef25c6a516 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -122,11 +122,21 @@ class AssetManager2 {
// Returns the DynamicRefTable for the ApkAssets represented by the cookie.
// This may be nullptr if the APK represented by `cookie` has no resource table.
- const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
+ 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;
const std::unordered_map<std::string, std::string>*
GetOverlayableMapForPackage(uint32_t package_id) const;
+ // Returns whether the resources.arsc of any loaded apk assets is allocated in RAM (not mmapped).
+ bool ContainsAllocatedTable() const;
+
// Sets/resets the configuration for this AssetManager. This will cause all
// caches that are related to the configuration change to be invalidated.
void SetConfiguration(const ResTable_config& configuration);
@@ -232,12 +242,14 @@ class AssetManager2 {
ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
uint32_t* out_last_reference) const;
- // Enables or disables resource resolution logging. Clears stored steps when
- // disabled.
+ // Resets the resource resolution structures in preparation for the next resource retrieval.
+ void ResetResourceResolution() const;
+
+ // Enables or disables resource resolution logging. Clears stored steps when disabled.
void SetResourceResolutionLoggingEnabled(bool enabled);
- // Returns formatted log of last resource resolution path, or empty if no
- // resource has been resolved yet.
+ // Returns formatted log of last resource resolution path, or empty if no resource has been
+ // resolved yet.
std::string GetLastResourceResolution() const;
const std::vector<uint32_t> GetBagResIdStack(uint32_t resid);
@@ -257,10 +269,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;
}
}
@@ -271,6 +286,50 @@ class AssetManager2 {
private:
DISALLOW_COPY_AND_ASSIGN(AssetManager2);
+ // A collection of configurations and their associated ResTable_type that match the current
+ // AssetManager configuration.
+ struct FilteredConfigGroup {
+ std::vector<ResTable_config> configurations;
+ std::vector<const ResTable_type*> types;
+ };
+
+ // Represents an single package.
+ struct ConfiguredPackage {
+ // A pointer to the immutable, loaded package info.
+ const LoadedPackage* loaded_package_;
+
+ // A mutable AssetManager-specific list of configurations that match the AssetManager's
+ // current configuration. This is used as an optimization to avoid checking every single
+ // candidate configuration when looking up resources.
+ ByteBucketArray<FilteredConfigGroup> filtered_configs_;
+ };
+
+ // Represents a Runtime Resource Overlay that overlays resources in the logical package.
+ struct ConfiguredOverlay {
+ // The set of package groups that overlay this package group.
+ IdmapResMap overlay_res_maps_;
+
+ // The cookie of the overlay assets.
+ ApkAssetsCookie cookie;
+ };
+
+ // Represents a logical package, which can be made up of many individual packages. Each package
+ // in a PackageGroup shares the same package name and package ID.
+ struct PackageGroup {
+ // The set of packages that make-up this group.
+ std::vector<ConfiguredPackage> packages_;
+
+ // The cookies associated with each package in the group. They share the same order as
+ // packages_.
+ std::vector<ApkAssetsCookie> cookies_;
+
+ // Runtime Resource Overlays that overlay resources in this package group.
+ std::vector<ConfiguredOverlay> overlays_;
+
+ // A library reference table that contains build-package ID to runtime-package ID mappings.
+ std::shared_ptr<DynamicRefTable> dynamic_ref_table = std::make_shared<DynamicRefTable>();
+ };
+
// Finds the best entry for `resid` from the set of ApkAssets. The entry can be a simple
// Res_value, or a complex map/bag type. If successful, it is available in `out_entry`.
// Returns kInvalidCookie on failure. Otherwise, the return value is the cookie associated with
@@ -291,6 +350,11 @@ class AssetManager2 {
ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
bool ignore_configuration, FindEntryResult* out_entry) const;
+ ApkAssetsCookie FindEntryInternal(const PackageGroup& package_group, uint8_t type_idx,
+ uint16_t entry_idx, const ResTable_config& desired_config,
+ bool /*stop_at_first_match*/,
+ bool ignore_configuration, FindEntryResult* out_entry) const;
+
// Assigns package IDs to all shared library ApkAssets.
// Should be called whenever the ApkAssets are changed.
void BuildDynamicRefTable();
@@ -303,49 +367,17 @@ class AssetManager2 {
// This should always be called when mutating the AssetManager's configuration or ApkAssets set.
void RebuildFilterList(bool filter_incompatible_configs = true);
+ // Retrieves the APK paths of overlays that overlay non-system packages.
+ std::set<std::string> GetNonSystemOverlayPaths() const;
+
// AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
// 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);
-
// 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_;
- // A collection of configurations and their associated ResTable_type that match the current
- // AssetManager configuration.
- struct FilteredConfigGroup {
- std::vector<ResTable_config> configurations;
- std::vector<const ResTable_type*> types;
- };
-
- // Represents an single package.
- struct ConfiguredPackage {
- // A pointer to the immutable, loaded package info.
- const LoadedPackage* loaded_package_;
-
- // A mutable AssetManager-specific list of configurations that match the AssetManager's
- // current configuration. This is used as an optimization to avoid checking every single
- // candidate configuration when looking up resources.
- ByteBucketArray<FilteredConfigGroup> filtered_configs_;
- };
-
- // Represents a logical package, which can be made up of many individual packages. Each package
- // in a PackageGroup shares the same package name and package ID.
- struct PackageGroup {
- // The set of packages that make-up this group.
- std::vector<ConfiguredPackage> packages_;
-
- // The cookies associated with each package in the group. They share the same order as
- // packages_.
- std::vector<ApkAssetsCookie> cookies_;
-
- // A library reference table that contains build-package ID to runtime-package ID mappings.
- DynamicRefTable dynamic_ref_table;
- };
-
// DynamicRefTables for shared library package resolution.
// These are ordered according to apk_assets_. The mappings may change depending on what is
// in apk_assets_, therefore they must be stored in the AssetManager and not in the
@@ -378,7 +410,13 @@ class AssetManager2 {
enum class Type {
INITIAL,
BETTER_MATCH,
- OVERLAID
+ BETTER_MATCH_LOADER,
+ OVERLAID,
+ OVERLAID_LOADER,
+ SKIPPED,
+ SKIPPED_LOADER,
+ NO_ENTRY,
+ NO_ENTRY_LOADER,
};
// Marks what kind of override this step was.
@@ -408,7 +446,7 @@ class AssetManager2 {
};
// Record of the last resolved resource's resolution path.
- mutable Resolution last_resolution;
+ mutable Resolution last_resolution_;
};
class Theme {
diff --git a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
deleted file mode 100644
index 8bc25202b3ab..000000000000
--- a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2015 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 <gui/DisplayEventReceiver.h>
-#include <utils/Log.h>
-#include <utils/Looper.h>
-
-namespace android {
-
-class DisplayEventDispatcher : public LooperCallback {
-public:
- explicit DisplayEventDispatcher(const sp<Looper>& looper,
- ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
- ISurfaceComposer::ConfigChanged configChanged = ISurfaceComposer::eConfigChangedSuppress);
-
- status_t initialize();
- void dispose();
- status_t scheduleVsync();
-
-protected:
- virtual ~DisplayEventDispatcher() = default;
-
-private:
- sp<Looper> mLooper;
- DisplayEventReceiver mReceiver;
- bool mWaitingForVsync;
-
- virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) = 0;
- virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
- bool connected) = 0;
- virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
- int32_t configId) = 0;
-
- virtual int handleEvent(int receiveFd, int events, void* data);
- bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
- uint32_t* outCount);
-};
-}
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index fd02e6f63b74..ecc1ce65d124 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -20,55 +20,190 @@
#include <memory>
#include <string>
#include <unordered_map>
+#include <variant>
#include "android-base/macros.h"
-
#include "androidfw/StringPiece.h"
+#include "androidfw/ResourceTypes.h"
+#include "utils/ByteOrder.h"
namespace android {
-struct Idmap_header;
-struct IdmapEntry_header;
+class LoadedIdmap;
+class IdmapResMap;
+
+// A string pool for overlay apk assets. The string pool holds the strings of the overlay resources
+// table and additionally allows for loading strings from the idmap string pool. The idmap string
+// pool strings are offset after the end of the overlay resource table string pool entries so
+// queries for strings defined inline in the idmap do not conflict with queries for overlay
+// resource table strings.
+class OverlayStringPool : public ResStringPool {
+ public:
+ virtual ~OverlayStringPool();
+ const char16_t* stringAt(size_t idx, size_t* outLen) const override;
+ const char* string8At(size_t idx, size_t* outLen) const override;
+ size_t size() const override;
+
+ explicit OverlayStringPool(const LoadedIdmap* loaded_idmap);
+ private:
+ const Idmap_data_header* data_header_;
+ const ResStringPool* idmap_string_pool_;
+};
+
+// A dynamic reference table for loaded overlay packages that rewrites the resource id of overlay
+// resources to the resource id of corresponding target resources.
+class OverlayDynamicRefTable : public DynamicRefTable {
+ public:
+ ~OverlayDynamicRefTable() override = default;
+ status_t lookupResourceId(uint32_t* resId) const override;
+
+ private:
+ explicit OverlayDynamicRefTable(const Idmap_data_header* data_header,
+ const Idmap_overlay_entry* entries,
+ uint8_t target_assigned_package_id);
+
+ // Rewrites a compile-time overlay resource id to the runtime resource id of corresponding target
+ // resource.
+ virtual status_t lookupResourceIdNoRewrite(uint32_t* resId) const;
+
+ const Idmap_data_header* data_header_;
+ const Idmap_overlay_entry* entries_;
+ const int8_t target_assigned_package_id_;
+
+ friend LoadedIdmap;
+ friend IdmapResMap;
+};
+
+// A mapping of target resource ids to a values or resource ids that should overlay the target.
+class IdmapResMap {
+ public:
+ // Represents the result of a idmap lookup. The result can be one of three possibillities:
+ // 1) The result is a resource id which represents the overlay resource that should act as an
+ // alias of the target resource.
+ // 2) The result is a table entry which overlays the type and value of the target resource.
+ // 3) The result is neither and the target resource is not overlaid.
+ class Result {
+ public:
+ Result() : data_(nullptr) {};
+ explicit Result(uint32_t value) : data_(value) {};
+ explicit Result(ResTable_entry_handle&& value) : data_(value) { };
+
+ // Returns `true` if the resource is overlaid.
+ inline explicit operator bool() const {
+ return !std::get_if<nullptr_t>(&data_);
+ }
+
+ inline bool IsResourceId() const {
+ return std::get_if<uint32_t>(&data_);
+ }
+
+ inline uint32_t GetResourceId() const {
+ return *std::get_if<uint32_t>(&data_);
+ }
+
+ inline bool IsTableEntry() const {
+ return std::get_if<ResTable_entry_handle>(&data_);
+ }
+
+ inline const ResTable_entry_handle& GetTableEntry() const {
+ return *std::get_if<ResTable_entry_handle>(&data_);
+ }
+
+ private:
+ std::variant<uint32_t, nullptr_t, ResTable_entry_handle> data_;
+ };
+
+ // Looks up the value that overlays the target resource id.
+ Result Lookup(uint32_t target_res_id) const;
+
+ inline const OverlayDynamicRefTable* GetOverlayDynamicRefTable() const {
+ return overlay_ref_table_;
+ }
+
+ private:
+ explicit IdmapResMap(const Idmap_data_header* data_header,
+ const Idmap_target_entry* entries,
+ uint8_t target_assigned_package_id,
+ const OverlayDynamicRefTable* overlay_ref_table);
+
+ const Idmap_data_header* data_header_;
+ const Idmap_target_entry* entries_;
+ const uint8_t target_assigned_package_id_;
+ const OverlayDynamicRefTable* overlay_ref_table_;
+
+ friend LoadedIdmap;
+};
// Represents a loaded/parsed IDMAP for a Runtime Resource Overlay (RRO).
-// An RRO and its target APK have different resource IDs assigned to their resources. Overlaying
-// a resource is done by resource name. An IDMAP is a generated mapping between the resource IDs
-// of the RRO and the target APK for each resource with the same name.
+// An RRO and its target APK have different resource IDs assigned to their resources.
+// An IDMAP is a generated mapping between the resource IDs of the RRO and the target APK.
// A LoadedIdmap can be set alongside the overlay's LoadedArsc to allow the overlay ApkAssets to
// masquerade as the target ApkAssets resources.
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_data);
-
- // Performs a lookup of the expected entry ID for the given IDMAP entry header.
- // Returns true if the mapping exists and fills `output_entry_id` with the result.
- static bool Lookup(const IdmapEntry_header* header, uint16_t input_entry_id,
- uint16_t* output_entry_id);
+ static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_path,
+ const StringPiece& idmap_data);
- // Returns the package ID for which this overlay should apply.
- uint8_t TargetPackageId() const;
+ // Returns the path to the IDMAP.
+ inline const std::string& IdmapPath() const {
+ return idmap_path_;
+ }
// Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
inline const std::string& OverlayApkPath() const {
return overlay_apk_path_;
}
- // Returns the mapping of target entry ID to overlay entry ID for the given target type.
- const IdmapEntry_header* GetEntryMapForType(uint8_t type_id) const;
+ // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
+ inline const std::string& TargetApkPath() const {
+ return target_apk_path_;
+ }
+
+ // Returns a mapping from target resource ids to overlay values.
+ inline const IdmapResMap GetTargetResourcesMap(
+ uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) const {
+ return IdmapResMap(data_header_, target_entries_, target_assigned_package_id,
+ overlay_ref_table);
+ }
+
+ // Returns a dynamic reference table for a loaded overlay package.
+ inline const OverlayDynamicRefTable GetOverlayDynamicRefTable(
+ uint8_t target_assigned_package_id) const {
+ return OverlayDynamicRefTable(data_header_, overlay_entries_, target_assigned_package_id);
+ }
+
+ // Returns whether the idmap file on disk has not been modified since the construction of this
+ // LoadedIdmap.
+ bool IsUpToDate() const;
protected:
// Exposed as protected so that tests can subclass and mock this class out.
LoadedIdmap() = default;
- const Idmap_header* header_ = nullptr;
+ const Idmap_header* header_;
+ const Idmap_data_header* data_header_;
+ const Idmap_target_entry* target_entries_;
+ const Idmap_overlay_entry* overlay_entries_;
+ const std::unique_ptr<ResStringPool> string_pool_;
+
+ const std::string idmap_path_;
std::string overlay_apk_path_;
- std::unordered_map<uint8_t, const IdmapEntry_header*> type_map_;
+ std::string target_apk_path_;
+ const time_t idmap_last_mod_time_;
private:
DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);
- explicit LoadedIdmap(const Idmap_header* header);
+ explicit LoadedIdmap(std::string&& idmap_path,
+ time_t last_mod_time,
+ 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);
+
+ friend OverlayStringPool;
};
} // namespace android
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 950f5413f550..89ff9f52125d 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -51,10 +51,6 @@ struct TypeSpec {
// and under which configurations it varies.
const ResTable_typeSpec* type_spec;
- // Pointer to the mmapped data where the IDMAP mappings for this type
- // exist. May be nullptr if no IDMAP exists.
- const IdmapEntry_header* idmap_entries;
-
// The number of types that follow this struct.
// There is a type for each configuration that entries are defined for.
size_t type_count;
@@ -73,6 +69,26 @@ struct TypeSpec {
}
};
+// Flags that change the behavior of loaded packages.
+// Keep in sync with f/b/android/content/res/ApkAssets.java
+using package_property_t = uint32_t;
+enum : package_property_t {
+ // The package contains framework resource values specified by the system.
+ // This allows some functions to filter out this package when computing
+ // what configurations/resources are available.
+ PROPERTY_SYSTEM = 1U << 0U,
+
+ // The package is a shared library or has a package id of 7f and is loaded as a shared library by
+ // force.
+ PROPERTY_DYNAMIC = 1U << 1U,
+
+ // The package has been loaded dynamically using a ResourcesProvider.
+ PROPERTY_LOADER = 1U << 2U,
+
+ // The package is a RRO.
+ PROPERTY_OVERLAY = 1U << 3U,
+};
+
// 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.
@@ -136,8 +152,7 @@ class LoadedPackage {
}
static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
- const LoadedIdmap* loaded_idmap, bool system,
- bool load_as_shared_library);
+ package_property_t property_flags);
~LoadedPackage();
@@ -174,17 +189,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 from an overlay ApkAssets.
- inline bool IsOverlay() const {
- return overlay_;
+ // Returns true if this package is a custom loader and should behave like an overlay.
+ inline bool IsCustomLoader() const {
+ 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
@@ -216,9 +240,6 @@ class LoadedPackage {
const TypeSpecPtr& ptr = type_specs_[i];
if (ptr != nullptr) {
uint8_t type_id = ptr->type_spec->id;
- if (ptr->idmap_entries != nullptr) {
- type_id = ptr->idmap_entries->target_type_id;
- }
f(ptr.get(), type_id - 1);
}
}
@@ -255,17 +276,17 @@ 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 overlay_ = false;
- bool defines_overlayable_ = false;
+ package_property_t property_flags_ = 0U;
ByteBucketArray<TypeSpecPtr> type_specs_;
ByteBucketArray<uint32_t> resource_ids_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
std::vector<const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>> overlayable_infos_;
+
+ // A map of overlayable name to actor
std::unordered_map<std::string, std::string> overlayable_map_;
};
@@ -281,8 +302,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);
+ 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();
@@ -290,7 +310,7 @@ class LoadedArsc {
// Returns the string pool where all string resource values
// (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
inline const ResStringPool* GetStringPool() const {
- return &global_string_pool_;
+ return global_string_pool_.get();
}
// Gets a pointer to the package with the specified package ID, or nullptr if no such package
@@ -302,20 +322,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 LoadTable(
+ const Chunk& chunk, const LoadedIdmap* loaded_idmap, package_property_t property_flags);
- ResStringPool global_string_pool_;
+ std::unique_ptr<ResStringPool> global_string_pool_ = util::make_unique<ResStringPool>();
std::vector<std::unique_ptr<const LoadedPackage>> packages_;
- bool system_ = false;
};
} // namespace android
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index fc635aaeb0d8..e351a46d633a 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -22,6 +22,7 @@
#include <androidfw/Asset.h>
#include <androidfw/LocaleData.h>
+#include <androidfw/StringPiece.h>
#include <utils/Errors.h>
#include <utils/String16.h>
#include <utils/Vector.h>
@@ -34,12 +35,13 @@
#include <android/configuration.h>
+#include <array>
#include <memory>
namespace android {
constexpr const static uint32_t kIdmapMagic = 0x504D4449u;
-constexpr const static uint32_t kIdmapCurrentVersion = 0x00000001u;
+constexpr const static uint32_t kIdmapCurrentVersion = 0x00000004u;
/**
* In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
@@ -492,7 +494,7 @@ class ResStringPool
public:
ResStringPool();
ResStringPool(const void* data, size_t size, bool copyData=false);
- ~ResStringPool();
+ virtual ~ResStringPool();
void setToEmpty();
status_t setTo(const void* data, size_t size, bool copyData=false);
@@ -506,10 +508,10 @@ public:
inline const char16_t* stringAt(const ResStringPool_ref& ref, size_t* outLen) const {
return stringAt(ref.index, outLen);
}
- const char16_t* stringAt(size_t idx, size_t* outLen) const;
+ virtual const char16_t* stringAt(size_t idx, size_t* outLen) const;
// Note: returns null if the string pool is not UTF8.
- const char* string8At(size_t idx, size_t* outLen) const;
+ virtual const char* string8At(size_t idx, size_t* outLen) const;
// Return string whether the pool is UTF8 or UTF16. Does not allow you
// to distinguish null.
@@ -520,9 +522,11 @@ public:
ssize_t indexOfString(const char16_t* str, size_t strLen) const;
- size_t size() const;
+ virtual size_t size() const;
size_t styleCount() const;
size_t bytes() const;
+ const void* data() const;
+
bool isSorted() const;
bool isUTF8() const;
@@ -810,7 +814,7 @@ public:
* The tree stores a clone of the specified DynamicRefTable, so any changes to the original
* DynamicRefTable will not affect this tree after instantiation.
**/
- explicit ResXMLTree(const DynamicRefTable* dynamicRefTable);
+ explicit ResXMLTree(std::shared_ptr<const DynamicRefTable> dynamicRefTable);
ResXMLTree();
~ResXMLTree();
@@ -825,7 +829,7 @@ private:
status_t validateNode(const ResXMLTree_node* node) const;
- std::unique_ptr<const DynamicRefTable> mDynamicRefTable;
+ std::shared_ptr<const DynamicRefTable> mDynamicRefTable;
status_t mError;
void* mOwnedData;
@@ -1582,6 +1586,50 @@ struct ResTable_map
Res_value value;
};
+
+// A ResTable_entry variant that either holds an unmanaged pointer to a constant ResTable_entry or
+// holds a ResTable_entry which is tied to the lifetime of the handle.
+class ResTable_entry_handle {
+ public:
+ ResTable_entry_handle() = default;
+
+ ResTable_entry_handle(const ResTable_entry_handle& handle) {
+ entry_ = handle.entry_;
+ }
+
+ ResTable_entry_handle(ResTable_entry_handle&& handle) noexcept {
+ entry_ = handle.entry_;
+ }
+
+ inline static ResTable_entry_handle managed(ResTable_entry* entry, void (*deleter)(void *)) {
+ return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, deleter));
+ }
+
+ inline static ResTable_entry_handle unmanaged(const ResTable_entry* entry) {
+ return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, [](auto /*p */){}));
+ }
+
+ inline ResTable_entry_handle& operator=(const ResTable_entry_handle& handle) noexcept {
+ entry_ = handle.entry_;
+ return *this;
+ }
+
+ inline ResTable_entry_handle& operator=(ResTable_entry_handle&& handle) noexcept {
+ entry_ = handle.entry_;
+ return *this;
+ }
+
+ inline const ResTable_entry* operator*() & {
+ return entry_.get();
+ }
+
+ private:
+ explicit ResTable_entry_handle(std::shared_ptr<const ResTable_entry> entry)
+ : entry_(std::move(entry)) { }
+
+ std::shared_ptr<const ResTable_entry> entry_;
+};
+
/**
* A package-id to package name mapping for any shared libraries used
* in this resource table. The package-id's encoded in this resource
@@ -1630,43 +1678,66 @@ struct ResTable_overlayable_header
*/
struct ResTable_overlayable_policy_header
{
- struct ResChunk_header header;
-
+ /**
+ * Flags for a bitmask for all possible overlayable policy options.
+ *
+ * Any changes to this set should also update aidl/android/os/OverlayablePolicy.aidl
+ */
enum PolicyFlags : uint32_t {
+ // Base
+ NONE = 0x00000000,
+
// Any overlay can overlay these resources.
- POLICY_PUBLIC = 0x00000001,
+ PUBLIC = 0x00000001,
// The overlay must reside of the system partition or must have existed on the system partition
// before an upgrade to overlay these resources.
- POLICY_SYSTEM_PARTITION = 0x00000002,
+ SYSTEM_PARTITION = 0x00000002,
// The overlay must reside of the vendor partition or must have existed on the vendor partition
// before an upgrade to overlay these resources.
- POLICY_VENDOR_PARTITION = 0x00000004,
+ VENDOR_PARTITION = 0x00000004,
// The overlay must reside of the product partition or must have existed on the product
// partition before an upgrade to overlay these resources.
- POLICY_PRODUCT_PARTITION = 0x00000008,
+ PRODUCT_PARTITION = 0x00000008,
- // The overlay must be signed with the same signature as the actor of the target resource,
- // which can be separate or the same as the target package with the resource.
- POLICY_SIGNATURE = 0x00000010,
+ // The overlay must be signed with the same signature as the package containing the target
+ // resource
+ SIGNATURE = 0x00000010,
// The overlay must reside of the odm partition or must have existed on the odm
// partition before an upgrade to overlay these resources.
- POLICY_ODM_PARTITION = 0x00000020,
+ ODM_PARTITION = 0x00000020,
// The overlay must reside of the oem partition or must have existed on the oem
// partition before an upgrade to overlay these resources.
- POLICY_OEM_PARTITION = 0x00000040,
+ OEM_PARTITION = 0x00000040,
+
+ // The overlay must be signed with the same signature as the actor declared for the target
+ // resource
+ ACTOR_SIGNATURE = 0x00000080,
};
- uint32_t policy_flags;
+
+ using PolicyBitmask = uint32_t;
+
+ struct ResChunk_header header;
+
+ PolicyFlags policy_flags;
// The number of ResTable_ref that follow this header.
uint32_t entry_count;
};
-struct alignas(uint32_t) Idmap_header {
+inline ResTable_overlayable_policy_header::PolicyFlags& operator |=(
+ ResTable_overlayable_policy_header::PolicyFlags& first,
+ ResTable_overlayable_policy_header::PolicyFlags second) {
+ first = static_cast<ResTable_overlayable_policy_header::PolicyFlags>(first | second);
+ return first;
+}
+
+#pragma pack(push, 1)
+struct Idmap_header {
// Always 0x504D4449 ('IDMP')
uint32_t magic;
@@ -1675,20 +1746,38 @@ struct alignas(uint32_t) Idmap_header {
uint32_t target_crc32;
uint32_t overlay_crc32;
+ uint32_t fulfilled_policies;
+ uint8_t enforce_overlayable;
+
uint8_t target_path[256];
uint8_t overlay_path[256];
- uint16_t target_package_id;
- uint16_t type_count;
-} __attribute__((packed));
+ uint32_t debug_info_size;
+ uint8_t debug_info[0];
-struct alignas(uint32_t) IdmapEntry_header {
- uint16_t target_type_id;
- uint16_t overlay_type_id;
- uint16_t entry_count;
- uint16_t entry_id_offset;
- uint32_t entries[0];
-} __attribute__((packed));
+ size_t Size() const;
+};
+
+struct Idmap_data_header {
+ uint8_t target_package_id;
+ uint8_t overlay_package_id;
+ uint32_t target_entry_count;
+ uint32_t overlay_entry_count;
+ uint32_t string_pool_index_offset;
+ uint32_t string_pool_length;
+};
+
+struct Idmap_target_entry {
+ uint32_t target_id;
+ uint8_t type;
+ uint32_t value;
+};
+
+struct Idmap_overlay_entry {
+ uint32_t overlay_id;
+ uint32_t target_id;
+};
+#pragma pack(pop)
class AssetManager2;
@@ -1706,6 +1795,7 @@ class DynamicRefTable
public:
DynamicRefTable();
DynamicRefTable(uint8_t packageId, bool appAsLib);
+ virtual ~DynamicRefTable() = default;
// Loads an unmapped reference table from the package.
status_t load(const ResTable_lib_header* const header);
@@ -1719,12 +1809,12 @@ public:
void addMapping(uint8_t buildPackageId, uint8_t runtimePackageId);
- // Creates a new clone of the reference table
- std::unique_ptr<DynamicRefTable> clone() const;
+ // Returns whether or not the value must be looked up.
+ bool requiresLookup(const Res_value* value) const;
// Performs the actual conversion of build-time resource ID to run-time
// resource ID.
- status_t lookupResourceId(uint32_t* resId) const;
+ virtual status_t lookupResourceId(uint32_t* resId) const;
status_t lookupResourceValue(Res_value* value) const;
inline const KeyedVector<String16, uint8_t>& entries() const {
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index aa1466fde778..9a3646b49db8 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -19,12 +19,19 @@
#include <cstdlib>
#include <memory>
+#include <sstream>
#include <vector>
#include "android-base/macros.h"
#include "androidfw/StringPiece.h"
+#ifdef __ANDROID__
+#define ANDROID_LOG(x) LOG(x)
+#else
+#define ANDROID_LOG(x) std::stringstream()
+#endif
+
namespace android {
namespace util {