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