blob: 27d40f1506ca2dbf11aaca6bd2ef63f63dfc6c73 [file] [log] [blame]
Songchun Fan3c82a302019-11-29 14:23:45 -08001/*
2 * Copyright (C) 2019 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 <android-base/strings.h>
20#include <android-base/unique_fd.h>
Songchun Fan3c82a302019-11-29 14:23:45 -080021#include <android/content/pm/DataLoaderParamsParcel.h>
22#include <binder/IServiceManager.h>
23#include <utils/String16.h>
24#include <utils/StrongPointer.h>
25#include <utils/Vector.h>
26
27#include <atomic>
28#include <chrono>
29#include <future>
30#include <limits>
31#include <map>
32#include <mutex>
Songchun Fan9b753082020-02-26 13:08:06 -080033#include <span>
Songchun Fan3c82a302019-11-29 14:23:45 -080034#include <string>
35#include <string_view>
36#include <unordered_map>
37#include <utility>
38#include <vector>
39
40#include "ServiceWrappers.h"
41#include "android/content/pm/BnDataLoaderStatusListener.h"
Alex Buynytskyyf4156792020-04-07 14:26:55 -070042#include "android/os/incremental/BnIncrementalServiceConnector.h"
Songchun Fan3c82a302019-11-29 14:23:45 -080043#include "incfs.h"
44#include "path.h"
45
46using namespace android::os::incremental;
47
48namespace android::os {
49class IVold;
50}
51
52namespace android::incremental {
53
54using MountId = int;
55using StorageId = int;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080056using FileId = incfs::FileId;
Songchun Fan3c82a302019-11-29 14:23:45 -080057using BlockIndex = incfs::BlockIndex;
58using RawMetadata = incfs::RawMetadata;
59using Clock = std::chrono::steady_clock;
60using TimePoint = std::chrono::time_point<Clock>;
61using Seconds = std::chrono::seconds;
62
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -070063using IDataLoaderStatusListener = ::android::content::pm::IDataLoaderStatusListener;
64using DataLoaderStatusListener = ::android::sp<IDataLoaderStatusListener>;
Alex Buynytskyy04f73912020-02-10 08:34:18 -080065
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080066class IncrementalService final {
Songchun Fan3c82a302019-11-29 14:23:45 -080067public:
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080068 explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
Songchun Fan3c82a302019-11-29 14:23:45 -080069
70#pragma GCC diagnostic push
71#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
72 ~IncrementalService();
73#pragma GCC diagnostic pop
74
75 static constexpr StorageId kInvalidStorageId = -1;
76 static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max();
77
78 enum CreateOptions {
79 TemporaryBind = 1,
80 PermanentBind = 2,
81 CreateNew = 4,
82 OpenExisting = 8,
83
84 Default = TemporaryBind | CreateNew
85 };
86
87 enum class BindKind {
88 Temporary = 0,
89 Permanent = 1,
90 };
91
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080092 static FileId idFromMetadata(std::span<const uint8_t> metadata);
93 static inline FileId idFromMetadata(std::span<const char> metadata) {
94 return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
95 }
96
Alex Buynytskyy18b07a42020-02-03 20:06:00 -080097 void onDump(int fd);
98
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -070099 void onSystemReady();
Songchun Fan3c82a302019-11-29 14:23:45 -0800100
Songchun Fan9b753082020-02-26 13:08:06 -0800101 StorageId createStorage(std::string_view mountPoint, DataLoaderParamsParcel&& dataLoaderParams,
Alex Buynytskyy04f73912020-02-10 08:34:18 -0800102 const DataLoaderStatusListener& dataLoaderStatusListener,
Songchun Fan3c82a302019-11-29 14:23:45 -0800103 CreateOptions options = CreateOptions::Default);
104 StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
105 CreateOptions options = CreateOptions::Default);
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800106 StorageId openStorage(std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800107
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800108 FileId nodeFor(StorageId storage, std::string_view path) const;
109 std::pair<FileId, std::string_view> parentAndNameFor(StorageId storage,
110 std::string_view path) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800111
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800112 int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
Songchun Fan3c82a302019-11-29 14:23:45 -0800113 int unbind(StorageId storage, std::string_view target);
114 void deleteStorage(StorageId storage);
115
Alex Buynytskyy5e860ba2020-03-31 15:30:21 -0700116 int setStorageParams(StorageId storage, bool enableReadLogs);
117
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800118 int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
119 incfs::NewFileParams params);
Songchun Fan96100932020-02-03 19:20:58 -0800120 int makeDir(StorageId storage, std::string_view path, int mode = 0755);
121 int makeDirs(StorageId storage, std::string_view path, int mode = 0755);
Songchun Fan3c82a302019-11-29 14:23:45 -0800122
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800123 int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
124 std::string_view newPath);
125 int unlink(StorageId storage, std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800126
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800127 bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
Songchun Fan3c82a302019-11-29 14:23:45 -0800128 return false;
129 }
130
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800131 RawMetadata getMetadata(StorageId storage, FileId node) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800132
133 std::vector<std::string> listFiles(StorageId storage) const;
134 bool startLoading(StorageId storage) const;
Songchun Fan0f8b6fe2020-02-05 17:41:25 -0800135 bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
136 std::string_view libDirRelativePath, std::string_view abi);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700137
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700138 class AppOpsListener : public android::BnAppOpsCallback {
139 public:
140 AppOpsListener(IncrementalService& incrementalService, std::string packageName) : incrementalService(incrementalService), packageName(std::move(packageName)) {}
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700141 void opChanged(int32_t op, const String16& packageName) final;
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700142
143 private:
144 IncrementalService& incrementalService;
145 const std::string packageName;
146 };
147
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700148 class IncrementalServiceConnector : public BnIncrementalServiceConnector {
149 public:
150 IncrementalServiceConnector(IncrementalService& incrementalService, int32_t storage)
Alex Buynytskyy5f9e3a02020-04-07 21:13:41 -0700151 : incrementalService(incrementalService), storage(storage) {}
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700152 binder::Status setStorageParams(bool enableReadLogs, int32_t* _aidl_return) final;
153
154 private:
155 IncrementalService& incrementalService;
Alex Buynytskyy5f9e3a02020-04-07 21:13:41 -0700156 int32_t const storage;
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700157 };
158
Songchun Fan3c82a302019-11-29 14:23:45 -0800159private:
Yurii Zubrytskyi3787c9f2020-04-06 23:10:28 -0700160 static const bool sEnablePerfLogging;
161
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700162 struct IncFsMount;
163
164 class DataLoaderStub : public android::content::pm::BnDataLoaderStatusListener {
165 public:
166 DataLoaderStub(IncrementalService& service, MountId id, DataLoaderParamsParcel&& params,
167 FileSystemControlParcel&& control,
168 const DataLoaderStatusListener* externalListener)
169 : mService(service),
170 mId(id),
171 mParams(std::move(params)),
172 mControl(std::move(control)),
173 mListener(externalListener ? *externalListener : DataLoaderStatusListener()) {}
174 ~DataLoaderStub();
175
176 bool create();
177 bool start();
178 void destroy();
179
180 // accessors
181 MountId id() const { return mId; }
182 const DataLoaderParamsParcel& params() const { return mParams; }
183 int status() const { return mStatus.load(); }
184 bool startRequested() const { return mStartRequested; }
185
186 private:
187 binder::Status onStatusChanged(MountId mount, int newStatus) final;
188
189 IncrementalService& mService;
190 MountId const mId;
191 DataLoaderParamsParcel const mParams;
192 FileSystemControlParcel const mControl;
193 DataLoaderStatusListener const mListener;
194
195 std::atomic<int> mStatus = -1;
196 bool mStartRequested = false;
197 bool mDestroyRequested = false;
198 };
199 using DataLoaderStubPtr = sp<DataLoaderStub>;
200
Songchun Fan3c82a302019-11-29 14:23:45 -0800201 struct IncFsMount {
202 struct Bind {
203 StorageId storage;
204 std::string savedFilename;
205 std::string sourceDir;
206 BindKind kind;
207 };
208
209 struct Storage {
210 std::string name;
Songchun Fan3c82a302019-11-29 14:23:45 -0800211 };
212
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800213 using Control = incfs::UniqueControl;
Songchun Fan3c82a302019-11-29 14:23:45 -0800214
215 using BindMap = std::map<std::string, Bind>;
216 using StorageMap = std::unordered_map<StorageId, Storage>;
217
218 mutable std::mutex lock;
219 const std::string root;
220 Control control;
221 /*const*/ MountId mountId;
222 StorageMap storages;
223 BindMap bindPoints;
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700224 DataLoaderStubPtr dataLoaderStub;
Songchun Fan3c82a302019-11-29 14:23:45 -0800225 std::atomic<int> nextStorageDirNo{0};
Songchun Fan3c82a302019-11-29 14:23:45 -0800226 const IncrementalService& incrementalService;
227
228 IncFsMount(std::string root, MountId mountId, Control control,
229 const IncrementalService& incrementalService)
230 : root(std::move(root)),
231 control(std::move(control)),
232 mountId(mountId),
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700233 incrementalService(incrementalService) {}
Songchun Fan3c82a302019-11-29 14:23:45 -0800234 IncFsMount(IncFsMount&&) = delete;
235 IncFsMount& operator=(IncFsMount&&) = delete;
236 ~IncFsMount();
237
238 StorageMap::iterator makeStorage(StorageId id);
239
240 static void cleanupFilesystem(std::string_view root);
241 };
242
243 using IfsMountPtr = std::shared_ptr<IncFsMount>;
244 using MountMap = std::unordered_map<MountId, IfsMountPtr>;
245 using BindPathMap = std::map<std::string, IncFsMount::BindMap::iterator, path::PathLess>;
246
247 void mountExistingImages();
Yurii Zubrytskyi107ae352020-04-03 13:12:51 -0700248 bool mountExistingImage(std::string_view root);
Songchun Fan3c82a302019-11-29 14:23:45 -0800249
250 IfsMountPtr getIfs(StorageId storage) const;
251 const IfsMountPtr& getIfsLocked(StorageId storage) const;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800252 int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
253 std::string&& source, std::string&& target, BindKind kind,
254 std::unique_lock<std::mutex>& mainLock);
Songchun Fan3c82a302019-11-29 14:23:45 -0800255
256 int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800257 std::string&& source, std::string&& target, BindKind kind,
Songchun Fan3c82a302019-11-29 14:23:45 -0800258 std::unique_lock<std::mutex>& mainLock);
259
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700260 DataLoaderStubPtr prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel&& params,
261 const DataLoaderStatusListener* externalListener = nullptr);
Alex Buynytskyybf1c0632020-03-10 15:49:29 -0700262
Songchun Fan3c82a302019-11-29 14:23:45 -0800263 BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
264 StorageId findStorageId(std::string_view path) const;
265
266 void deleteStorage(IncFsMount& ifs);
267 void deleteStorageLocked(IncFsMount& ifs, std::unique_lock<std::mutex>&& ifsLock);
268 MountMap::iterator getStorageSlotLocked();
Yurii Zubrytskyi3787c9f2020-04-06 23:10:28 -0700269 std::string normalizePathToStorage(const IfsMountPtr& incfs, StorageId storage,
Songchun Fan103ba1d2020-02-03 17:32:32 -0800270 std::string_view path);
Yurii Zubrytskyi3787c9f2020-04-06 23:10:28 -0700271 std::string normalizePathToStorageLocked(IncFsMount::StorageMap::iterator storageIt,
272 std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800273
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700274 binder::Status applyStorageParams(IncFsMount& ifs, bool enableReadLogs);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700275
276 void registerAppOpsCallback(const std::string& packageName);
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700277 bool unregisterAppOpsCallback(const std::string& packageName);
278 void onAppOpChanged(const std::string& packageName);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700279
Songchun Fan3c82a302019-11-29 14:23:45 -0800280 // Member variables
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700281 std::unique_ptr<VoldServiceWrapper> const mVold;
282 std::unique_ptr<DataLoaderManagerWrapper> const mDataLoaderManager;
283 std::unique_ptr<IncFsWrapper> const mIncFs;
284 std::unique_ptr<AppOpsManagerWrapper> const mAppOpsManager;
Songchun Fan3c82a302019-11-29 14:23:45 -0800285 const std::string mIncrementalDir;
286
287 mutable std::mutex mLock;
288 mutable std::mutex mMountOperationLock;
289 MountMap mMounts;
290 BindPathMap mBindsByPath;
291
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700292 std::mutex mCallbacksLock;
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700293 std::map<std::string, sp<AppOpsListener>> mCallbackRegistered;
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700294
Songchun Fan3c82a302019-11-29 14:23:45 -0800295 std::atomic_bool mSystemReady = false;
296 StorageId mNextId = 0;
Songchun Fan3c82a302019-11-29 14:23:45 -0800297};
298
299} // namespace android::incremental