1 /* 2 * Copyright (C) 2021 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 ANDROIDFW_ASSETSPROVIDER_H 18 #define ANDROIDFW_ASSETSPROVIDER_H 19 20 #include <memory> 21 #include <string> 22 23 #include "android-base/function_ref.h" 24 #include "android-base/macros.h" 25 #include "android-base/unique_fd.h" 26 27 #include "androidfw/Asset.h" 28 #include "androidfw/Idmap.h" 29 #include "androidfw/LoadedArsc.h" 30 #include "androidfw/misc.h" 31 32 struct ZipArchive; 33 34 namespace android { 35 36 // Interface responsible for opening and iterating through asset files. 37 struct AssetsProvider { 38 static constexpr off64_t kUnknownLength = -1; 39 40 // Opens a file for reading. If `file_exists` is not null, it will be set to `true` if the file 41 // exists. This is useful for determining if the file exists but was unable to be opened due to 42 // an I/O error. 43 std::unique_ptr<Asset> Open(const std::string& path, 44 Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM, 45 bool* file_exists = nullptr) const; 46 47 // Iterate over all files and directories provided by the interface. The order of iteration is 48 // stable. 49 virtual bool ForEachFile(const std::string& path, 50 base::function_ref<void(StringPiece, FileType)> f) const = 0; 51 52 // Retrieves the path to the contents of the AssetsProvider on disk. The path could represent an 53 // APk, a directory, or some other file type. 54 WARN_UNUSED virtual std::optional<std::string_view> GetPath() const = 0; 55 56 // Retrieves a name that represents the interface. This may or may not be the path of the 57 // interface source. 58 WARN_UNUSED virtual const std::string& GetDebugName() const = 0; 59 60 // Returns whether the interface provides the most recent version of its files. 61 WARN_UNUSED virtual bool IsUpToDate() const = 0; 62 63 // Creates an Asset from a file on disk. 64 static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path); 65 66 // Creates an Asset from a file descriptor. 67 // 68 // The asset takes ownership of the file descriptor. If `length` equals kUnknownLength, offset 69 // must equal 0; otherwise, the asset data will be read using the `offset` into the file 70 // descriptor and will be `length` bytes long. 71 static std::unique_ptr<Asset> CreateAssetFromFd(base::unique_fd fd, 72 const char* path, 73 off64_t offset = 0, 74 off64_t length = AssetsProvider::kUnknownLength); 75 76 virtual ~AssetsProvider() = default; 77 protected: 78 virtual std::unique_ptr<Asset> OpenInternal(const std::string& path, Asset::AccessMode mode, 79 bool* file_exists) const = 0; 80 }; 81 82 // Supplies assets from a zip archive. 83 struct ZipAssetsProvider : public AssetsProvider { 84 static std::unique_ptr<ZipAssetsProvider> Create(std::string path, package_property_t flags, 85 base::unique_fd fd = {}); 86 87 static std::unique_ptr<ZipAssetsProvider> Create(base::unique_fd fd, 88 std::string friendly_name, 89 package_property_t flags, 90 off64_t offset = 0, 91 off64_t len = kUnknownLength); 92 93 bool ForEachFile(const std::string& root_path, 94 base::function_ref<void(StringPiece, FileType)> f) const override; 95 96 WARN_UNUSED std::optional<std::string_view> GetPath() const override; 97 WARN_UNUSED const std::string& GetDebugName() const override; 98 WARN_UNUSED bool IsUpToDate() const override; 99 WARN_UNUSED std::optional<uint32_t> GetCrc(std::string_view path) const; 100 101 ~ZipAssetsProvider() override = default; 102 protected: 103 std::unique_ptr<Asset> OpenInternal(const std::string& path, Asset::AccessMode mode, 104 bool* file_exists) const override; 105 106 private: 107 struct PathOrDebugName; 108 ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path, package_property_t flags, 109 time_t last_mod_time); 110 111 struct PathOrDebugName { PathZipAssetsProvider::PathOrDebugName112 static PathOrDebugName Path(std::string value) { 113 return {std::move(value), true}; 114 } DebugNameZipAssetsProvider::PathOrDebugName115 static PathOrDebugName DebugName(std::string value) { 116 return {std::move(value), false}; 117 } 118 119 // Retrieves the path or null if this class represents a debug name. 120 WARN_UNUSED const std::string* GetPath() const; 121 122 // Retrieves a name that represents the interface. This may or may not represent a path. 123 WARN_UNUSED const std::string& GetDebugName() const; 124 125 private: PathOrDebugNameZipAssetsProvider::PathOrDebugName126 PathOrDebugName(std::string value, bool is_path) : value_(std::move(value)), is_path_(is_path) { 127 } 128 std::string value_; 129 bool is_path_; 130 }; 131 132 struct ZipCloser { 133 void operator()(ZipArchive* a) const; 134 }; 135 std::unique_ptr<ZipArchive, ZipCloser> zip_handle_; 136 PathOrDebugName name_; 137 package_property_t flags_; 138 time_t last_mod_time_; 139 }; 140 141 // Supplies assets from a root directory. 142 struct DirectoryAssetsProvider : public AssetsProvider { 143 static std::unique_ptr<DirectoryAssetsProvider> Create(std::string root_dir); 144 145 bool ForEachFile(const std::string& path, 146 base::function_ref<void(StringPiece, FileType)> f) const override; 147 148 WARN_UNUSED std::optional<std::string_view> GetPath() const override; 149 WARN_UNUSED const std::string& GetDebugName() const override; 150 WARN_UNUSED bool IsUpToDate() const override; 151 152 ~DirectoryAssetsProvider() override = default; 153 protected: 154 std::unique_ptr<Asset> OpenInternal(const std::string& path, 155 Asset::AccessMode mode, 156 bool* file_exists) const override; 157 158 private: 159 explicit DirectoryAssetsProvider(std::string&& path, time_t last_mod_time); 160 std::string dir_; 161 time_t last_mod_time_; 162 }; 163 164 // Supplies assets from a `primary` asset provider and falls back to supplying assets from the 165 // `secondary` asset provider if the asset cannot be found in the `primary`. 166 struct MultiAssetsProvider : public AssetsProvider { 167 static std::unique_ptr<AssetsProvider> Create(std::unique_ptr<AssetsProvider>&& primary, 168 std::unique_ptr<AssetsProvider>&& secondary); 169 170 bool ForEachFile(const std::string& root_path, 171 base::function_ref<void(StringPiece, FileType)> f) const override; 172 173 WARN_UNUSED std::optional<std::string_view> GetPath() const override; 174 WARN_UNUSED const std::string& GetDebugName() const override; 175 WARN_UNUSED bool IsUpToDate() const override; 176 177 ~MultiAssetsProvider() override = default; 178 protected: 179 std::unique_ptr<Asset> OpenInternal( 180 const std::string& path, Asset::AccessMode mode, bool* file_exists) const override; 181 182 private: 183 MultiAssetsProvider(std::unique_ptr<AssetsProvider>&& primary, 184 std::unique_ptr<AssetsProvider>&& secondary); 185 186 std::unique_ptr<AssetsProvider> primary_; 187 std::unique_ptr<AssetsProvider> secondary_; 188 std::optional<std::string_view> path_; 189 std::string debug_name_; 190 }; 191 192 // Does not provide any assets. 193 struct EmptyAssetsProvider : public AssetsProvider { 194 static std::unique_ptr<AssetsProvider> Create(); 195 static std::unique_ptr<AssetsProvider> Create(std::string path); 196 197 bool ForEachFile(const std::string& path, 198 base::function_ref<void(StringPiece, FileType)> f) const override; 199 200 WARN_UNUSED std::optional<std::string_view> GetPath() const override; 201 WARN_UNUSED const std::string& GetDebugName() const override; 202 WARN_UNUSED bool IsUpToDate() const override; 203 204 ~EmptyAssetsProvider() override = default; 205 protected: 206 std::unique_ptr<Asset> OpenInternal(const std::string& path, Asset::AccessMode mode, 207 bool* file_exists) const override; 208 209 private: 210 explicit EmptyAssetsProvider(std::optional<std::string>&& path); 211 std::optional<std::string> path_; 212 }; 213 214 } // namespace android 215 216 #endif /* ANDROIDFW_ASSETSPROVIDER_H */ 217