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