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