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 <utils/RefBase.h> 21 22 #include <memory> 23 #include <string> 24 25 #include "android-base/macros.h" 26 #include "android-base/unique_fd.h" 27 #include "androidfw/Asset.h" 28 #include "androidfw/AssetsProvider.h" 29 #include "androidfw/Idmap.h" 30 #include "androidfw/LoadedArsc.h" 31 #include "androidfw/misc.h" 32 33 namespace android { 34 35 class ApkAssets; 36 37 using ApkAssetsPtr = sp<ApkAssets>; 38 39 // Holds an APK. 40 class ApkAssets : public RefBase { 41 public: 42 // Creates an ApkAssets from a path on device. 43 static ApkAssetsPtr Load(const std::string& path, package_property_t flags = 0U); 44 45 // Creates an ApkAssets from an open file descriptor. 46 static ApkAssetsPtr LoadFromFd(base::unique_fd fd, const std::string& debug_name, 47 package_property_t flags = 0U, off64_t offset = 0, 48 off64_t len = AssetsProvider::kUnknownLength); 49 50 // 51 // Creates an ApkAssets from an AssetProvider. 52 // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed; 53 // the original argument is not moved from if loading fails. 54 // 55 // Note: this function takes care of the case when you pass a move(unique_ptr<Derived>) 56 // that would create a temporary unique_ptr<AssetsProvider> by moving your pointer into 57 // it before the function call, making it impossible to not move from the parameter 58 // on loading failure. The two overloads take care of moving the pointer back if needed. 59 // 60 61 template <class T> 62 static ApkAssetsPtr Load(std::unique_ptr<T>&& assets, package_property_t flags = 0U) requires(std::is_same_v<T,AssetsProvider>)63 requires(std::is_same_v<T, AssetsProvider>) { 64 return LoadImpl(std::move(assets), flags); 65 } 66 67 template <class T> 68 static ApkAssetsPtr Load(std::unique_ptr<T>&& assets, package_property_t flags = 0U) 69 requires(!std::is_same_v<T, AssetsProvider> && std::is_base_of_v<AssetsProvider, T>) { 70 std::unique_ptr<AssetsProvider> base_assets(std::move(assets)); 71 auto res = LoadImpl(std::move(base_assets), flags); 72 if (!res) { 73 assets.reset(static_cast<T*>(base_assets.release())); 74 } 75 return res; 76 } 77 78 // Creates an ApkAssets from the given asset file representing a resources.arsc. 79 static ApkAssetsPtr LoadTable(std::unique_ptr<Asset>&& resources_asset, 80 std::unique_ptr<AssetsProvider>&& assets, 81 package_property_t flags = 0U); 82 83 // Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay 84 // data. 85 static ApkAssetsPtr LoadOverlay(const std::string& idmap_path, package_property_t flags = 0U); 86 87 // Path to the contents of the ApkAssets on disk. The path could represent an APk, a directory, 88 // or some other file type. 89 std::optional<std::string_view> GetPath() const; 90 91 const std::string& GetDebugName() const; 92 GetAssetsProvider()93 const AssetsProvider* GetAssetsProvider() const { 94 return assets_provider_.get(); 95 } 96 97 // This is never nullptr. GetLoadedArsc()98 const LoadedArsc* GetLoadedArsc() const { 99 return loaded_arsc_.get(); 100 } 101 GetLoadedIdmap()102 const LoadedIdmap* GetLoadedIdmap() const { 103 return loaded_idmap_.get(); 104 } 105 IsLoader()106 bool IsLoader() const { 107 return (property_flags_ & PROPERTY_LOADER) != 0; 108 } 109 IsOverlay()110 bool IsOverlay() const { 111 return loaded_idmap_ != nullptr; 112 } 113 114 // Returns whether the resources.arsc is allocated in RAM (not mmapped). IsTableAllocated()115 bool IsTableAllocated() const { 116 return resources_asset_ != nullptr && resources_asset_->isAllocated(); 117 } 118 119 bool IsUpToDate() const; 120 121 // DANGER! 122 // This is a destructive method that rips the assets provider out of ApkAssets object. 123 // It is only useful when one knows this assets object can't be used anymore, and they 124 // need the underlying assets provider back (e.g. when initialization fails for some 125 // reason). TakeAssetsProvider()126 std::unique_ptr<AssetsProvider> TakeAssetsProvider() && { 127 return std::move(assets_provider_); 128 } 129 130 private: 131 static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider>&& assets, 132 package_property_t property_flags, 133 std::unique_ptr<Asset>&& idmap_asset, 134 std::unique_ptr<LoadedIdmap>&& loaded_idmap); 135 136 static ApkAssetsPtr LoadImpl(std::unique_ptr<Asset>&& resources_asset, 137 std::unique_ptr<AssetsProvider>&& assets, 138 package_property_t property_flags, 139 std::unique_ptr<Asset>&& idmap_asset, 140 std::unique_ptr<LoadedIdmap>&& loaded_idmap); 141 142 static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider>&& assets, 143 package_property_t flags = 0U); 144 145 // Allows us to make it possible to call make_shared from inside the class but still keeps the 146 // ctor 'private' for all means and purposes. 147 struct PrivateConstructorUtil { 148 explicit PrivateConstructorUtil() = default; 149 }; 150 151 public: 152 ApkAssets(PrivateConstructorUtil, std::unique_ptr<Asset> resources_asset, 153 std::unique_ptr<LoadedArsc> loaded_arsc, std::unique_ptr<AssetsProvider> assets, 154 package_property_t property_flags, std::unique_ptr<Asset> idmap_asset, 155 std::unique_ptr<LoadedIdmap> loaded_idmap); 156 157 std::unique_ptr<Asset> resources_asset_; 158 std::unique_ptr<LoadedArsc> loaded_arsc_; 159 160 std::unique_ptr<AssetsProvider> assets_provider_; 161 package_property_t property_flags_ = 0U; 162 163 std::unique_ptr<Asset> idmap_asset_; 164 std::unique_ptr<LoadedIdmap> loaded_idmap_; 165 }; 166 167 } // namespace android 168 169 #endif // APKASSETS_H_