blob: 0a18e21e9d6d421a4d785134141c58d4cbc13898 [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
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070019#include <android/content/pm/BnDataLoaderStatusListener.h>
Songchun Fan3c82a302019-11-29 14:23:45 -080020#include <android/content/pm/DataLoaderParamsParcel.h>
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070021#include <android/content/pm/IDataLoaderStatusListener.h>
22#include <android/os/incremental/BnIncrementalServiceConnector.h>
23#include <binder/IAppOpsCallback.h>
Songchun Fan3c82a302019-11-29 14:23:45 -080024#include <utils/String16.h>
25#include <utils/StrongPointer.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>
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070040#include <unordered_set>
Songchun Fan3c82a302019-11-29 14:23:45 -080041#include <utility>
42#include <vector>
43
44#include "ServiceWrappers.h"
Songchun Fan3c82a302019-11-29 14:23:45 -080045#include "incfs.h"
46#include "path.h"
47
Songchun Fan3c82a302019-11-29 14:23:45 -080048namespace android::incremental {
49
50using MountId = int;
51using StorageId = int;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080052using FileId = incfs::FileId;
Songchun Fan3c82a302019-11-29 14:23:45 -080053using BlockIndex = incfs::BlockIndex;
54using RawMetadata = incfs::RawMetadata;
55using Clock = std::chrono::steady_clock;
56using TimePoint = std::chrono::time_point<Clock>;
57using Seconds = std::chrono::seconds;
58
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -070059using IDataLoaderStatusListener = ::android::content::pm::IDataLoaderStatusListener;
60using DataLoaderStatusListener = ::android::sp<IDataLoaderStatusListener>;
Alex Buynytskyy04f73912020-02-10 08:34:18 -080061
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080062class IncrementalService final {
Songchun Fan3c82a302019-11-29 14:23:45 -080063public:
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080064 explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
Songchun Fan3c82a302019-11-29 14:23:45 -080065
66#pragma GCC diagnostic push
67#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
68 ~IncrementalService();
69#pragma GCC diagnostic pop
70
71 static constexpr StorageId kInvalidStorageId = -1;
72 static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max();
73
74 enum CreateOptions {
75 TemporaryBind = 1,
76 PermanentBind = 2,
77 CreateNew = 4,
78 OpenExisting = 8,
79
80 Default = TemporaryBind | CreateNew
81 };
82
83 enum class BindKind {
84 Temporary = 0,
85 Permanent = 1,
86 };
87
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080088 static FileId idFromMetadata(std::span<const uint8_t> metadata);
89 static inline FileId idFromMetadata(std::span<const char> metadata) {
90 return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
91 }
92
Alex Buynytskyy18b07a42020-02-03 20:06:00 -080093 void onDump(int fd);
94
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -070095 void onSystemReady();
Songchun Fan3c82a302019-11-29 14:23:45 -080096
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070097 StorageId createStorage(std::string_view mountPoint,
98 content::pm::DataLoaderParamsParcel&& dataLoaderParams,
Alex Buynytskyy04f73912020-02-10 08:34:18 -080099 const DataLoaderStatusListener& dataLoaderStatusListener,
Songchun Fan3c82a302019-11-29 14:23:45 -0800100 CreateOptions options = CreateOptions::Default);
101 StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
102 CreateOptions options = CreateOptions::Default);
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800103 StorageId openStorage(std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800104
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800105 int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
Songchun Fan3c82a302019-11-29 14:23:45 -0800106 int unbind(StorageId storage, std::string_view target);
107 void deleteStorage(StorageId storage);
108
Alex Buynytskyy5e860ba2020-03-31 15:30:21 -0700109 int setStorageParams(StorageId storage, bool enableReadLogs);
110
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800111 int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
112 incfs::NewFileParams params);
Songchun Fan96100932020-02-03 19:20:58 -0800113 int makeDir(StorageId storage, std::string_view path, int mode = 0755);
114 int makeDirs(StorageId storage, std::string_view path, int mode = 0755);
Songchun Fan3c82a302019-11-29 14:23:45 -0800115
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800116 int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
117 std::string_view newPath);
118 int unlink(StorageId storage, std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800119
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800120 bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
Songchun Fan3c82a302019-11-29 14:23:45 -0800121 return false;
122 }
123
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700124 RawMetadata getMetadata(StorageId storage, std::string_view path) const;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800125 RawMetadata getMetadata(StorageId storage, FileId node) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800126
Songchun Fan3c82a302019-11-29 14:23:45 -0800127 bool startLoading(StorageId storage) const;
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700128
Songchun Fan0f8b6fe2020-02-05 17:41:25 -0800129 bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
130 std::string_view libDirRelativePath, std::string_view abi);
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700131 bool waitForNativeBinariesExtraction(StorageId storage);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700132
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700133 class AppOpsListener : public android::BnAppOpsCallback {
134 public:
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700135 AppOpsListener(IncrementalService& incrementalService, std::string packageName)
136 : incrementalService(incrementalService), packageName(std::move(packageName)) {}
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700137 void opChanged(int32_t op, const String16& packageName) final;
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700138
139 private:
140 IncrementalService& incrementalService;
141 const std::string packageName;
142 };
143
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700144 class IncrementalServiceConnector : public os::incremental::BnIncrementalServiceConnector {
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700145 public:
146 IncrementalServiceConnector(IncrementalService& incrementalService, int32_t storage)
Alex Buynytskyy5f9e3a02020-04-07 21:13:41 -0700147 : incrementalService(incrementalService), storage(storage) {}
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700148 binder::Status setStorageParams(bool enableReadLogs, int32_t* _aidl_return) final;
149
150 private:
151 IncrementalService& incrementalService;
Alex Buynytskyy5f9e3a02020-04-07 21:13:41 -0700152 int32_t const storage;
Alex Buynytskyyf4156792020-04-07 14:26:55 -0700153 };
154
Songchun Fan3c82a302019-11-29 14:23:45 -0800155private:
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700156 struct IncFsMount;
157
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700158 class DataLoaderStub : public content::pm::BnDataLoaderStatusListener {
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700159 public:
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700160 DataLoaderStub(IncrementalService& service, MountId id,
161 content::pm::DataLoaderParamsParcel&& params,
162 content::pm::FileSystemControlParcel&& control,
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700163 const DataLoaderStatusListener* externalListener);
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700164 ~DataLoaderStub();
Alex Buynytskyy9a54579a2020-04-17 15:34:47 -0700165 // Cleans up the internal state and invalidates DataLoaderStub. Any subsequent calls will
166 // result in an error.
167 void cleanupResources();
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700168
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700169 bool requestCreate();
Alex Buynytskyy0b202662020-04-13 09:53:04 -0700170 bool requestStart();
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700171 bool requestDestroy();
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700172
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700173 void onDump(int fd);
174
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700175 MountId id() const { return mId; }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700176 const content::pm::DataLoaderParamsParcel& params() const { return mParams; }
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700177
178 private:
179 binder::Status onStatusChanged(MountId mount, int newStatus) final;
180
Alex Buynytskyy9a54579a2020-04-17 15:34:47 -0700181 bool isValid() const { return mId != kInvalidStorageId; }
182
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700183 bool create();
Alex Buynytskyy0b202662020-04-13 09:53:04 -0700184 bool start();
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700185 bool destroy();
186
187 bool setTargetStatus(int status);
188 bool waitForStatus(int status, Clock::duration duration);
189
190 bool fsmStep();
Alex Buynytskyy0b202662020-04-13 09:53:04 -0700191
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700192 IncrementalService& mService;
Alex Buynytskyy9a54579a2020-04-17 15:34:47 -0700193 MountId mId = kInvalidStorageId;
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700194 content::pm::DataLoaderParamsParcel mParams;
195 content::pm::FileSystemControlParcel mControl;
Alex Buynytskyy9a54579a2020-04-17 15:34:47 -0700196 DataLoaderStatusListener mListener;
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700197
Alex Buynytskyy0b202662020-04-13 09:53:04 -0700198 std::mutex mStatusMutex;
199 std::condition_variable mStatusCondition;
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700200 int mCurrentStatus = content::pm::IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
201 int mTargetStatus = content::pm::IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
Alex Buynytskyyab65cb12020-04-17 10:01:47 -0700202 TimePoint mTargetStatusTs = {};
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700203 };
204 using DataLoaderStubPtr = sp<DataLoaderStub>;
205
Songchun Fan3c82a302019-11-29 14:23:45 -0800206 struct IncFsMount {
207 struct Bind {
208 StorageId storage;
209 std::string savedFilename;
210 std::string sourceDir;
211 BindKind kind;
212 };
213
214 struct Storage {
215 std::string name;
Songchun Fan3c82a302019-11-29 14:23:45 -0800216 };
217
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800218 using Control = incfs::UniqueControl;
Songchun Fan3c82a302019-11-29 14:23:45 -0800219
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700220 using BindMap = std::map<std::string, Bind, path::PathLess>;
Songchun Fan3c82a302019-11-29 14:23:45 -0800221 using StorageMap = std::unordered_map<StorageId, Storage>;
222
223 mutable std::mutex lock;
224 const std::string root;
225 Control control;
226 /*const*/ MountId mountId;
227 StorageMap storages;
228 BindMap bindPoints;
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700229 DataLoaderStubPtr dataLoaderStub;
Songchun Fan3c82a302019-11-29 14:23:45 -0800230 std::atomic<int> nextStorageDirNo{0};
Songchun Fan3c82a302019-11-29 14:23:45 -0800231 const IncrementalService& incrementalService;
232
233 IncFsMount(std::string root, MountId mountId, Control control,
234 const IncrementalService& incrementalService)
235 : root(std::move(root)),
236 control(std::move(control)),
237 mountId(mountId),
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700238 incrementalService(incrementalService) {}
Songchun Fan3c82a302019-11-29 14:23:45 -0800239 IncFsMount(IncFsMount&&) = delete;
240 IncFsMount& operator=(IncFsMount&&) = delete;
241 ~IncFsMount();
242
243 StorageMap::iterator makeStorage(StorageId id);
244
245 static void cleanupFilesystem(std::string_view root);
246 };
247
248 using IfsMountPtr = std::shared_ptr<IncFsMount>;
249 using MountMap = std::unordered_map<MountId, IfsMountPtr>;
250 using BindPathMap = std::map<std::string, IncFsMount::BindMap::iterator, path::PathLess>;
251
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700252 static bool perfLoggingEnabled();
253
254 std::unordered_set<std::string_view> adoptMountedInstances();
255 void mountExistingImages(const std::unordered_set<std::string_view>& mountedRootNames);
Yurii Zubrytskyi107ae352020-04-03 13:12:51 -0700256 bool mountExistingImage(std::string_view root);
Songchun Fan3c82a302019-11-29 14:23:45 -0800257
258 IfsMountPtr getIfs(StorageId storage) const;
259 const IfsMountPtr& getIfsLocked(StorageId storage) const;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800260 int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
261 std::string&& source, std::string&& target, BindKind kind,
262 std::unique_lock<std::mutex>& mainLock);
Songchun Fan3c82a302019-11-29 14:23:45 -0800263
264 int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800265 std::string&& source, std::string&& target, BindKind kind,
Songchun Fan3c82a302019-11-29 14:23:45 -0800266 std::unique_lock<std::mutex>& mainLock);
267
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700268 void addBindMountRecordLocked(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
269 std::string&& source, std::string&& target, BindKind kind);
270
271 DataLoaderStubPtr prepareDataLoader(IncFsMount& ifs,
272 content::pm::DataLoaderParamsParcel&& params,
Alex Buynytskyy0ea4ff42020-04-09 17:25:42 -0700273 const DataLoaderStatusListener* externalListener = nullptr);
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700274 void prepareDataLoaderLocked(IncFsMount& ifs, content::pm::DataLoaderParamsParcel&& params,
275 const DataLoaderStatusListener* externalListener = nullptr);
Alex Buynytskyybf1c0632020-03-10 15:49:29 -0700276
Songchun Fan3c82a302019-11-29 14:23:45 -0800277 BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
278 StorageId findStorageId(std::string_view path) const;
279
280 void deleteStorage(IncFsMount& ifs);
281 void deleteStorageLocked(IncFsMount& ifs, std::unique_lock<std::mutex>&& ifsLock);
282 MountMap::iterator getStorageSlotLocked();
Yurii Zubrytskyiefebb452020-04-22 13:59:06 -0700283 std::string normalizePathToStorage(const IncFsMount& incfs, StorageId storage,
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700284 std::string_view path) const;
Yurii Zubrytskyiefebb452020-04-22 13:59:06 -0700285 std::string normalizePathToStorageLocked(const IncFsMount& incfs,
286 IncFsMount::StorageMap::const_iterator storageIt,
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700287 std::string_view path) const;
Yurii Zubrytskyiefebb452020-04-22 13:59:06 -0700288 int makeDirs(const IncFsMount& ifs, StorageId storageId, std::string_view path, int mode);
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700289 binder::Status applyStorageParams(IncFsMount& ifs, bool enableReadLogs);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700290
291 void registerAppOpsCallback(const std::string& packageName);
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700292 bool unregisterAppOpsCallback(const std::string& packageName);
293 void onAppOpChanged(const std::string& packageName);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700294
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700295 void runJobProcessing();
296 void extractZipFile(const IfsMountPtr& ifs, ZipArchiveHandle zipFile, ZipEntry& entry,
297 const incfs::FileId& libFileId, std::string_view targetLibPath,
298 Clock::time_point scheduledTs);
299
300private:
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700301 const std::unique_ptr<VoldServiceWrapper> mVold;
302 const std::unique_ptr<DataLoaderManagerWrapper> mDataLoaderManager;
303 const std::unique_ptr<IncFsWrapper> mIncFs;
304 const std::unique_ptr<AppOpsManagerWrapper> mAppOpsManager;
305 const std::unique_ptr<JniWrapper> mJni;
Songchun Fan3c82a302019-11-29 14:23:45 -0800306 const std::string mIncrementalDir;
307
308 mutable std::mutex mLock;
309 mutable std::mutex mMountOperationLock;
310 MountMap mMounts;
311 BindPathMap mBindsByPath;
312
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700313 std::mutex mCallbacksLock;
Alex Buynytskyy1d892162020-04-03 23:00:19 -0700314 std::map<std::string, sp<AppOpsListener>> mCallbackRegistered;
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700315
Songchun Fan3c82a302019-11-29 14:23:45 -0800316 std::atomic_bool mSystemReady = false;
317 StorageId mNextId = 0;
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700318
319 using Job = std::function<void()>;
Yurii Zubrytskyi721ac4d2020-04-13 11:34:32 -0700320 std::unordered_map<MountId, std::vector<Job>> mJobQueue;
321 MountId mPendingJobsMount = kInvalidStorageId;
Yurii Zubrytskyida208012020-04-07 15:35:21 -0700322 std::condition_variable mJobCondition;
323 std::mutex mJobMutex;
324 std::thread mJobProcessor;
325 bool mRunning = true;
Songchun Fan3c82a302019-11-29 14:23:45 -0800326};
327
328} // namespace android::incremental