summaryrefslogtreecommitdiff
path: root/libs/androidfw/include
diff options
context:
space:
mode:
author Adam Lesinski <adamlesinski@google.com> 2017-01-27 22:30:22 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-01-27 22:30:24 +0000
commit90572a4ab8ac393c57e896be3c608e634866ed38 (patch)
tree524319d2edfd555f3b637bd332f1a494bf4c1114 /libs/androidfw/include
parent904aca762c7e1c1ac5c005134ca802dba0ceed5b (diff)
parentda431a22da38f9c4085b5d71ed9a9c6122c6a5a6 (diff)
Merge "libandroidfw: Add new support for shared libraries"
Diffstat (limited to 'libs/androidfw/include')
-rw-r--r--libs/androidfw/include/androidfw/ApkAssets.h3
-rw-r--r--libs/androidfw/include/androidfw/AssetManager2.h36
-rw-r--r--libs/androidfw/include/androidfw/Chunk.h113
-rw-r--r--libs/androidfw/include/androidfw/LoadedArsc.h104
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h12
-rw-r--r--libs/androidfw/include/androidfw/Util.h8
6 files changed, 244 insertions, 32 deletions
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index a3d67f04eb90..9d4fd29d30d7 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -32,6 +32,7 @@ namespace android {
class ApkAssets {
public:
static std::unique_ptr<ApkAssets> Load(const std::string& path);
+ static std::unique_ptr<ApkAssets> LoadAsSharedLibrary(const std::string& path);
std::unique_ptr<Asset> Open(const std::string& path,
Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const;
@@ -43,6 +44,8 @@ class ApkAssets {
private:
DISALLOW_COPY_AND_ASSIGN(ApkAssets);
+ static std::unique_ptr<ApkAssets> LoadImpl(const std::string& path, bool load_as_shared_library);
+
ApkAssets() = default;
struct ZipArchivePtrCloser {
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 66d5034463a5..86553390dadf 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -19,6 +19,7 @@
#include "android-base/macros.h"
+#include <array>
#include <limits>
#include <unordered_map>
@@ -95,18 +96,21 @@ class AssetManager2 : public ::AAssetManager {
// new resource IDs.
bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true);
- const std::vector<const ApkAssets*> GetApkAssets() const;
+ 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.
const ResStringPool* GetStringPoolForCookie(ApkAssetsCookie cookie) const;
+ // Returns the DynamicRefTable for the given package ID.
+ const DynamicRefTable* GetDynamicRefTableForPackage(uint32_t package_id) 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);
- const ResTable_config& GetConfiguration() const;
+ inline const ResTable_config& GetConfiguration() const { return configuration_; }
// Searches the set of APKs loaded by this AssetManager and opens the first one found located
// in the assets/ directory.
@@ -173,6 +177,8 @@ class AssetManager2 : public ::AAssetManager {
// Creates a new Theme from this AssetManager.
std::unique_ptr<Theme> NewTheme();
+ void DumpToLog() const;
+
private:
DISALLOW_COPY_AND_ASSIGN(AssetManager2);
@@ -189,9 +195,13 @@ class AssetManager2 : public ::AAssetManager {
// `out_flags` stores the resulting bitmask of configuration axis with which the resource
// value varies.
ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
- LoadedArsc::Entry* out_entry, ResTable_config* out_selected_config,
+ LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
uint32_t* out_flags);
+ // Assigns package IDs to all shared library ApkAssets.
+ // Should be called whenever the ApkAssets are changed.
+ void BuildDynamicRefTable();
+
// Purge all resources that are cached and vary by the configuration axis denoted by the
// bitmask `diff`.
void InvalidateCaches(uint32_t diff);
@@ -200,6 +210,22 @@ class AssetManager2 : public ::AAssetManager {
// have a longer lifetime.
std::vector<const ApkAssets*> apk_assets_;
+ struct PackageGroup {
+ std::vector<const LoadedPackage*> packages_;
+ std::vector<ApkAssetsCookie> cookies_;
+ 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
+ // immutable ApkAssets class.
+ std::vector<PackageGroup> package_groups_;
+
+ // An array mapping package ID to index into package_groups. This keeps the lookup fast
+ // without taking too much memory.
+ std::array<uint8_t, std::numeric_limits<uint8_t>::max() + 1> package_ids_;
+
// The current configuration set for this AssetManager. When this changes, cached resources
// may need to be purged.
ResTable_config configuration_;
@@ -279,12 +305,12 @@ class Theme {
struct Package {
// Each element of Type will be a dynamically sized object
// allocated to have the entries stored contiguously with the Type.
- util::unique_cptr<Type> types[kTypeCount];
+ std::array<util::unique_cptr<Type>, kTypeCount> types;
};
AssetManager2* asset_manager_;
uint32_t type_spec_flags_ = 0u;
- std::unique_ptr<Package> packages_[kPackageCount];
+ std::array<std::unique_ptr<Package>, kPackageCount> packages_;
};
inline const ResolvedBag::Entry* begin(const ResolvedBag* bag) { return bag->entries; }
diff --git a/libs/androidfw/include/androidfw/Chunk.h b/libs/androidfw/include/androidfw/Chunk.h
new file mode 100644
index 000000000000..e87b94087450
--- /dev/null
+++ b/libs/androidfw/include/androidfw/Chunk.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2016 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 CHUNK_H_
+#define CHUNK_H_
+
+#include "android-base/logging.h"
+#include "android-base/macros.h"
+#include "utils/ByteOrder.h"
+
+#ifdef _WIN32
+#ifdef ERROR
+#undef ERROR
+#endif
+#endif
+
+#include "androidfw/ResourceTypes.h"
+
+namespace android {
+
+// Helpful wrapper around a ResChunk_header that provides getter methods
+// that handle endianness conversions and provide access to the data portion
+// of the chunk.
+class Chunk {
+ public:
+ explicit Chunk(const ResChunk_header* chunk) : device_chunk_(chunk) {}
+
+ // Returns the type of the chunk. Caller need not worry about endianness.
+ inline int type() const { return dtohs(device_chunk_->type); }
+
+ // Returns the size of the entire chunk. This can be useful for skipping
+ // over the entire chunk. Caller need not worry about endianness.
+ inline size_t size() const { return dtohl(device_chunk_->size); }
+
+ // Returns the size of the header. Caller need not worry about endianness.
+ inline size_t header_size() const { return dtohs(device_chunk_->headerSize); }
+
+ template <typename T>
+ inline const T* header() const {
+ if (header_size() >= sizeof(T)) {
+ return reinterpret_cast<const T*>(device_chunk_);
+ }
+ return nullptr;
+ }
+
+ inline const void* data_ptr() const {
+ return reinterpret_cast<const uint8_t*>(device_chunk_) + header_size();
+ }
+
+ inline size_t data_size() const { return size() - header_size(); }
+
+ private:
+ const ResChunk_header* device_chunk_;
+};
+
+// Provides a Java style iterator over an array of ResChunk_header's.
+// Validation is performed while iterating.
+// The caller should check if there was an error during chunk validation
+// by calling HadError() and GetLastError() to get the reason for failure.
+// Example:
+//
+// ChunkIterator iter(data_ptr, data_len);
+// while (iter.HasNext()) {
+// const Chunk chunk = iter.Next();
+// ...
+// }
+//
+// if (iter.HadError()) {
+// LOG(ERROR) << iter.GetLastError();
+// }
+//
+class ChunkIterator {
+ public:
+ ChunkIterator(const void* data, size_t len)
+ : next_chunk_(reinterpret_cast<const ResChunk_header*>(data)),
+ len_(len),
+ last_error_(nullptr) {
+ CHECK(next_chunk_ != nullptr) << "data can't be nullptr";
+ VerifyNextChunk();
+ }
+
+ Chunk Next();
+ inline bool HasNext() const { return !HadError() && len_ != 0; };
+ inline bool HadError() const { return last_error_ != nullptr; }
+ inline std::string GetLastError() const { return last_error_; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChunkIterator);
+
+ // Returns false if there was an error.
+ bool VerifyNextChunk();
+
+ const ResChunk_header* next_chunk_;
+ size_t len_;
+ const char* last_error_;
+};
+
+} // namespace android
+
+#endif /* CHUNK_H_ */
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index e2e56c88ee1d..8362008eccc7 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -22,12 +22,82 @@
#include "android-base/macros.h"
+#include "androidfw/ByteBucketArray.h"
+#include "androidfw/Chunk.h"
#include "androidfw/ResourceTypes.h"
+#include "androidfw/Util.h"
namespace android {
-class Chunk;
-class LoadedPackage;
+class DynamicPackageEntry {
+ public:
+ DynamicPackageEntry() = default;
+ DynamicPackageEntry(std::string&& package_name, int package_id)
+ : package_name(std::move(package_name)), package_id(package_id) {}
+
+ std::string package_name;
+ int package_id = 0;
+};
+
+struct LoadedArscEntry {
+ // 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 dynamic package ID map for the package from which this resource came from.
+ const DynamicRefTable* dynamic_ref_table = nullptr;
+
+ // The string pool reference to the type's name. This uses a different string pool than
+ // the global string pool, but this is hidden from the caller.
+ StringPoolRef type_string_ref;
+
+ // The string pool reference to the entry's name. This uses a different string pool than
+ // the global string pool, but this is hidden from the caller.
+ StringPoolRef entry_string_ref;
+};
+
+struct TypeSpec;
+class LoadedArsc;
+
+class LoadedPackage {
+ friend class LoadedArsc;
+
+ public:
+ 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;
+
+ inline const ResStringPool* GetTypeStringPool() const { return &type_string_pool_; }
+
+ inline const ResStringPool* GetKeyStringPool() const { return &key_string_pool_; }
+
+ inline const std::string& GetPackageName() const { return package_name_; }
+
+ inline int GetPackageId() const { return package_id_; }
+
+ inline bool IsDynamic() const { return dynamic_; }
+
+ inline const std::vector<DynamicPackageEntry>& GetDynamicPackageMap() const {
+ return dynamic_package_map_;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
+
+ static std::unique_ptr<LoadedPackage> Load(const Chunk& chunk);
+
+ LoadedPackage() = default;
+
+ ResStringPool type_string_pool_;
+ ResStringPool key_string_pool_;
+ std::string package_name_;
+ int package_id_ = -1;
+ bool dynamic_ = false;
+
+ ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
+ std::vector<DynamicPackageEntry> dynamic_package_map_;
+};
// Read-only view into a resource table. This class validates all data
// when loading, including offsets and lengths.
@@ -35,7 +105,8 @@ class LoadedArsc {
public:
// Load the resource table from memory. The data's lifetime must out-live the
// object returned from this method.
- static std::unique_ptr<LoadedArsc> Load(const void* data, size_t len);
+ static std::unique_ptr<LoadedArsc> Load(const void* data, size_t len,
+ bool load_as_shared_library = false);
~LoadedArsc();
@@ -43,39 +114,28 @@ class LoadedArsc {
// (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
inline const ResStringPool* GetStringPool() const { return &global_string_pool_; }
- struct Entry {
- // 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 string pool reference to the type's name. This uses a different string pool than
- // the global string pool, but this is hidden from the caller.
- StringPoolRef type_string_ref;
-
- // The string pool reference to the entry's name. This uses a different string pool than
- // the global string pool, but this is hidden from the caller.
- StringPoolRef entry_string_ref;
- };
-
// 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, Entry* out_entry,
+ bool FindEntry(uint32_t resid, const ResTable_config& config, LoadedArscEntry* out_entry,
ResTable_config* selected_config, uint32_t* out_flags) const;
// Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
- const std::string* GetPackageNameForId(uint32_t resid) const;
+ const LoadedPackage* GetPackageForId(uint32_t resid) const;
+
+ inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
+ return packages_;
+ }
private:
DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
LoadedArsc() = default;
- bool LoadTable(const Chunk& chunk);
+ bool LoadTable(const Chunk& chunk, bool load_as_shared_library);
ResStringPool global_string_pool_;
- std::vector<std::unique_ptr<LoadedPackage>> packages_;
+ std::vector<std::unique_ptr<const LoadedPackage>> packages_;
};
} // namespace android
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 86ab123ff064..56c22e60e30b 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1538,6 +1538,8 @@ struct ResTable_lib_entry
uint16_t packageName[128];
};
+class AssetManager2;
+
/**
* Holds the shared library ID table. Shared libraries are assigned package IDs at
* build time, but they may be loaded in a different order, so we need to maintain
@@ -1548,7 +1550,9 @@ struct ResTable_lib_entry
*/
class DynamicRefTable
{
+ friend class AssetManager2;
public:
+ DynamicRefTable() = default;
DynamicRefTable(uint8_t packageId, bool appAsLib);
// Loads an unmapped reference table from the package.
@@ -1563,18 +1567,18 @@ public:
// Performs the actual conversion of build-time resource ID to run-time
// resource ID.
- inline status_t lookupResourceId(uint32_t* resId) const;
- inline status_t lookupResourceValue(Res_value* value) const;
+ status_t lookupResourceId(uint32_t* resId) const;
+ status_t lookupResourceValue(Res_value* value) const;
inline const KeyedVector<String16, uint8_t>& entries() const {
return mEntries;
}
private:
- const uint8_t mAssignedPackageId;
+ uint8_t mAssignedPackageId = 0;
uint8_t mLookupTable[256];
KeyedVector<String16, uint8_t> mEntries;
- bool mAppAsLib;
+ bool mAppAsLib = false;
};
bool U16StringToInt(const char16_t* s, size_t len, Res_value* outValue);
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index 5266d09e84e3..fd96730d2398 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -102,6 +102,10 @@ class unique_cptr {
pointer ptr_;
};
+inline uint32_t fix_package_id(uint32_t resid, uint8_t package_id) {
+ return resid | (static_cast<uint32_t>(package_id) << 24);
+}
+
inline uint8_t get_package_id(uint32_t resid) {
return static_cast<uint8_t>((resid >> 24) & 0x000000ffu);
}
@@ -113,7 +117,7 @@ inline uint8_t get_type_id(uint32_t resid) {
inline uint16_t get_entry_id(uint32_t resid) { return static_cast<uint16_t>(resid & 0x0000ffffu); }
-inline bool is_internal_id(uint32_t resid) {
+inline bool is_internal_resid(uint32_t resid) {
return (resid & 0xffff0000u) != 0 && (resid & 0x00ff0000u) == 0;
}
@@ -121,6 +125,8 @@ inline bool is_valid_resid(uint32_t resid) {
return (resid & 0x00ff0000u) != 0 && (resid & 0xff000000u) != 0;
}
+void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out);
+
} // namespace util
} // namespace android