• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 /*
18  * # idmap file format (current version)
19  *
20  * idmap                      := header constraints_count constraint* data*
21  * header                     := magic version target_crc overlay_crc fulfilled_policies
22  *                               enforce_overlayable target_path overlay_path overlay_name
23  *                               debug_info
24  * constraints                := constraint_type constraint_value
25  * data                       := data_header target_entries target_inline_entries
26                                  target_inline_entry_value* config* overlay_entries string_pool
27  * data_header                := target_entry_count target_inline_entry_count
28                                  target_inline_entry_value_count config_count overlay_entry_count
29  *                               string_pool_index
30  * target_entries             := target_id* overlay_id*
31  * target_inline_entries      := target_id* target_inline_value_header*
32  * target_inline_value_header := start_value_index value_count
33  * target_inline_entry_value  := config_index Res_value::size padding(1) Res_value::type
34  *                               Res_value::value
35  * config                     := target_id Res_value::size padding(1) Res_value::type
36  *                               Res_value::value
37  * overlay_entries            := overlay_id* target_id*
38  *
39  * debug_info                       := string
40  * enforce_overlayable              := <uint32_t>
41  * fulfilled_policies               := <uint32_t>
42  * magic                            := <uint32_t>
43  * overlay_crc                      := <uint32_t>
44  * overlay_entry_count              := <uint32_t>
45  * overlay_id                       := <uint32_t>
46  * overlay_package_id               := <uint8_t>
47  * overlay_name                     := string
48  * overlay_path                     := string
49  * padding(n)                       := <uint8_t>[n]
50  * Res_value::size                  := <uint16_t>
51  * Res_value::type                  := <uint8_t>
52  * Res_value::value                 := <uint32_t>
53  * string                           := <uint32_t> <uint8_t>+ padding(n)
54  * string_pool                      := string
55  * string_pool_index                := <uint32_t>
56  * string_pool_length               := <uint32_t>
57  * target_crc                       := <uint32_t>
58  * target_entry_count               := <uint32_t>
59  * target_inline_entry_count        := <uint32_t>
60  * target_inline_entry_value_count  := <uint32_t>
61  * config_count                     := <uint32_t>
62  * config_index                     := <uint32_t>
63  * start_value_index                := <uint32_t>
64  * value_count                      := <uint32_t>
65  * target_id                        := <uint32_t>
66  * target_package_id                := <uint8_t>
67  * target_path                      := string
68  * value_type                       := <uint8_t>
69  * value_data                       := <uint32_t>
70  * version                          := <uint32_t>
71  * constraints_count                := <uint32_t>
72  * constraint_type                  := <uint32_t>
73  * constraint_value                 := <uint32_t>
74  */
75 
76 #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
77 #define IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
78 
79 #include <istream>
80 #include <memory>
81 #include <string>
82 #include <string_view>
83 #include <unordered_set>
84 #include <vector>
85 
86 #include "android-base/macros.h"
87 #include "androidfw/ResourceTypes.h"
88 #include "androidfw/StringPiece.h"
89 #include "androidfw/ConfigDescription.h"
90 #include "idmap2/ResourceContainer.h"
91 #include "idmap2/ResourceMapping.h"
92 
93 namespace android::idmap2 {
94 
95 class Idmap;
96 class Visitor;
97 
98 // magic number: all idmap files start with this
99 static constexpr const uint32_t kIdmapMagic = android::kIdmapMagic;
100 
101 // current version of the idmap binary format; must be incremented when the format is changed
102 static constexpr const uint32_t kIdmapCurrentVersion = android::kIdmapCurrentVersion;
103 
104 class IdmapHeader {
105  public:
106   static std::unique_ptr<const IdmapHeader> FromBinaryStream(std::istream& stream);
107 
GetMagic()108   inline uint32_t GetMagic() const {
109     return magic_;
110   }
111 
GetVersion()112   inline uint32_t GetVersion() const {
113     return version_;
114   }
115 
GetTargetCrc()116   inline uint32_t GetTargetCrc() const {
117     return target_crc_;
118   }
119 
GetOverlayCrc()120   inline uint32_t GetOverlayCrc() const {
121     return overlay_crc_;
122   }
123 
GetFulfilledPolicies()124   inline uint32_t GetFulfilledPolicies() const {
125     return fulfilled_policies_;
126   }
127 
GetEnforceOverlayable()128   bool GetEnforceOverlayable() const {
129     return enforce_overlayable_;
130   }
131 
GetTargetPath()132   const std::string& GetTargetPath() const {
133     return target_path_;
134   }
135 
GetOverlayPath()136   const std::string& GetOverlayPath() const {
137     return overlay_path_;
138   }
139 
GetOverlayName()140   const std::string& GetOverlayName() const {
141     return overlay_name_;
142   }
143 
GetDebugInfo()144   const std::string& GetDebugInfo() const {
145     return debug_info_;
146   }
147 
148   // Invariant: anytime the idmap data encoding is changed, the idmap version
149   // field *must* be incremented. Because of this, we know that if the idmap
150   // header is up-to-date the entire file is up-to-date.
151   Result<Unit> IsUpToDate(const TargetResourceContainer& target,
152                           const OverlayResourceContainer& overlay, const std::string& overlay_name,
153                           PolicyBitmask fulfilled_policies, bool enforce_overlayable) const;
154 
155   Result<Unit> IsUpToDate(const std::string& target_path, const std::string& overlay_path,
156                           const std::string& overlay_name, uint32_t target_crc,
157                           uint32_t overlay_crc, PolicyBitmask fulfilled_policies,
158                           bool enforce_overlayable) const;
159 
160   void accept(Visitor* v) const;
161 
162  private:
163   IdmapHeader() = default;
164 
165   uint32_t magic_;
166   uint32_t version_;
167   uint32_t target_crc_;
168   uint32_t overlay_crc_;
169   uint32_t fulfilled_policies_;
170   bool enforce_overlayable_;
171   std::string target_path_;
172   std::string overlay_path_;
173   std::string overlay_name_;
174   std::string debug_info_;
175 
176   friend Idmap;
177   DISALLOW_COPY_AND_ASSIGN(IdmapHeader);
178 };
179 
180 struct IdmapConstraint {
181   // Constraint type can be android::kOverlayConstraintTypeDisplayId or
182   // android::kOverlayConstraintTypeDeviceId
183   uint32_t constraint_type;
184   uint32_t constraint_value;
185 
186   bool operator==(const IdmapConstraint&) const = default;
187 };
188 
189 struct IdmapConstraints {
190   static std::unique_ptr<const IdmapConstraints> FromBinaryStream(std::istream& stream);
191 
192   struct Hash {
operatorIdmapConstraints::Hash193     static std::size_t operator()(const IdmapConstraint& constraint) {
194       return std::hash<int>()(constraint.constraint_type) * 31
195               + std::hash<int>()(constraint.constraint_value);
196     }
197   };
198 
199   bool operator == (const IdmapConstraints& constraints) const = default;
200 
201   void accept(Visitor* v) const;
202 
203   std::unordered_set<IdmapConstraint, Hash> constraints;
204 };
205 
206 class IdmapData {
207  public:
208   class Header {
209    public:
210     static std::unique_ptr<const Header> FromBinaryStream(std::istream& stream);
211 
GetTargetEntryCount()212     [[nodiscard]] inline uint32_t GetTargetEntryCount() const {
213       return target_entry_count;
214     }
215 
GetTargetInlineEntryCount()216     [[nodiscard]] inline uint32_t GetTargetInlineEntryCount() const {
217       return target_entry_inline_count;
218     }
219 
GetTargetInlineEntryValueCount()220     [[nodiscard]] inline uint32_t GetTargetInlineEntryValueCount() const {
221       return target_entry_inline_value_count;
222     }
223 
GetConfigCount()224     [[nodiscard]] inline uint32_t GetConfigCount() const {
225       return config_count;
226     }
227 
GetOverlayEntryCount()228     [[nodiscard]] inline uint32_t GetOverlayEntryCount() const {
229       return overlay_entry_count;
230     }
231 
GetStringPoolIndexOffset()232     [[nodiscard]] inline uint32_t GetStringPoolIndexOffset() const {
233       return string_pool_index_offset;
234     }
235 
236     void accept(Visitor* v) const;
237 
238    private:
239     uint32_t target_entry_count;
240     uint32_t target_entry_inline_count;
241     uint32_t target_entry_inline_value_count;
242     uint32_t config_count;
243     uint32_t overlay_entry_count;
244     uint32_t string_pool_index_offset;
245     Header() = default;
246 
247     friend Idmap;
248     friend IdmapData;
249     DISALLOW_COPY_AND_ASSIGN(Header);
250   };
251 
252   struct TargetEntry {
253     ResourceId target_id;
254     ResourceId overlay_id;
255   };
256 
257   struct TargetInlineEntry {
258     ResourceId target_id;
259     std::map<ConfigDescription, TargetValue> values;
260   };
261 
262   struct OverlayEntry {
263     ResourceId overlay_id;
264     ResourceId target_id;
265   };
266 
267   static std::unique_ptr<const IdmapData> FromBinaryStream(std::istream& stream);
268 
269   static Result<std::unique_ptr<const IdmapData>> FromResourceMapping(
270       const ResourceMapping& resource_mapping);
271 
GetHeader()272   const std::unique_ptr<const Header>& GetHeader() const {
273     return header_;
274   }
275 
GetTargetEntries()276   const std::vector<TargetEntry>& GetTargetEntries() const {
277     return target_entries_;
278   }
279 
GetTargetInlineEntries()280   const std::vector<TargetInlineEntry>& GetTargetInlineEntries() const {
281     return target_inline_entries_;
282   }
283 
GetOverlayEntries()284   [[nodiscard]] const std::vector<OverlayEntry>& GetOverlayEntries() const {
285     return overlay_entries_;
286   }
287 
GetStringPoolData()288   [[nodiscard]] const std::string& GetStringPoolData() const {
289     return string_pool_data_;
290   }
291 
292   void accept(Visitor* v) const;
293 
294  private:
295   IdmapData() = default;
296 
297   std::unique_ptr<const Header> header_;
298   std::vector<TargetEntry> target_entries_;
299   std::vector<TargetInlineEntry> target_inline_entries_;
300   std::vector<OverlayEntry> overlay_entries_;
301   std::string string_pool_data_;
302 
303   friend Idmap;
304   DISALLOW_COPY_AND_ASSIGN(IdmapData);
305 };
306 
307 class Idmap {
308  public:
309   static std::string CanonicalIdmapPathFor(std::string_view absolute_dir,
310                                            std::string_view absolute_apk_path);
311 
312   static Result<std::unique_ptr<const Idmap>> FromBinaryStream(std::istream& stream);
313 
314   // In the current version of idmap, the first package in each resources.arsc
315   // file is used; change this in the next version of idmap to use a named
316   // package instead; also update FromApkAssets to take additional parameters:
317   // the target and overlay package names
318   static Result<std::unique_ptr<const Idmap>> FromContainers(
319       const TargetResourceContainer& target, const OverlayResourceContainer& overlay,
320       const std::string& overlay_name, const PolicyBitmask& fulfilled_policies,
321       bool enforce_overlayable, std::unique_ptr<const IdmapConstraints>&& constraints);
322 
GetHeader()323   const std::unique_ptr<const IdmapHeader>& GetHeader() const {
324     return header_;
325   }
326 
GetConstraints()327   const std::unique_ptr<const IdmapConstraints>& GetConstraints() const {
328     return constraints_;
329   }
330 
GetData()331   const std::vector<std::unique_ptr<const IdmapData>>& GetData() const {
332     return data_;
333   }
334 
335   void accept(Visitor* v) const;
336 
337  private:
338   Idmap() = default;
339 
340   std::unique_ptr<const IdmapHeader> header_;
341   std::unique_ptr<const IdmapConstraints> constraints_;
342   std::vector<std::unique_ptr<const IdmapData>> data_;
343 
344   DISALLOW_COPY_AND_ASSIGN(Idmap);
345 };
346 
347 class Visitor {
348  public:
349   virtual ~Visitor() = default;
350   virtual void visit(const Idmap& idmap) = 0;
351   virtual void visit(const IdmapHeader& header) = 0;
352   virtual void visit(const IdmapConstraints& constraints) = 0;
353   virtual void visit(const IdmapData& data) = 0;
354   virtual void visit(const IdmapData::Header& header) = 0;
355 };
356 
CalculatePadding(size_t data_length)357 inline size_t CalculatePadding(size_t data_length) {
358   return (4 - (data_length % 4)) % 4;
359 }
360 
361 }  // namespace android::idmap2
362 
363 #endif  // IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
364