1 /* 2 * Copyright (C) 2016 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 #ifndef APKASSETS_H_ 18 #define APKASSETS_H_ 19 20 #include <memory> 21 #include <string> 22 23 #include "android-base/macros.h" 24 #include "android-base/unique_fd.h" 25 26 #include "androidfw/Asset.h" 27 #include "androidfw/Idmap.h" 28 #include "androidfw/LoadedArsc.h" 29 #include "androidfw/misc.h" 30 31 struct ZipArchive; 32 typedef ZipArchive* ZipArchiveHandle; 33 34 namespace android { 35 36 class LoadedIdmap; 37 38 // Interface for retrieving assets provided by an ApkAssets. 39 class AssetsProvider { 40 public: 41 virtual ~AssetsProvider() = default; 42 43 // Opens a file for reading. 44 std::unique_ptr<Asset> Open(const std::string& path, 45 Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM, 46 bool* file_exists = nullptr) const { 47 return OpenInternal(path, mode, file_exists); 48 } 49 50 // Iterate over all files and directories provided by the zip. The order of iteration is stable. ForEachFile(const std::string &,const std::function<void (const StringPiece &,FileType)> &)51 virtual bool ForEachFile(const std::string& /* path */, 52 const std::function<void(const StringPiece&, FileType)>& /* f */) const { 53 return true; 54 } 55 56 protected: 57 AssetsProvider() = default; 58 59 virtual std::unique_ptr<Asset> OpenInternal(const std::string& path, 60 Asset::AccessMode mode, 61 bool* file_exists) const = 0; 62 63 private: 64 DISALLOW_COPY_AND_ASSIGN(AssetsProvider); 65 }; 66 67 class ZipAssetsProvider; 68 69 // Holds an APK. 70 class ApkAssets { 71 public: 72 // This means the data extends to the end of the file. 73 static constexpr off64_t kUnknownLength = -1; 74 75 // Creates an ApkAssets. 76 // If `system` is true, the package is marked as a system package, and allows some functions to 77 // filter out this package when computing what configurations/resources are available. 78 static std::unique_ptr<const ApkAssets> Load( 79 const std::string& path, package_property_t flags = 0U, 80 std::unique_ptr<const AssetsProvider> override_asset = nullptr); 81 82 // Creates an ApkAssets from the given file descriptor, and takes ownership of the file 83 // descriptor. The `friendly_name` is some name that will be used to identify the source of 84 // this ApkAssets in log messages and other debug scenarios. 85 // If `length` equals kUnknownLength, offset must equal 0; otherwise, the apk data will be read 86 // using the `offset` into the file descriptor and will be `length` bytes long. 87 static std::unique_ptr<const ApkAssets> LoadFromFd( 88 base::unique_fd fd, const std::string& friendly_name, package_property_t flags = 0U, 89 std::unique_ptr<const AssetsProvider> override_asset = nullptr, off64_t offset = 0, 90 off64_t length = kUnknownLength); 91 92 // Creates an ApkAssets from the given path which points to a resources.arsc. 93 static std::unique_ptr<const ApkAssets> LoadTable( 94 const std::string& path, package_property_t flags = 0U, 95 std::unique_ptr<const AssetsProvider> override_asset = nullptr); 96 97 // Creates an ApkAssets from the given file descriptor which points to an resources.arsc, and 98 // takes ownership of the file descriptor. 99 // If `length` equals kUnknownLength, offset must equal 0; otherwise, the .arsc data will be read 100 // using the `offset` into the file descriptor and will be `length` bytes long. 101 static std::unique_ptr<const ApkAssets> LoadTableFromFd( 102 base::unique_fd fd, const std::string& friendly_name, package_property_t flags = 0U, 103 std::unique_ptr<const AssetsProvider> override_asset = nullptr, off64_t offset = 0, 104 off64_t length = kUnknownLength); 105 106 // Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay 107 // data. 108 static std::unique_ptr<const ApkAssets> LoadOverlay(const std::string& idmap_path, 109 package_property_t flags = 0U); 110 111 // Creates an ApkAssets from the directory path. File-based resources are read within the 112 // directory as if the directory is an APK. 113 static std::unique_ptr<const ApkAssets> LoadFromDir( 114 const std::string& path, package_property_t flags = 0U, 115 std::unique_ptr<const AssetsProvider> override_asset = nullptr); 116 117 // Creates a totally empty ApkAssets with no resources table and no file entries. 118 static std::unique_ptr<const ApkAssets> LoadEmpty( 119 package_property_t flags = 0U, 120 std::unique_ptr<const AssetsProvider> override_asset = nullptr); 121 GetPath()122 const std::string& GetPath() const { 123 return path_; 124 } 125 GetAssetsProvider()126 const AssetsProvider* GetAssetsProvider() const { 127 return assets_provider_.get(); 128 } 129 130 // This is never nullptr. GetLoadedArsc()131 const LoadedArsc* GetLoadedArsc() const { 132 return loaded_arsc_.get(); 133 } 134 GetLoadedIdmap()135 const LoadedIdmap* GetLoadedIdmap() const { 136 return loaded_idmap_.get(); 137 } 138 IsLoader()139 bool IsLoader() const { 140 return (property_flags_ & PROPERTY_LOADER) != 0; 141 } 142 IsOverlay()143 bool IsOverlay() const { 144 return loaded_idmap_ != nullptr; 145 } 146 147 // Returns whether the resources.arsc is allocated in RAM (not mmapped). IsTableAllocated()148 bool IsTableAllocated() const { 149 return resources_asset_ && resources_asset_->isAllocated(); 150 } 151 152 bool IsUpToDate() const; 153 154 // Creates an Asset from a file on disk. 155 static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path); 156 157 // Creates an Asset from a file descriptor. 158 // 159 // The asset takes ownership of the file descriptor. If `length` equals kUnknownLength, offset 160 // must equal 0; otherwise, the asset data will be read using the `offset` into the file 161 // descriptor and will be `length` bytes long. 162 static std::unique_ptr<Asset> CreateAssetFromFd(base::unique_fd fd, 163 const char* path, 164 off64_t offset = 0, 165 off64_t length = kUnknownLength); 166 private: 167 DISALLOW_COPY_AND_ASSIGN(ApkAssets); 168 169 static std::unique_ptr<const ApkAssets> LoadImpl( 170 std::unique_ptr<const AssetsProvider> assets, const std::string& path, 171 package_property_t property_flags, 172 std::unique_ptr<const AssetsProvider> override_assets = nullptr, 173 std::unique_ptr<Asset> idmap_asset = nullptr, 174 std::unique_ptr<const LoadedIdmap> idmap = nullptr); 175 176 static std::unique_ptr<const ApkAssets> LoadTableImpl( 177 std::unique_ptr<Asset> resources_asset, const std::string& path, 178 package_property_t property_flags, 179 std::unique_ptr<const AssetsProvider> override_assets = nullptr); 180 181 ApkAssets(std::unique_ptr<const AssetsProvider> assets_provider, 182 std::string path, 183 time_t last_mod_time, 184 package_property_t property_flags); 185 186 std::unique_ptr<const AssetsProvider> assets_provider_; 187 const std::string path_; 188 time_t last_mod_time_; 189 package_property_t property_flags_ = 0U; 190 std::unique_ptr<Asset> resources_asset_; 191 std::unique_ptr<Asset> idmap_asset_; 192 std::unique_ptr<const LoadedArsc> loaded_arsc_; 193 std::unique_ptr<const LoadedIdmap> loaded_idmap_; 194 }; 195 196 } // namespace android 197 198 #endif /* APKASSETS_H_ */ 199