17ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski/*
27ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Copyright (C) 2016 The Android Open Source Project
37ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *
47ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
57ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * you may not use this file except in compliance with the License.
67ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * You may obtain a copy of the License at
77ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *
87ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
97ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *
107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Unless required by applicable law or agreed to in writing, software
117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * See the License for the specific language governing permissions and
147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * limitations under the License.
157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski */
167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#ifndef LOADEDARSC_H_
187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#define LOADEDARSC_H_
197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include <memory>
210c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski#include <set>
227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include <vector>
237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "android-base/macros.h"
257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
26da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski#include "androidfw/ByteBucketArray.h"
27da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski#include "androidfw/Chunk.h"
287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "androidfw/ResourceTypes.h"
29da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski#include "androidfw/Util.h"
307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskinamespace android {
327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
33da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskiclass DynamicPackageEntry {
34da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski public:
35da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  DynamicPackageEntry() = default;
36da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  DynamicPackageEntry(std::string&& package_name, int package_id)
37da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      : package_name(std::move(package_name)), package_id(package_id) {}
38da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
39da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  std::string package_name;
40da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  int package_id = 0;
41da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski};
42da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
43da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskistruct LoadedArscEntry {
44da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // A pointer to the resource table entry for this resource.
45da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
46da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // a ResTable_map_entry and processed as a bag/map.
47da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const ResTable_entry* entry = nullptr;
48da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
49da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // The dynamic package ID map for the package from which this resource came from.
50da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const DynamicRefTable* dynamic_ref_table = nullptr;
51da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
52da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // The string pool reference to the type's name. This uses a different string pool than
53da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // the global string pool, but this is hidden from the caller.
54da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  StringPoolRef type_string_ref;
55da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
56da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // The string pool reference to the entry's name. This uses a different string pool than
57da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // the global string pool, but this is hidden from the caller.
58da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  StringPoolRef entry_string_ref;
59da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski};
60da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
61da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskistruct TypeSpec;
62da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskiclass LoadedArsc;
63da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
64da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskiclass LoadedPackage {
65da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  friend class LoadedArsc;
66da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
67da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski public:
68da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  bool FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
69da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski                 LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
70da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski                 uint32_t* out_flags) const;
71da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
720c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Returns the string pool where type names are stored.
73da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  inline const ResStringPool* GetTypeStringPool() const { return &type_string_pool_; }
74da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
750c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Returns the string pool where the names of resource entries are stored.
76da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  inline const ResStringPool* GetKeyStringPool() const { return &key_string_pool_; }
77da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
78da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  inline const std::string& GetPackageName() const { return package_name_; }
79da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
80da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  inline int GetPackageId() const { return package_id_; }
81da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
820c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Returns true if this package is dynamic (shared library) and needs to have an ID assigned.
83da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  inline bool IsDynamic() const { return dynamic_; }
84da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
850c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Returns true if this package originates from a system provided resource.
860c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  inline bool IsSystem() const { return system_; }
870c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
880c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Returns the map of package name to package ID used in this LoadedPackage. At runtime, a
890c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // package could have been assigned a different package ID than what this LoadedPackage was
900c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // compiled with. AssetManager rewrites the package IDs so that they are compatible at runtime.
91da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  inline const std::vector<DynamicPackageEntry>& GetDynamicPackageMap() const {
92da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    return dynamic_package_map_;
93da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
94da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
950c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Populates a set of ResTable_config structs, possibly excluding configurations defined for
960c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // the mipmap type.
970c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  void CollectConfigurations(bool exclude_mipmap, std::set<ResTable_config>* out_configs) const;
980c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
990c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Populates a set of strings representing locales.
1000c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // If `canonicalize` is set to true, each locale is transformed into its canonical format
1010c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // before being inserted into the set. This may cause some equivalent locales to de-dupe.
1020c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const;
1030c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
104929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  // Finds the entry with the specified type name and entry name. The names are in UTF-16 because
105929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  // the underlying ResStringPool API expects this. For now this is acceptable, but since
106929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  // the default policy in AAPT2 is to build UTF-8 string pools, this needs to change.
107929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  // Returns a partial resource ID, with the package ID left as 0x00. The caller is responsible
108929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  // for patching the correct package ID to the resource ID.
109929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const;
110929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
111da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski private:
112da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
113da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
114da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  static std::unique_ptr<LoadedPackage> Load(const Chunk& chunk);
115da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
116da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  LoadedPackage() = default;
117da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
118da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  ResStringPool type_string_pool_;
119da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  ResStringPool key_string_pool_;
120da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  std::string package_name_;
121da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  int package_id_ = -1;
122c6aada9c5789b2777b19c522d3cd5052bbe784a4Adam Lesinski  int type_id_offset_ = 0;
1230c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  bool dynamic_ = false;
1240c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  bool system_ = false;
125da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
126da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
127da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  std::vector<DynamicPackageEntry> dynamic_package_map_;
128da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski};
1297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// Read-only view into a resource table. This class validates all data
1317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// when loading, including offsets and lengths.
1327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiclass LoadedArsc {
1337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski public:
1340c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Load a resource table from memory pointed to by `data` of size `len`.
1350c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // The lifetime of `data` must out-live the LoadedArsc returned from this method.
1360c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // If `system` is set to true, the LoadedArsc is considered as a system provided resource.
1370c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // If `load_as_shared_library` is set to true, the application package (0x7f) is treated
1380c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // as a shared library (0x00). When loaded into an AssetManager, the package will be assigned an
1390c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // ID.
1400c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  static std::unique_ptr<const LoadedArsc> Load(const void* data, size_t len, bool system = false,
1410c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                                                bool load_as_shared_library = false);
1427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ~LoadedArsc();
1447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Returns the string pool where all string resource values
1467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
1477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  inline const ResStringPool* GetStringPool() const { return &global_string_pool_; }
1487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Finds the resource with ID `resid` with the best value for configuration `config`.
1507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // The parameter `out_entry` will be filled with the resulting resource entry.
1517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // The resource entry can be a simple entry (ResTable_entry) or a complex bag
1527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // (ResTable_entry_map).
153da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  bool FindEntry(uint32_t resid, const ResTable_config& config, LoadedArscEntry* out_entry,
1547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                 ResTable_config* selected_config, uint32_t* out_flags) const;
1557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
157da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const LoadedPackage* GetPackageForId(uint32_t resid) const;
158da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
1590c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Returns true if this is a system provided resource.
1600c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  inline bool IsSystem() const { return system_; }
1610c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
1620c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
163da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
164da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    return packages_;
165da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
1667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski private:
1687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
1697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  LoadedArsc() = default;
171da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  bool LoadTable(const Chunk& chunk, bool load_as_shared_library);
1727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResStringPool global_string_pool_;
174da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  std::vector<std::unique_ptr<const LoadedPackage>> packages_;
1750c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  bool system_ = false;
1767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski};
1777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}  // namespace android
1797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#endif /* LOADEDARSC_H_ */
181