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