1 /*
2  * Copyright (C) 2016 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 APKASSETS_H_
18 #define APKASSETS_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 typedef ZipArchive* ZipArchiveHandle;
33 
34 namespace android {
35 
36 class LoadedIdmap;
37 
38 // Interface for retrieving assets provided by an ApkAssets.
39 class AssetsProvider {
40  public:
41   virtual ~AssetsProvider() = default;
42 
43   // Opens a file for reading.
44   std::unique_ptr<Asset> Open(const std::string& path,
45                               Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM,
46                               bool* file_exists = nullptr) const {
47     return OpenInternal(path, mode, file_exists);
48   }
49 
50   // Iterate over all files and directories provided by the zip. The order of iteration is stable.
ForEachFile(const std::string &,const std::function<void (const StringPiece &,FileType)> &)51   virtual bool ForEachFile(const std::string& /* path */,
52                            const std::function<void(const StringPiece&, FileType)>& /* f */) const {
53     return true;
54   }
55 
56  protected:
57   AssetsProvider() = default;
58 
59   virtual std::unique_ptr<Asset> OpenInternal(const std::string& path,
60                                               Asset::AccessMode mode,
61                                               bool* file_exists) const = 0;
62 
63  private:
64   DISALLOW_COPY_AND_ASSIGN(AssetsProvider);
65 };
66 
67 class ZipAssetsProvider;
68 
69 // Holds an APK.
70 class ApkAssets {
71  public:
72   // This means the data extends to the end of the file.
73   static constexpr off64_t kUnknownLength = -1;
74 
75   // Creates an ApkAssets.
76   // If `system` is true, the package is marked as a system package, and allows some functions to
77   // filter out this package when computing what configurations/resources are available.
78   static std::unique_ptr<const ApkAssets> Load(
79       const std::string& path, package_property_t flags = 0U,
80       std::unique_ptr<const AssetsProvider> override_asset = nullptr);
81 
82   // Creates an ApkAssets from the given file descriptor, and takes ownership of the file
83   // descriptor. The `friendly_name` is some name that will be used to identify the source of
84   // this ApkAssets in log messages and other debug scenarios.
85   // If `length` equals kUnknownLength, offset must equal 0; otherwise, the apk data will be read
86   // using the `offset` into the file descriptor and will be `length` bytes long.
87   static std::unique_ptr<const ApkAssets> LoadFromFd(
88       base::unique_fd fd, const std::string& friendly_name, package_property_t flags = 0U,
89       std::unique_ptr<const AssetsProvider> override_asset = nullptr, off64_t offset = 0,
90       off64_t length = kUnknownLength);
91 
92   // Creates an ApkAssets from the given path which points to a resources.arsc.
93   static std::unique_ptr<const ApkAssets> LoadTable(
94       const std::string& path, package_property_t flags = 0U,
95       std::unique_ptr<const AssetsProvider> override_asset = nullptr);
96 
97   // Creates an ApkAssets from the given file descriptor which points to an resources.arsc, and
98   // takes ownership of the file descriptor.
99   // If `length` equals kUnknownLength, offset must equal 0; otherwise, the .arsc data will be read
100   // using the `offset` into the file descriptor and will be `length` bytes long.
101   static std::unique_ptr<const ApkAssets> LoadTableFromFd(
102       base::unique_fd fd, const std::string& friendly_name, package_property_t flags = 0U,
103       std::unique_ptr<const AssetsProvider> override_asset = nullptr, off64_t offset = 0,
104       off64_t length = kUnknownLength);
105 
106   // Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay
107   // data.
108   static std::unique_ptr<const ApkAssets> LoadOverlay(const std::string& idmap_path,
109                                                       package_property_t flags = 0U);
110 
111   // Creates an ApkAssets from the directory path. File-based resources are read within the
112   // directory as if the directory is an APK.
113   static std::unique_ptr<const ApkAssets> LoadFromDir(
114       const std::string& path, package_property_t flags = 0U,
115       std::unique_ptr<const AssetsProvider> override_asset = nullptr);
116 
117   // Creates a totally empty ApkAssets with no resources table and no file entries.
118   static std::unique_ptr<const ApkAssets> LoadEmpty(
119       package_property_t flags = 0U,
120       std::unique_ptr<const AssetsProvider> override_asset = nullptr);
121 
GetPath()122   const std::string& GetPath() const {
123     return path_;
124   }
125 
GetAssetsProvider()126   const AssetsProvider* GetAssetsProvider() const {
127     return assets_provider_.get();
128   }
129 
130   // This is never nullptr.
GetLoadedArsc()131   const LoadedArsc* GetLoadedArsc() const {
132     return loaded_arsc_.get();
133   }
134 
GetLoadedIdmap()135   const LoadedIdmap* GetLoadedIdmap() const {
136     return loaded_idmap_.get();
137   }
138 
IsLoader()139   bool IsLoader() const {
140     return (property_flags_ & PROPERTY_LOADER) != 0;
141   }
142 
IsOverlay()143   bool IsOverlay() const {
144     return loaded_idmap_ != nullptr;
145   }
146 
147   // Returns whether the resources.arsc is allocated in RAM (not mmapped).
IsTableAllocated()148   bool IsTableAllocated() const {
149     return resources_asset_ && resources_asset_->isAllocated();
150   }
151 
152   bool IsUpToDate() const;
153 
154   // Creates an Asset from a file on disk.
155   static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path);
156 
157   // Creates an Asset from a file descriptor.
158   //
159   // The asset takes ownership of the file descriptor. If `length` equals kUnknownLength, offset
160   // must equal 0; otherwise, the asset data will be read using the `offset` into the file
161   // descriptor and will be `length` bytes long.
162   static std::unique_ptr<Asset> CreateAssetFromFd(base::unique_fd fd,
163                                                   const char* path,
164                                                   off64_t offset = 0,
165                                                   off64_t length = kUnknownLength);
166  private:
167   DISALLOW_COPY_AND_ASSIGN(ApkAssets);
168 
169   static std::unique_ptr<const ApkAssets> LoadImpl(
170       std::unique_ptr<const AssetsProvider> assets, const std::string& path,
171       package_property_t property_flags,
172       std::unique_ptr<const AssetsProvider> override_assets = nullptr,
173       std::unique_ptr<Asset> idmap_asset = nullptr,
174       std::unique_ptr<const LoadedIdmap> idmap  = nullptr);
175 
176   static std::unique_ptr<const ApkAssets> LoadTableImpl(
177       std::unique_ptr<Asset> resources_asset, const std::string& path,
178       package_property_t property_flags,
179       std::unique_ptr<const AssetsProvider> override_assets = nullptr);
180 
181   ApkAssets(std::unique_ptr<const AssetsProvider> assets_provider,
182             std::string path,
183             time_t last_mod_time,
184             package_property_t property_flags);
185 
186   std::unique_ptr<const AssetsProvider> assets_provider_;
187   const std::string path_;
188   time_t last_mod_time_;
189   package_property_t property_flags_ = 0U;
190   std::unique_ptr<Asset> resources_asset_;
191   std::unique_ptr<Asset> idmap_asset_;
192   std::unique_ptr<const LoadedArsc> loaded_arsc_;
193   std::unique_ptr<const LoadedIdmap> loaded_idmap_;
194 };
195 
196 }  // namespace android
197 
198 #endif /* APKASSETS_H_ */
199