• 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 target_path overlay_path
22  * data              := data_header data_block*
23  * data_header       := target_package_id types_count
24  * data_block        := target_type overlay_type entry_count entry_offset entry*
25  * overlay_path      := string
26  * target_path       := string
27  * entry             := <uint32_t>
28  * entry_count       := <uint16_t>
29  * entry_offset      := <uint16_t>
30  * magic             := <uint32_t>
31  * overlay_crc       := <uint32_t>
32  * overlay_type      := <uint16_t>
33  * string            := <uint8_t>[256]
34  * target_crc        := <uint32_t>
35  * target_package_id := <uint16_t>
36  * target_type       := <uint16_t>
37  * types_count       := <uint16_t>
38  * version           := <uint32_t>
39  *
40  *
41  * # idmap file format changelog
42  * ## v1
43  * - Identical to idmap v1.
44  */
45 
46 #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
47 #define IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
48 
49 #include <iostream>
50 #include <memory>
51 #include <string>
52 #include <vector>
53 
54 #include "android-base/macros.h"
55 #include "androidfw/ApkAssets.h"
56 #include "androidfw/ResourceTypes.h"
57 #include "androidfw/StringPiece.h"
58 #include "idmap2/Policies.h"
59 
60 namespace android::idmap2 {
61 
62 class Idmap;
63 class Visitor;
64 
65 // use typedefs to let the compiler warn us about implicit casts
66 typedef uint32_t ResourceId;  // 0xpptteeee
67 typedef uint8_t PackageId;    // pp in 0xpptteeee
68 typedef uint8_t TypeId;       // tt in 0xpptteeee
69 typedef uint16_t EntryId;     // eeee in 0xpptteeee
70 
71 static constexpr const ResourceId kPadding = 0xffffffffu;
72 
73 static constexpr const EntryId kNoEntry = 0xffffu;
74 
75 // magic number: all idmap files start with this
76 static constexpr const uint32_t kIdmapMagic = android::kIdmapMagic;
77 
78 // current version of the idmap binary format; must be incremented when the format is changed
79 static constexpr const uint32_t kIdmapCurrentVersion = android::kIdmapCurrentVersion;
80 
81 // strings in the idmap are encoded char arrays of length 'kIdmapStringLength' (including mandatory
82 // terminating null)
83 static constexpr const size_t kIdmapStringLength = 256;
84 
85 class IdmapHeader {
86  public:
87   static std::unique_ptr<const IdmapHeader> FromBinaryStream(std::istream& stream);
88 
GetMagic()89   inline uint32_t GetMagic() const {
90     return magic_;
91   }
92 
GetVersion()93   inline uint32_t GetVersion() const {
94     return version_;
95   }
96 
GetTargetCrc()97   inline uint32_t GetTargetCrc() const {
98     return target_crc_;
99   }
100 
GetOverlayCrc()101   inline uint32_t GetOverlayCrc() const {
102     return overlay_crc_;
103   }
104 
GetTargetPath()105   inline StringPiece GetTargetPath() const {
106     return StringPiece(target_path_);
107   }
108 
GetOverlayPath()109   inline StringPiece GetOverlayPath() const {
110     return StringPiece(overlay_path_);
111   }
112 
113   // Invariant: anytime the idmap data encoding is changed, the idmap version
114   // field *must* be incremented. Because of this, we know that if the idmap
115   // header is up-to-date the entire file is up-to-date.
116   Result<Unit> IsUpToDate() const;
117 
118   void accept(Visitor* v) const;
119 
120  private:
IdmapHeader()121   IdmapHeader() {
122   }
123 
124   uint32_t magic_;
125   uint32_t version_;
126   uint32_t target_crc_;
127   uint32_t overlay_crc_;
128   char target_path_[kIdmapStringLength];
129   char overlay_path_[kIdmapStringLength];
130 
131   friend Idmap;
132   DISALLOW_COPY_AND_ASSIGN(IdmapHeader);
133 };
134 
135 class IdmapData {
136  public:
137   class Header {
138    public:
139     static std::unique_ptr<const Header> FromBinaryStream(std::istream& stream);
140 
GetTargetPackageId()141     inline PackageId GetTargetPackageId() const {
142       return target_package_id_;
143     }
144 
GetTypeCount()145     inline uint16_t GetTypeCount() const {
146       return type_count_;
147     }
148 
149     void accept(Visitor* v) const;
150 
151    private:
Header()152     Header() {
153     }
154 
155     PackageId target_package_id_;
156     uint16_t type_count_;
157 
158     friend Idmap;
159     DISALLOW_COPY_AND_ASSIGN(Header);
160   };
161 
162   class TypeEntry {
163    public:
164     static std::unique_ptr<const TypeEntry> FromBinaryStream(std::istream& stream);
165 
GetTargetTypeId()166     inline TypeId GetTargetTypeId() const {
167       return target_type_id_;
168     }
169 
GetOverlayTypeId()170     inline TypeId GetOverlayTypeId() const {
171       return overlay_type_id_;
172     }
173 
GetEntryCount()174     inline uint16_t GetEntryCount() const {
175       return entries_.size();
176     }
177 
GetEntryOffset()178     inline uint16_t GetEntryOffset() const {
179       return entry_offset_;
180     }
181 
GetEntry(size_t i)182     inline EntryId GetEntry(size_t i) const {
183       return i < entries_.size() ? entries_[i] : 0xffffu;
184     }
185 
186     void accept(Visitor* v) const;
187 
188    private:
TypeEntry()189     TypeEntry() {
190     }
191 
192     TypeId target_type_id_;
193     TypeId overlay_type_id_;
194     uint16_t entry_offset_;
195     std::vector<EntryId> entries_;
196 
197     friend Idmap;
198     DISALLOW_COPY_AND_ASSIGN(TypeEntry);
199   };
200 
201   static std::unique_ptr<const IdmapData> FromBinaryStream(std::istream& stream);
202 
GetHeader()203   inline const std::unique_ptr<const Header>& GetHeader() const {
204     return header_;
205   }
206 
GetTypeEntries()207   inline const std::vector<std::unique_ptr<const TypeEntry>>& GetTypeEntries() const {
208     return type_entries_;
209   }
210 
211   void accept(Visitor* v) const;
212 
213  private:
IdmapData()214   IdmapData() {
215   }
216 
217   std::unique_ptr<const Header> header_;
218   std::vector<std::unique_ptr<const TypeEntry>> type_entries_;
219 
220   friend Idmap;
221   DISALLOW_COPY_AND_ASSIGN(IdmapData);
222 };
223 
224 class Idmap {
225  public:
226   static std::string CanonicalIdmapPathFor(const std::string& absolute_dir,
227                                            const std::string& absolute_apk_path);
228 
229   static Result<std::unique_ptr<const Idmap>> FromBinaryStream(std::istream& stream);
230 
231   // In the current version of idmap, the first package in each resources.arsc
232   // file is used; change this in the next version of idmap to use a named
233   // package instead; also update FromApkAssets to take additional parameters:
234   // the target and overlay package names
235   static Result<std::unique_ptr<const Idmap>> FromApkAssets(const std::string& target_apk_path,
236                                                             const ApkAssets& target_apk_assets,
237                                                             const std::string& overlay_apk_path,
238                                                             const ApkAssets& overlay_apk_assets,
239                                                             const PolicyBitmask& fulfilled_policies,
240                                                             bool enforce_overlayable);
241 
GetHeader()242   inline const std::unique_ptr<const IdmapHeader>& GetHeader() const {
243     return header_;
244   }
245 
GetData()246   inline const std::vector<std::unique_ptr<const IdmapData>>& GetData() const {
247     return data_;
248   }
249 
250   void accept(Visitor* v) const;
251 
252  private:
Idmap()253   Idmap() {
254   }
255 
256   std::unique_ptr<const IdmapHeader> header_;
257   std::vector<std::unique_ptr<const IdmapData>> data_;
258 
259   DISALLOW_COPY_AND_ASSIGN(Idmap);
260 };
261 
262 class Visitor {
263  public:
~Visitor()264   virtual ~Visitor() {
265   }
266   virtual void visit(const Idmap& idmap) = 0;
267   virtual void visit(const IdmapHeader& header) = 0;
268   virtual void visit(const IdmapData& data) = 0;
269   virtual void visit(const IdmapData::Header& header) = 0;
270   virtual void visit(const IdmapData::TypeEntry& type_entry) = 0;
271 };
272 
273 }  // namespace android::idmap2
274 
275 #endif  // IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
276