• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef IDMAP_H_
18 #define IDMAP_H_
19 
20 #include <memory>
21 #include <string>
22 #include <unordered_map>
23 #include <variant>
24 
25 #include "android-base/macros.h"
26 #include "androidfw/ConfigDescription.h"
27 #include "androidfw/StringPiece.h"
28 #include "androidfw/ResourceTypes.h"
29 #include "utils/ByteOrder.h"
30 
31 namespace android {
32 
33 class LoadedIdmap;
34 class IdmapResMap;
35 struct Idmap_header;
36 struct Idmap_data_header;
37 struct Idmap_target_entry;
38 struct Idmap_target_entry_inline;
39 struct Idmap_target_entry_inline_value;
40 struct Idmap_overlay_entry;
41 
42 // A string pool for overlay apk assets. The string pool holds the strings of the overlay resources
43 // table and additionally allows for loading strings from the idmap string pool. The idmap string
44 // pool strings are offset after the end of the overlay resource table string pool entries so
45 // queries for strings defined inline in the idmap do not conflict with queries for overlay
46 // resource table strings.
47 class OverlayStringPool : public ResStringPool {
48  public:
49   virtual ~OverlayStringPool();
50   base::expected<StringPiece16, NullOrIOError> stringAt(size_t idx) const override;
51   base::expected<StringPiece, NullOrIOError> string8At(size_t idx) const override;
52   size_t size() const override;
53 
54   explicit OverlayStringPool(const LoadedIdmap* loaded_idmap);
55  private:
56     const Idmap_data_header* data_header_;
57     const ResStringPool* idmap_string_pool_;
58 };
59 
60 // A dynamic reference table for loaded overlay packages that rewrites the resource id of overlay
61 // resources to the resource id of corresponding target resources.
62 class OverlayDynamicRefTable : public DynamicRefTable {
63  public:
64   ~OverlayDynamicRefTable() override = default;
65   status_t lookupResourceId(uint32_t* resId) const override;
66 
67  private:
68   explicit OverlayDynamicRefTable(const Idmap_data_header* data_header,
69                                   const Idmap_overlay_entry* entries,
70                                   uint8_t target_assigned_package_id);
71 
72   // Rewrites a compile-time overlay resource id to the runtime resource id of corresponding target
73   // resource.
74   virtual status_t lookupResourceIdNoRewrite(uint32_t* resId) const;
75 
76   const Idmap_data_header* data_header_;
77   const Idmap_overlay_entry* entries_;
78   const int8_t target_assigned_package_id_;
79 
80   friend LoadedIdmap;
81   friend IdmapResMap;
82 };
83 
84 // A mapping of target resource ids to a values or resource ids that should overlay the target.
85 class IdmapResMap {
86  public:
87   // Represents the result of a idmap lookup. The result can be one of three possibilities:
88   // 1) The result is a resource id which represents the overlay resource that should act as an
89   //    alias of the target resource.
90   // 2) The result is a table entry which overlays the type and value of the target resource.
91   // 3) The result is neither and the target resource is not overlaid.
92   class Result {
93    public:
94     Result() = default;
Result(uint32_t value)95     explicit Result(uint32_t value) : data_(value) {};
Result(std::map<ConfigDescription,Res_value> value)96     explicit Result(std::map<ConfigDescription, Res_value> value) : data_(std::move(value)) {
97     }
98 
99     // Returns `true` if the resource is overlaid.
100     explicit operator bool() const {
101       return std::get_if<std::monostate>(&data_) == nullptr;
102     }
103 
IsResourceId()104     bool IsResourceId() const {
105       return std::get_if<uint32_t>(&data_) != nullptr;
106     }
107 
GetResourceId()108     uint32_t GetResourceId() const {
109       return std::get<uint32_t>(data_);
110     }
111 
IsInlineValue()112     bool IsInlineValue() const {
113       return std::get_if<2>(&data_) != nullptr;
114     }
115 
GetInlineValue()116     const std::map<ConfigDescription, Res_value>& GetInlineValue() const {
117       return std::get<2>(data_);
118     }
119 
120    private:
121       std::variant<std::monostate, uint32_t,
122           std::map<ConfigDescription, Res_value> > data_;
123   };
124 
125   // Looks up the value that overlays the target resource id.
126   Result Lookup(uint32_t target_res_id) const;
127 
GetOverlayDynamicRefTable()128   inline const OverlayDynamicRefTable* GetOverlayDynamicRefTable() const {
129     return overlay_ref_table_;
130   }
131 
132  private:
133   explicit IdmapResMap(const Idmap_data_header* data_header,
134                        const Idmap_target_entry* entries,
135                        const Idmap_target_entry_inline* inline_entries,
136                        const Idmap_target_entry_inline_value* inline_entry_values,
137                        const ConfigDescription* configs,
138                        uint8_t target_assigned_package_id,
139                        const OverlayDynamicRefTable* overlay_ref_table);
140 
141   const Idmap_data_header* data_header_;
142   const Idmap_target_entry* entries_;
143   const Idmap_target_entry_inline* inline_entries_;
144   const Idmap_target_entry_inline_value* inline_entry_values_;
145   const ConfigDescription* configurations_;
146   const uint8_t target_assigned_package_id_;
147   const OverlayDynamicRefTable* overlay_ref_table_;
148 
149   friend LoadedIdmap;
150 };
151 
152 // Represents a loaded/parsed IDMAP for a Runtime Resource Overlay (RRO).
153 // An RRO and its target APK have different resource IDs assigned to their resources.
154 // An IDMAP is a generated mapping between the resource IDs of the RRO and the target APK.
155 // A LoadedIdmap can be set alongside the overlay's LoadedArsc to allow the overlay ApkAssets to
156 // masquerade as the target ApkAssets resources.
157 class LoadedIdmap {
158  public:
159   // Loads an IDMAP from a chunk of memory. Returns nullptr if the IDMAP data was malformed.
160   static std::unique_ptr<LoadedIdmap> Load(StringPiece idmap_path, StringPiece idmap_data);
161 
162   // Returns the path to the IDMAP.
IdmapPath()163   std::string_view IdmapPath() const {
164     return idmap_path_;
165   }
166 
167   // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
OverlayApkPath()168   std::string_view OverlayApkPath() const {
169     return overlay_apk_path_;
170   }
171 
172   // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
TargetApkPath()173   std::string_view TargetApkPath() const {
174     return target_apk_path_;
175   }
176 
177   // Returns a mapping from target resource ids to overlay values.
GetTargetResourcesMap(uint8_t target_assigned_package_id,const OverlayDynamicRefTable * overlay_ref_table)178   const IdmapResMap GetTargetResourcesMap(uint8_t target_assigned_package_id,
179                                           const OverlayDynamicRefTable* overlay_ref_table) const {
180     return IdmapResMap(data_header_, target_entries_, target_inline_entries_, inline_entry_values_,
181                        configurations_, target_assigned_package_id, overlay_ref_table);
182   }
183 
184   // Returns a dynamic reference table for a loaded overlay package.
GetOverlayDynamicRefTable(uint8_t target_assigned_package_id)185   const OverlayDynamicRefTable GetOverlayDynamicRefTable(uint8_t target_assigned_package_id) const {
186     return OverlayDynamicRefTable(data_header_, overlay_entries_, target_assigned_package_id);
187   }
188 
189   // Returns whether the idmap file on disk has not been modified since the construction of this
190   // LoadedIdmap.
191   bool IsUpToDate() const;
192 
193  protected:
194   // Exposed as protected so that tests can subclass and mock this class out.
195   LoadedIdmap() = default;
196 
197   const Idmap_header* header_;
198   const Idmap_data_header* data_header_;
199   const Idmap_target_entry* target_entries_;
200   const Idmap_target_entry_inline* target_inline_entries_;
201   const Idmap_target_entry_inline_value* inline_entry_values_;
202   const ConfigDescription* configurations_;
203   const Idmap_overlay_entry* overlay_entries_;
204   const std::unique_ptr<ResStringPool> string_pool_;
205 
206   std::string idmap_path_;
207   std::string_view overlay_apk_path_;
208   std::string_view target_apk_path_;
209   time_t idmap_last_mod_time_;
210 
211  private:
212   DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);
213 
214   explicit LoadedIdmap(std::string&& idmap_path,
215                        const Idmap_header* header,
216                        const Idmap_data_header* data_header,
217                        const Idmap_target_entry* target_entries,
218                        const Idmap_target_entry_inline* target_inline_entries,
219                        const Idmap_target_entry_inline_value* inline_entry_values_,
220                        const ConfigDescription* configs,
221                        const Idmap_overlay_entry* overlay_entries,
222                        std::unique_ptr<ResStringPool>&& string_pool,
223                        std::string_view overlay_apk_path,
224                        std::string_view target_apk_path);
225 
226   friend OverlayStringPool;
227 };
228 
229 }  // namespace android
230 
231 #endif  // IDMAP_H_
232