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