• 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* 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