Home | History | Annotate | Download | only in idmap2
      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 
     89   inline uint32_t GetMagic() const {
     90     return magic_;
     91   }
     92 
     93   inline uint32_t GetVersion() const {
     94     return version_;
     95   }
     96 
     97   inline uint32_t GetTargetCrc() const {
     98     return target_crc_;
     99   }
    100 
    101   inline uint32_t GetOverlayCrc() const {
    102     return overlay_crc_;
    103   }
    104 
    105   inline StringPiece GetTargetPath() const {
    106     return StringPiece(target_path_);
    107   }
    108 
    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:
    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 
    141     inline PackageId GetTargetPackageId() const {
    142       return target_package_id_;
    143     }
    144 
    145     inline uint16_t GetTypeCount() const {
    146       return type_count_;
    147     }
    148 
    149     void accept(Visitor* v) const;
    150 
    151    private:
    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 
    166     inline TypeId GetTargetTypeId() const {
    167       return target_type_id_;
    168     }
    169 
    170     inline TypeId GetOverlayTypeId() const {
    171       return overlay_type_id_;
    172     }
    173 
    174     inline uint16_t GetEntryCount() const {
    175       return entries_.size();
    176     }
    177 
    178     inline uint16_t GetEntryOffset() const {
    179       return entry_offset_;
    180     }
    181 
    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:
    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 
    203   inline const std::unique_ptr<const Header>& GetHeader() const {
    204     return header_;
    205   }
    206 
    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:
    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 
    242   inline const std::unique_ptr<const IdmapHeader>& GetHeader() const {
    243     return header_;
    244   }
    245 
    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:
    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:
    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