diff options
Diffstat (limited to 'libs/androidfw/include')
-rw-r--r-- | libs/androidfw/include/androidfw/ApkAssets.h | 56 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/AssetManager.h | 33 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/AssetManager2.h | 112 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/Idmap.h | 76 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/LoadedArsc.h | 89 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/ResourceTypes.h | 50 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/ResourceUtils.h | 4 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/ZipFileRO.h | 6 |
8 files changed, 318 insertions, 108 deletions
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h index b7e66fb68be5..69702e314442 100644 --- a/libs/androidfw/include/androidfw/ApkAssets.h +++ b/libs/androidfw/include/androidfw/ApkAssets.h @@ -21,7 +21,7 @@ #include <string> #include "android-base/macros.h" -#include "ziparchive/zip_archive.h" +#include "android-base/unique_fd.h" #include "androidfw/Asset.h" #include "androidfw/LoadedArsc.h" @@ -29,41 +29,73 @@ namespace android { +class LoadedIdmap; + // Holds an APK. class ApkAssets { public: + // 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); + + // 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 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); + std::unique_ptr<Asset> Open(const std::string& path, Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const; bool ForEachFile(const std::string& path, const std::function<void(const StringPiece&, FileType)>& f) const; - inline const std::string& GetPath() const { return path_; } + inline const std::string& GetPath() const { + return path_; + } - inline const LoadedArsc* GetLoadedArsc() const { return loaded_arsc_.get(); } + // This is never nullptr. + inline const LoadedArsc* GetLoadedArsc() const { + return loaded_arsc_.get(); + } private: DISALLOW_COPY_AND_ASSIGN(ApkAssets); - static std::unique_ptr<const ApkAssets> LoadImpl(const std::string& path, bool system, - bool load_as_shared_library); + 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); - ApkAssets() = default; + // Creates an Asset from any file on the file system. + static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path); - struct ZipArchivePtrCloser { - void operator()(::ZipArchiveHandle handle) { ::CloseArchive(handle); } - }; + ApkAssets(void* unmanaged_handle, const std::string& path); - using ZipArchivePtr = - std::unique_ptr<typename std::remove_pointer<::ZipArchiveHandle>::type, ZipArchivePtrCloser>; + using ZipArchivePtr = std::unique_ptr<void, void(*)(void*)>; ZipArchivePtr zip_handle_; - std::string path_; + const std::string path_; std::unique_ptr<Asset> resources_asset_; + std::unique_ptr<Asset> idmap_asset_; std::unique_ptr<const LoadedArsc> loaded_arsc_; }; diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h index 0441b9d789e2..ecc5dc1ad331 100644 --- a/libs/androidfw/include/androidfw/AssetManager.h +++ b/libs/androidfw/include/androidfw/AssetManager.h @@ -92,6 +92,20 @@ public: bool addOverlayPath(const String8& path, int32_t* cookie); /* + * Add a new source for assets from an already open file descriptor. + * This does not give full AssetManager functionality for these assets, + * since the origin of the file is not known for purposes of sharing, + * overlay resolution, and other features. However it does allow you + * to do simple access to the contents of the given fd as an apk file. + * + * Returns "true" on success, "false" on failure. If 'cookie' is non-NULL, + * then on success, *cookie is set to the value corresponding to the + * newly-added asset source. + */ + bool addAssetFd(int fd, const String8& debugPathName, int32_t* cookie, + bool appAsLib=false, bool assume_ownership=true); + + /* * Convenience for adding the standard system assets. Uses the * ANDROID_ROOT environment variable to find them. */ @@ -195,24 +209,29 @@ public: uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize); private: + class SharedZip; + struct asset_path { - asset_path() : path(""), type(kFileTypeRegular), idmap(""), - isSystemOverlay(false), isSystemAsset(false) {} + asset_path() : path(""), rawFd(-1), type(kFileTypeRegular), idmap(""), + isSystemOverlay(false), isSystemAsset(false), assumeOwnership(false) {} String8 path; + int rawFd; FileType type; String8 idmap; bool isSystemOverlay; bool isSystemAsset; + bool assumeOwnership; + sp<SharedZip> zip; }; Asset* openNonAssetInPathLocked(const char* fileName, AccessMode mode, - const asset_path& path); + asset_path& path); String8 createPathNameLocked(const asset_path& path, const char* rootDir); String8 createZipSourceNameLocked(const String8& zipFileName, const String8& dirName, const String8& fileName); - ZipFileRO* getZipFileLocked(const asset_path& path); + ZipFileRO* getZipFileLocked(asset_path& path); Asset* openAssetFromFileLocked(const String8& fileName, AccessMode mode); Asset* openAssetFromZipLocked(const ZipFileRO* pZipFile, const ZipEntryRO entry, AccessMode mode, const String8& entryName); @@ -228,7 +247,7 @@ private: const ResTable* getResTable(bool required = true) const; void setLocaleLocked(const char* locale); void updateResourceParamsLocked() const; - bool appendPathToResTable(const asset_path& ap, bool appAsLib=false) const; + bool appendPathToResTable(asset_path& ap, bool appAsLib=false) const; Asset* openIdmapLocked(const struct asset_path& ap) const; @@ -238,6 +257,7 @@ private: class SharedZip : public RefBase { public: static sp<SharedZip> get(const String8& path, bool createIfNotPresent = true); + static sp<SharedZip> create(int fd, const String8& path); ZipFileRO* getZip(); @@ -257,6 +277,7 @@ private: private: SharedZip(const String8& path, time_t modWhen); + SharedZip(int fd, const String8& path); SharedZip(); // <-- not implemented String8 mPath; @@ -290,6 +311,8 @@ private: */ ZipFileRO* getZip(const String8& path); + const sp<SharedZip> getSharedZip(const String8& path); + Asset* getZipResourceTableAsset(const String8& path); Asset* setZipResourceTableAsset(const String8& path, Asset* asset); diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index d2bc6ee45576..b033137b4764 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -70,9 +70,8 @@ struct ResolvedBag { }; // AssetManager2 is the main entry point for accessing assets and resources. -// AssetManager2 provides caching of resources retrieved via the underlying -// ApkAssets. -class AssetManager2 : public ::AAssetManager { +// AssetManager2 provides caching of resources retrieved via the underlying ApkAssets. +class AssetManager2 { public: struct ResourceName { const char* package = nullptr; @@ -97,24 +96,29 @@ class AssetManager2 : public ::AAssetManager { // new resource IDs. bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true); - inline const std::vector<const ApkAssets*> GetApkAssets() const { return apk_assets_; } + inline const std::vector<const ApkAssets*> GetApkAssets() const { + return apk_assets_; + } // Returns the string pool for the given asset cookie. - // Use the string pool returned here with a valid Res_value object of - // type Res_value::TYPE_STRING. + // Use the string pool returned here with a valid Res_value object of type Res_value::TYPE_STRING. const ResStringPool* GetStringPoolForCookie(ApkAssetsCookie cookie) const; // Returns the DynamicRefTable for the given package ID. + // This may be nullptr if the APK represented by `cookie` has no resource table. const DynamicRefTable* GetDynamicRefTableForPackage(uint32_t package_id) const; // 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; // 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); - inline const ResTable_config& GetConfiguration() const { return configuration_; } + inline const ResTable_config& GetConfiguration() const { + return configuration_; + } // Returns all configurations for which there are resources defined. This includes resource // configurations in all the ApkAssets set for this AssetManager. @@ -206,7 +210,7 @@ class AssetManager2 : public ::AAssetManager { // are OR'd together with `in_out_flags`. // `in_out_config` is populated with the configuration for which the resolved value was defined. // `out_last_reference` is populated with the last reference ID before resolving to an actual - // value. + // value. This is only initialized if the passed in `in_out_value` is a reference. // Returns the cookie of the APK the resolved resource was defined in, or kInvalidCookie if // it was not found. ApkAssetsCookie ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value, @@ -228,26 +232,35 @@ class AssetManager2 : public ::AAssetManager { // Creates a new Theme from this AssetManager. std::unique_ptr<Theme> NewTheme(); + template <typename Func> + void ForEachPackage(Func func) { + for (const PackageGroup& package_group : package_groups_) { + func(package_group.packages_.front()->GetPackageName(), + package_group.dynamic_ref_table.mAssignedPackageId); + } + } + void DumpToLog() const; private: DISALLOW_COPY_AND_ASSIGN(AssetManager2); - // Finds the best entry for `resid` amongst all the ApkAssets. The entry can be a simple - // Res_value, or a complex map/bag type. + // 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 + // the ApkAssets in which the entry was found. // // `density_override` overrides the density of the current configuration when doing a search. // // When `stop_at_first_match` is true, the first match found is selected and the search // terminates. This is useful for methods that just look up the name of a resource and don't - // care about the value. In this case, the value of `out_flags` is incomplete and should not - // be used. + // care about the value. In this case, the value of `FindEntryResult::type_flags` is incomplete + // and should not be used. // - // `out_flags` stores the resulting bitmask of configuration axis with which the resource - // value varies. + // NOTE: FindEntry takes care of ensuring that structs within FindEntryResult have been properly + // bounds-checked. Callers of FindEntry are free to trust the data if this method succeeds. ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match, - LoadedArscEntry* out_entry, ResTable_config* out_selected_config, - uint32_t* out_flags); + FindEntryResult* out_entry); // Assigns package IDs to all shared library ApkAssets. // Should be called whenever the ApkAssets are changed. @@ -290,6 +303,8 @@ class Theme { friend class AssetManager2; public: + ~Theme(); + // Applies the style identified by `resid` to this theme. This can be called // multiple times with different styles. By default, any theme attributes that // are already defined before this call are not overridden. If `force` is set @@ -304,27 +319,31 @@ class Theme { void Clear(); - inline const AssetManager2* GetAssetManager() const { return asset_manager_; } + inline const AssetManager2* GetAssetManager() const { + return asset_manager_; + } - inline AssetManager2* GetAssetManager() { return asset_manager_; } + inline AssetManager2* GetAssetManager() { + return asset_manager_; + } // Returns a bit mask of configuration changes that will impact this // theme (and thus require completely reloading it). - inline uint32_t GetChangingConfigurations() const { return type_spec_flags_; } - - // Retrieve a value in the theme. If the theme defines this value, - // returns an asset cookie indicating which ApkAssets it came from - // and populates `out_value` with the value. If `out_flags` is non-null, - // populates it with a bitmask of the configuration axis the resource - // varies with. + inline uint32_t GetChangingConfigurations() const { + return type_spec_flags_; + } + + // Retrieve a value in the theme. If the theme defines this value, returns an asset cookie + // indicating which ApkAssets it came from and populates `out_value` with the value. + // `out_flags` is populated with a bitmask of the configuration axis with which the resource + // varies. // // If the attribute is not found, returns kInvalidCookie. // - // NOTE: This function does not do reference traversal. If you want - // to follow references to other resources to get the "real" value to - // use, you need to call ResolveReference() after this function. - ApkAssetsCookie GetAttribute(uint32_t resid, Res_value* out_value, - uint32_t* out_flags = nullptr) const; + // NOTE: This function does not do reference traversal. If you want to follow references to other + // resources to get the "real" value to use, you need to call ResolveReference() after this + // function. + ApkAssetsCookie GetAttribute(uint32_t resid, Res_value* out_value, uint32_t* out_flags) const; // This is like AssetManager2::ResolveReference(), but also takes // care of resolving attribute references to the theme. @@ -337,36 +356,21 @@ class Theme { DISALLOW_COPY_AND_ASSIGN(Theme); // Called by AssetManager2. - explicit inline Theme(AssetManager2* asset_manager) : asset_manager_(asset_manager) {} - - struct Entry { - ApkAssetsCookie cookie; - uint32_t type_spec_flags; - Res_value value; - }; - - struct Type { - // Use uint32_t for fewer cycles when loading from memory. - uint32_t entry_count; - uint32_t entry_capacity; - Entry entries[0]; - }; - - static constexpr const size_t kPackageCount = std::numeric_limits<uint8_t>::max() + 1; - static constexpr const size_t kTypeCount = std::numeric_limits<uint8_t>::max() + 1; - - struct Package { - // Each element of Type will be a dynamically sized object - // allocated to have the entries stored contiguously with the Type. - std::array<util::unique_cptr<Type>, kTypeCount> types; - }; + explicit Theme(AssetManager2* asset_manager); AssetManager2* asset_manager_; uint32_t type_spec_flags_ = 0u; + + // Defined in the cpp. + struct Package; + + constexpr static size_t kPackageCount = std::numeric_limits<uint8_t>::max() + 1; std::array<std::unique_ptr<Package>, kPackageCount> packages_; }; -inline const ResolvedBag::Entry* begin(const ResolvedBag* bag) { return bag->entries; } +inline const ResolvedBag::Entry* begin(const ResolvedBag* bag) { + return bag->entries; +} inline const ResolvedBag::Entry* end(const ResolvedBag* bag) { return bag->entries + bag->entry_count; diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h new file mode 100644 index 000000000000..fd02e6f63b74 --- /dev/null +++ b/libs/androidfw/include/androidfw/Idmap.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 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 IDMAP_H_ +#define IDMAP_H_ + +#include <memory> +#include <string> +#include <unordered_map> + +#include "android-base/macros.h" + +#include "androidfw/StringPiece.h" + +namespace android { + +struct Idmap_header; +struct IdmapEntry_header; + +// 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. +// 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); + + // Returns the package ID for which this overlay should apply. + uint8_t TargetPackageId() const; + + // 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; + + protected: + // Exposed as protected so that tests can subclass and mock this class out. + LoadedIdmap() = default; + + const Idmap_header* header_ = nullptr; + std::string overlay_apk_path_; + std::unordered_map<uint8_t, const IdmapEntry_header*> type_map_; + + private: + DISALLOW_COPY_AND_ASSIGN(LoadedIdmap); + + explicit LoadedIdmap(const Idmap_header* header); +}; + +} // namespace android + +#endif // IDMAP_H_ diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h index f30b158084eb..965e2dbd2fb2 100644 --- a/libs/androidfw/include/androidfw/LoadedArsc.h +++ b/libs/androidfw/include/androidfw/LoadedArsc.h @@ -25,6 +25,7 @@ #include "androidfw/ByteBucketArray.h" #include "androidfw/Chunk.h" +#include "androidfw/Idmap.h" #include "androidfw/ResourceTypes.h" #include "androidfw/Util.h" @@ -40,12 +41,18 @@ class DynamicPackageEntry { int package_id = 0; }; -struct LoadedArscEntry { +struct FindEntryResult { // A pointer to the resource table entry for this resource. // If the size of the entry is > sizeof(ResTable_entry), it can be cast to // a ResTable_map_entry and processed as a bag/map. const ResTable_entry* entry = nullptr; + // The configuration for which the resulting entry was defined. + const ResTable_config* config = nullptr; + + // Stores the resulting bitmask of configuration axis with which the resource value varies. + uint32_t type_flags = 0u; + // The dynamic package ID map for the package from which this resource came from. const DynamicRefTable* dynamic_ref_table = nullptr; @@ -62,28 +69,55 @@ struct TypeSpec; class LoadedArsc; class LoadedPackage { - friend class LoadedArsc; - public: + static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk, + const LoadedIdmap* loaded_idmap, bool system, + bool load_as_shared_library); + + ~LoadedPackage(); + bool FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config, - LoadedArscEntry* out_entry, ResTable_config* out_selected_config, - uint32_t* out_flags) const; + FindEntryResult* out_entry) const; + + // Finds the entry with the specified type name and entry name. The names are in UTF-16 because + // the underlying ResStringPool API expects this. For now this is acceptable, but since + // the default policy in AAPT2 is to build UTF-8 string pools, this needs to change. + // Returns a partial resource ID, with the package ID left as 0x00. The caller is responsible + // for patching the correct package ID to the resource ID. + uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const; // Returns the string pool where type names are stored. - inline const ResStringPool* GetTypeStringPool() const { return &type_string_pool_; } + inline const ResStringPool* GetTypeStringPool() const { + return &type_string_pool_; + } // Returns the string pool where the names of resource entries are stored. - inline const ResStringPool* GetKeyStringPool() const { return &key_string_pool_; } + inline const ResStringPool* GetKeyStringPool() const { + return &key_string_pool_; + } - inline const std::string& GetPackageName() const { return package_name_; } + inline const std::string& GetPackageName() const { + return package_name_; + } - inline int GetPackageId() const { return package_id_; } + inline int GetPackageId() const { + return package_id_; + } // Returns true if this package is dynamic (shared library) and needs to have an ID assigned. - inline bool IsDynamic() const { return dynamic_; } + inline bool IsDynamic() const { + return dynamic_; + } // Returns true if this package originates from a system provided resource. - inline bool IsSystem() const { return system_; } + inline bool IsSystem() const { + return system_; + } + + // Returns true if this package is from an overlay ApkAssets. + inline bool IsOverlay() const { + return overlay_; + } // Returns the map of package name to package ID used in this LoadedPackage. At runtime, a // package could have been assigned a different package ID than what this LoadedPackage was @@ -101,19 +135,13 @@ class LoadedPackage { // before being inserted into the set. This may cause some equivalent locales to de-dupe. void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const; - // Finds the entry with the specified type name and entry name. The names are in UTF-16 because - // the underlying ResStringPool API expects this. For now this is acceptable, but since - // the default policy in AAPT2 is to build UTF-8 string pools, this needs to change. - // Returns a partial resource ID, with the package ID left as 0x00. The caller is responsible - // for patching the correct package ID to the resource ID. - uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const; - private: DISALLOW_COPY_AND_ASSIGN(LoadedPackage); - static std::unique_ptr<LoadedPackage> Load(const Chunk& chunk); + LoadedPackage(); - LoadedPackage() = default; + bool FindEntry(const util::unique_cptr<TypeSpec>& type_spec_ptr, uint16_t entry_idx, + const ResTable_config& config, FindEntryResult* out_entry) const; ResStringPool type_string_pool_; ResStringPool key_string_pool_; @@ -122,6 +150,7 @@ class LoadedPackage { int type_id_offset_ = 0; bool dynamic_ = false; bool system_ = false; + bool overlay_ = false; ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_; std::vector<DynamicPackageEntry> dynamic_package_map_; @@ -137,27 +166,33 @@ class LoadedArsc { // 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(const void* data, size_t len, bool system = false, + static std::unique_ptr<const LoadedArsc> Load(const StringPiece& data, + const LoadedIdmap* loaded_idmap = nullptr, + bool system = false, bool load_as_shared_library = false); - ~LoadedArsc(); + // Create an empty LoadedArsc. This is used when an APK has no resources.arsc. + static std::unique_ptr<const LoadedArsc> CreateEmpty(); // 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_; } + inline const ResStringPool* GetStringPool() const { + return &global_string_pool_; + } // Finds the resource with ID `resid` with the best value for configuration `config`. // The parameter `out_entry` will be filled with the resulting resource entry. // The resource entry can be a simple entry (ResTable_entry) or a complex bag // (ResTable_entry_map). - bool FindEntry(uint32_t resid, const ResTable_config& config, LoadedArscEntry* out_entry, - ResTable_config* selected_config, uint32_t* out_flags) const; + bool FindEntry(uint32_t resid, const ResTable_config& config, FindEntryResult* out_entry) const; // Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist. const LoadedPackage* GetPackageForId(uint32_t resid) const; // Returns true if this is a system provided resource. - inline bool IsSystem() const { return system_; } + inline bool IsSystem() const { + return system_; + } // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc. inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const { @@ -168,7 +203,7 @@ class LoadedArsc { DISALLOW_COPY_AND_ASSIGN(LoadedArsc); LoadedArsc() = default; - bool LoadTable(const Chunk& chunk, bool load_as_shared_library); + bool LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library); ResStringPool global_string_pool_; std::vector<std::unique_ptr<const LoadedPackage>> packages_; diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 66c66c251d9b..20d017813cf7 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -38,6 +38,9 @@ namespace android { +constexpr const static uint32_t kIdmapMagic = 0x504D4449u; +constexpr const static uint32_t kIdmapCurrentVersion = 0x00000001u; + /** * In C++11, char16_t is defined as *at least* 16 bits. We do a lot of * casting on raw data and expect char16_t to be exactly 16 bits. @@ -543,15 +546,15 @@ private: */ class StringPoolRef { public: - StringPoolRef(); - StringPoolRef(const ResStringPool* pool, uint32_t index); + StringPoolRef() = default; + StringPoolRef(const ResStringPool* pool, uint32_t index); - const char* string8(size_t* outLen) const; - const char16_t* string16(size_t* outLen) const; + const char* string8(size_t* outLen) const; + const char16_t* string16(size_t* outLen) const; private: - const ResStringPool* mPool; - uint32_t mIndex; + const ResStringPool* mPool = nullptr; + uint32_t mIndex = 0u; }; /** ******************************************************************** @@ -1179,6 +1182,10 @@ struct ResTable_config // tried but could not compute a script. bool localeScriptWasComputed; + // The value of BCP 47 Unicode extension for key 'nu' (numbering system). + // Varies in length from 3 to 8 chars. Zero-filled value. + char localeNumberingSystem[8]; + void copyFromDeviceNoSwap(const ResTable_config& o); void copyFromDtoH(const ResTable_config& o); @@ -1256,9 +1263,9 @@ struct ResTable_config // variants, it will be a modified bcp47 tag: b+en+Latn+US. void appendDirLocale(String8& str) const; - // Sets the values of language, region, script and variant to the - // well formed BCP-47 locale contained in |in|. The input locale is - // assumed to be valid and no validation is performed. + // Sets the values of language, region, script, variant and numbering + // system to the well formed BCP 47 locale contained in |in|. + // The input locale is assumed to be valid and no validation is performed. void setBcp47Locale(const char* in); inline void clearLocale() { @@ -1266,6 +1273,7 @@ struct ResTable_config localeScriptWasComputed = false; memset(localeScript, 0, sizeof(localeScript)); memset(localeVariant, 0, sizeof(localeVariant)); + memset(localeNumberingSystem, 0, sizeof(localeNumberingSystem)); } inline void computeScript() { @@ -1583,6 +1591,30 @@ struct ResTable_lib_entry uint16_t packageName[128]; }; +struct alignas(uint32_t) Idmap_header { + // Always 0x504D4449 ('IDMP') + uint32_t magic; + + uint32_t version; + + uint32_t target_crc32; + uint32_t overlay_crc32; + + uint8_t target_path[256]; + uint8_t overlay_path[256]; + + uint16_t target_package_id; + uint16_t type_count; +} __attribute__((packed)); + +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)); + class AssetManager2; /** diff --git a/libs/androidfw/include/androidfw/ResourceUtils.h b/libs/androidfw/include/androidfw/ResourceUtils.h index 6bf7c2438797..c2eae855bb7b 100644 --- a/libs/androidfw/include/androidfw/ResourceUtils.h +++ b/libs/androidfw/include/androidfw/ResourceUtils.h @@ -40,7 +40,9 @@ inline uint8_t get_type_id(uint32_t resid) { return static_cast<uint8_t>((resid >> 16) & 0x000000ffu); } -inline uint16_t get_entry_id(uint32_t resid) { return static_cast<uint16_t>(resid & 0x0000ffffu); } +inline uint16_t get_entry_id(uint32_t resid) { + return static_cast<uint16_t>(resid & 0x0000ffffu); +} inline bool is_internal_resid(uint32_t resid) { return (resid & 0xffff0000u) != 0 && (resid & 0x00ff0000u) == 0; diff --git a/libs/androidfw/include/androidfw/ZipFileRO.h b/libs/androidfw/include/androidfw/ZipFileRO.h index 768034287afa..03154d04def1 100644 --- a/libs/androidfw/include/androidfw/ZipFileRO.h +++ b/libs/androidfw/include/androidfw/ZipFileRO.h @@ -80,6 +80,12 @@ public: static ZipFileRO* open(const char* zipFileName); /* + * Open an archive from an already open file descriptor. + */ + static ZipFileRO* openFd(int fd, const char* debugFileName, + bool assume_ownership = true); + + /* * Find an entry, by name. Returns the entry identifier, or NULL if * not found. */ |