• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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