blob: 8b28bac26f9a3331a55c4c194fa2d00a40245d88 [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>
Yurii Zubrytskyida208012020-04-07 15:35:21 -070026#include <ziparchive/zip_archive.h>
Songchun Fan3c82a302019-11-29 14:23:45 -080027
28#include <atomic>
29#include <chrono>
Yurii Zubrytskyida208012020-04-07 15:35:21 -070030#include <condition_variable>
31#include <functional>
Songchun Fan3c82a302019-11-29 14:23:45 -080032#include <limits>
33#include <map>
34#include <mutex>
Songchun Fan9b753082020-02-26 13:08:06 -080035#include <span>
Songchun Fan3c82a302019-11-29 14:23:45 -080036#include <string>
37#include <string_view>
Yurii Zubrytskyida208012020-04-07 15:35:21 -070038#include <thread>
Songchun Fan3c82a302019-11-29 14:23:45 -080039#include <unordered_map>
40#include <utility>
41#include <vector>
42
43#include "ServiceWrappers.h"
44#include "android/content/pm/BnDataLoaderStatusListener.h"
Alex Buynytskyyf4156792020-04-07 14:26:55 -070045#include "android/os/incremental/BnIncrementalServiceConnector.h"
Songchun Fan3c82a302019-11-29 14:23:45 -080046#include "incfs.h"
47#include "path.h"
48
49using namespace android::os::incremental;
50
51namespace android::os {
52class IVold;
53}
54
55namespace android::incremental {
56
57using MountId = int;
58using StorageId = int;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080059using FileId = incfs::FileId;
Songchun Fan3c82a302019-11-29 14:23:45 -080060using BlockIndex = incfs::BlockIndex;
61using RawMetadata = incfs::RawMetadata;
62using Clock = std::chrono::steady_clock;
63using TimePoint = std::chrono::time_point<Clock>;
64using Seconds = std::chrono::seconds;
65
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -070066using IDataLoaderStatusListener = ::android::content::pm::IDataLoaderStatusListener;
67using DataLoaderStatusListener = ::android::sp<IDataLoaderStatusListener>;
Alex Buynytskyy04f73912020-02-10 08:34:18 -080068
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080069class IncrementalService final {
Songchun Fan3c82a302019-11-29 14:23:45 -080070public:
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080071 explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
Songchun Fan3c82a302019-11-29 14:23:45 -080072
73#pragma GCC diagnostic push
74#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
75 ~IncrementalService();
76#pragma GCC diagnostic pop
77
78 static constexpr StorageId kInvalidStorageId = -1;
79 static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max();
80
81 enum CreateOptions {
82 TemporaryBind = 1,
83 PermanentBind = 2,
84 CreateNew = 4,
85 OpenExisting = 8,
86
87 Default = TemporaryBind | CreateNew
88 };
89
90 enum class BindKind {
91 Temporary = 0,
92 Permanent = 1,
93 };
94
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080095 static FileId idFromMetadata(std::span<const uint8_t> metadata);
96 static inline FileId idFromMetadata(std::span<const char> metadata) {
97 return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
98 }
99
Alex Buynytskyy18b07a42020-02-03 20:06:00 -0800100 void onDump(int fd);
101
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700102 void onSystemReady();
Songchun Fan3c82a302019-11-29 14:23:45 -0800103
Songchun Fan9b753082020-02-26 13:08:06 -0800104 StorageId createStorage(std::string_view mountPoint, DataLoaderParamsParcel&& dataLoaderParams,
Alex Buynytskyy04f73912020-02-10 08:34:18 -0800105 const DataLoaderStatusListener& dataLoaderStatusListener,
Songchun Fan3c82a302019-11-29 14:23:45 -0800106 CreateOptions options = CreateOptions::Default);
107 StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
108 CreateOptions options = CreateOptions::Default);
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800109 StorageId openStorage(std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800110
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800111 FileId nodeFor(StorageId storage, std::string_view path) const;
112 std::pair<FileId, std::string_view> parentAndNameFor(StorageId storage,
113 std::string_view path) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800114
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800115 int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
Songchun Fan3c82a302019-11-29 14:23:45 -0800116 int unbind(StorageId storage, std::string_view target);
117 void deleteStorage(StorageId storage);
118
Alex Buynytskyy5e860ba2020-03-31 15:30:21 -0700119 int setStorageParams(StorageId storage, bool enableReadLogs);
120
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800121 int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
122 incfs::NewFileParams params);
Songchun Fan96100932020-02-03 19:20:58 -0800123 int makeDir(StorageId storage, std::string_view path, int mode = 0755);
124 int makeDirs(StorageId storage, std::string_view path, int mode = 0755);
Songchun Fan3c82a302019-11-29 14:23:45 -0800125
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800126 int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
127 std::string_view newPath);
128 int unlink(StorageId storage, std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800129
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800130 bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
Songchun Fan3c82a302019-11-29 14:23:45 -0800131 return false;
132 }
133
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800134 RawMetadata getMetadata(StorageId storage, FileId node) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800135
136 std::vector<std::string> listFiles(StorageId storage) const;
137 bool startLoading(StorageId storage) const;
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700138
Songchun Fan0f8b6fe2020-02-05 17:41:25 -0800139 bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
140 std::string_view libDirRelativePath, std::string_view abi);
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700141 bool waitForNativeBinariesExtraction(StorageId storage);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700142
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700143 class AppOpsListener : public android::BnAppOpsCallback {
144 public:
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700145 AppOpsListener(IncrementalService& incrementalService, std::string packageName)
146 : incrementalService(incrementalService), packageName(std::move(packageName)) {}
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700147 void opChanged(int32_t op, const String16& packageName) final;
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700148
149 private:
150 IncrementalService& incrementalService;
151 const std::string packageName;
152 };
153
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700154 class IncrementalServiceConnector : public BnIncrementalServiceConnector {
155 public:
156 IncrementalServiceConnector(IncrementalService& incrementalService, int32_t storage)
Alex Buynytskyy5f9e3a02020-04-07 21:13:41 -0700157 : incrementalService(incrementalService), storage(storage) {}
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700158 binder::Status setStorageParams(bool enableReadLogs, int32_t* _aidl_return) final;
159
160 private:
161 IncrementalService& incrementalService;
Alex Buynytskyy5f9e3a02020-04-07 21:13:41 -0700162 int32_t const storage;
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700163 };
164
Songchun Fan3c82a302019-11-29 14:23:45 -0800165private:
Yurii Zubrytskyi3787c9f2020-04-06 23:10:28 -0700166 static const bool sEnablePerfLogging;
167
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700168 struct IncFsMount;
169
170 class DataLoaderStub : public android::content::pm::BnDataLoaderStatusListener {
171 public:
172 DataLoaderStub(IncrementalService& service, MountId id, DataLoaderParamsParcel&& params,
173 FileSystemControlParcel&& control,
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700174 const DataLoaderStatusListener* externalListener);
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700175 ~DataLoaderStub();
176
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700177 bool requestCreate();
Alex Buynytskyy0b202662020-04-13 09:53:04 -0700178 bool requestStart();
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700179 bool requestDestroy();
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700180
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700181 bool waitForDestroy(Clock::duration duration = std::chrono::seconds(60));
182
183 void onDump(int fd);
184
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700185 MountId id() const { return mId; }
186 const DataLoaderParamsParcel& params() const { return mParams; }
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700187
188 private:
189 binder::Status onStatusChanged(MountId mount, int newStatus) final;
190
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700191 bool create();
Alex Buynytskyy0b202662020-04-13 09:53:04 -0700192 bool start();
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700193 bool destroy();
194
195 bool setTargetStatus(int status);
196 bool waitForStatus(int status, Clock::duration duration);
197
198 bool fsmStep();
Alex Buynytskyy0b202662020-04-13 09:53:04 -0700199
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700200 IncrementalService& mService;
201 MountId const mId;
202 DataLoaderParamsParcel const mParams;
203 FileSystemControlParcel const mControl;
204 DataLoaderStatusListener const mListener;
205
Alex Buynytskyy0b202662020-04-13 09:53:04 -0700206 std::mutex mStatusMutex;
207 std::condition_variable mStatusCondition;
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700208 int mCurrentStatus = IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
209 int mTargetStatus = IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
210 TimePoint mTargetStatusTs = {};
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700211 };
212 using DataLoaderStubPtr = sp<DataLoaderStub>;
213
Songchun Fan3c82a302019-11-29 14:23:45 -0800214 struct IncFsMount {
215 struct Bind {
216 StorageId storage;
217 std::string savedFilename;
218 std::string sourceDir;
219 BindKind kind;
220 };
221
222 struct Storage {
223 std::string name;
Songchun Fan3c82a302019-11-29 14:23:45 -0800224 };
225
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800226 using Control = incfs::UniqueControl;
Songchun Fan3c82a302019-11-29 14:23:45 -0800227
228 using BindMap = std::map<std::string, Bind>;
229 using StorageMap = std::unordered_map<StorageId, Storage>;
230
231 mutable std::mutex lock;
232 const std::string root;
233 Control control;
234 /*const*/ MountId mountId;
235 StorageMap storages;
236 BindMap bindPoints;
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700237 DataLoaderStubPtr dataLoaderStub;
Songchun Fan3c82a302019-11-29 14:23:45 -0800238 std::atomic<int> nextStorageDirNo{0};
Songchun Fan3c82a302019-11-29 14:23:45 -0800239 const IncrementalService& incrementalService;
240
241 IncFsMount(std::string root, MountId mountId, Control control,
242 const IncrementalService& incrementalService)
243 : root(std::move(root)),
244 control(std::move(control)),
245 mountId(mountId),
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700246 incrementalService(incrementalService) {}
Songchun Fan3c82a302019-11-29 14:23:45 -0800247 IncFsMount(IncFsMount&&) = delete;
248 IncFsMount& operator=(IncFsMount&&) = delete;
249 ~IncFsMount();
250
251 StorageMap::iterator makeStorage(StorageId id);
252
253 static void cleanupFilesystem(std::string_view root);
254 };
255
256 using IfsMountPtr = std::shared_ptr<IncFsMount>;
257 using MountMap = std::unordered_map<MountId, IfsMountPtr>;
258 using BindPathMap = std::map<std::string, IncFsMount::BindMap::iterator, path::PathLess>;
259
260 void mountExistingImages();
Yurii Zubrytskyi107ae352020-04-03 13:12:51 -0700261 bool mountExistingImage(std::string_view root);
Songchun Fan3c82a302019-11-29 14:23:45 -0800262
263 IfsMountPtr getIfs(StorageId storage) const;
264 const IfsMountPtr& getIfsLocked(StorageId storage) const;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800265 int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
266 std::string&& source, std::string&& target, BindKind kind,
267 std::unique_lock<std::mutex>& mainLock);
Songchun Fan3c82a302019-11-29 14:23:45 -0800268
269 int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800270 std::string&& source, std::string&& target, BindKind kind,
Songchun Fan3c82a302019-11-29 14:23:45 -0800271 std::unique_lock<std::mutex>& mainLock);
272
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700273 DataLoaderStubPtr prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel&& params,
274 const DataLoaderStatusListener* externalListener = nullptr);
Alex Buynytskyybf1c0632020-03-10 15:49:29 -0700275
Songchun Fan3c82a302019-11-29 14:23:45 -0800276 BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
277 StorageId findStorageId(std::string_view path) const;
278
279 void deleteStorage(IncFsMount& ifs);
280 void deleteStorageLocked(IncFsMount& ifs, std::unique_lock<std::mutex>&& ifsLock);
281 MountMap::iterator getStorageSlotLocked();
Yurii Zubrytskyi3787c9f2020-04-06 23:10:28 -0700282 std::string normalizePathToStorage(const IfsMountPtr& incfs, StorageId storage,
Songchun Fan103ba1d2020-02-03 17:32:32 -0800283 std::string_view path);
Yurii Zubrytskyi3787c9f2020-04-06 23:10:28 -0700284 std::string normalizePathToStorageLocked(IncFsMount::StorageMap::iterator storageIt,
285 std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800286
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700287 binder::Status applyStorageParams(IncFsMount& ifs, bool enableReadLogs);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700288
289 void registerAppOpsCallback(const std::string& packageName);
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700290 bool unregisterAppOpsCallback(const std::string& packageName);
291 void onAppOpChanged(const std::string& packageName);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700292
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700293 void runJobProcessing();
294 void extractZipFile(const IfsMountPtr& ifs, ZipArchiveHandle zipFile, ZipEntry& entry,
295 const incfs::FileId& libFileId, std::string_view targetLibPath,
296 Clock::time_point scheduledTs);
297
298private:
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700299 const std::unique_ptr<VoldServiceWrapper> mVold;
300 const std::unique_ptr<DataLoaderManagerWrapper> mDataLoaderManager;
301 const std::unique_ptr<IncFsWrapper> mIncFs;
302 const std::unique_ptr<AppOpsManagerWrapper> mAppOpsManager;
303 const std::unique_ptr<JniWrapper> mJni;
Songchun Fan3c82a302019-11-29 14:23:45 -0800304 const std::string mIncrementalDir;
305
306 mutable std::mutex mLock;
307 mutable std::mutex mMountOperationLock;
308 MountMap mMounts;
309 BindPathMap mBindsByPath;
310
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700311 std::mutex mCallbacksLock;
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700312 std::map<std::string, sp<AppOpsListener>> mCallbackRegistered;
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700313
Songchun Fan3c82a302019-11-29 14:23:45 -0800314 std::atomic_bool mSystemReady = false;
315 StorageId mNextId = 0;
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700316
317 using Job = std::function<void()>;
Yurii Zubrytskyi721ac4d2020-04-13 11:34:32 -0700318 std::unordered_map<MountId, std::vector<Job>> mJobQueue;
319 MountId mPendingJobsMount = kInvalidStorageId;
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700320 std::condition_variable mJobCondition;
321 std::mutex mJobMutex;
322 std::thread mJobProcessor;
323 bool mRunning = true;
Songchun Fan3c82a302019-11-29 14:23:45 -0800324};
325
326} // namespace android::incremental