• 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 #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