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