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