blob: ff69633e185bc6a39f29ce489774728ffdc2aa8d [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"
42#include "incfs.h"
Alex Buynytskyy96e350b2020-04-02 20:03:47 -070043#include "dataloader_ndk.h"
Songchun Fan3c82a302019-11-29 14:23:45 -080044#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 Buynytskyy04f73912020-02-10 08:34:18 -080063using DataLoaderStatusListener = ::android::sp<::android::content::pm::IDataLoaderStatusListener>;
64
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080065class IncrementalService final {
Songchun Fan3c82a302019-11-29 14:23:45 -080066public:
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080067 explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
Songchun Fan3c82a302019-11-29 14:23:45 -080068
69#pragma GCC diagnostic push
70#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
71 ~IncrementalService();
72#pragma GCC diagnostic pop
73
74 static constexpr StorageId kInvalidStorageId = -1;
75 static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max();
76
77 enum CreateOptions {
78 TemporaryBind = 1,
79 PermanentBind = 2,
80 CreateNew = 4,
81 OpenExisting = 8,
82
83 Default = TemporaryBind | CreateNew
84 };
85
86 enum class BindKind {
87 Temporary = 0,
88 Permanent = 1,
89 };
90
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -080091 static FileId idFromMetadata(std::span<const uint8_t> metadata);
92 static inline FileId idFromMetadata(std::span<const char> metadata) {
93 return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
94 }
95
Alex Buynytskyy18b07a42020-02-03 20:06:00 -080096 void onDump(int fd);
97
Songchun Fan3c82a302019-11-29 14:23:45 -080098 std::optional<std::future<void>> onSystemReady();
99
Songchun Fan9b753082020-02-26 13:08:06 -0800100 StorageId createStorage(std::string_view mountPoint, DataLoaderParamsParcel&& dataLoaderParams,
Alex Buynytskyy04f73912020-02-10 08:34:18 -0800101 const DataLoaderStatusListener& dataLoaderStatusListener,
Songchun Fan3c82a302019-11-29 14:23:45 -0800102 CreateOptions options = CreateOptions::Default);
103 StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
104 CreateOptions options = CreateOptions::Default);
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800105 StorageId openStorage(std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800106
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800107 FileId nodeFor(StorageId storage, std::string_view path) const;
108 std::pair<FileId, std::string_view> parentAndNameFor(StorageId storage,
109 std::string_view path) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800110
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800111 int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
Songchun Fan3c82a302019-11-29 14:23:45 -0800112 int unbind(StorageId storage, std::string_view target);
113 void deleteStorage(StorageId storage);
114
Alex Buynytskyy5e860ba2020-03-31 15:30:21 -0700115 int setStorageParams(StorageId storage, bool enableReadLogs);
116
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800117 int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
118 incfs::NewFileParams params);
Songchun Fan96100932020-02-03 19:20:58 -0800119 int makeDir(StorageId storage, std::string_view path, int mode = 0755);
120 int makeDirs(StorageId storage, std::string_view path, int mode = 0755);
Songchun Fan3c82a302019-11-29 14:23:45 -0800121
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800122 int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
123 std::string_view newPath);
124 int unlink(StorageId storage, std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800125
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800126 bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
Songchun Fan3c82a302019-11-29 14:23:45 -0800127 return false;
128 }
129
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800130 RawMetadata getMetadata(StorageId storage, FileId node) const;
Songchun Fan3c82a302019-11-29 14:23:45 -0800131
132 std::vector<std::string> listFiles(StorageId storage) const;
133 bool startLoading(StorageId storage) const;
Songchun Fan0f8b6fe2020-02-05 17:41:25 -0800134 bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
135 std::string_view libDirRelativePath, std::string_view abi);
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700136
Songchun Fan3c82a302019-11-29 14:23:45 -0800137 class IncrementalDataLoaderListener : public android::content::pm::BnDataLoaderStatusListener {
138 public:
Songchun Fan9b753082020-02-26 13:08:06 -0800139 IncrementalDataLoaderListener(IncrementalService& incrementalService,
140 DataLoaderStatusListener externalListener)
Alex Buynytskyy04f73912020-02-10 08:34:18 -0800141 : incrementalService(incrementalService), externalListener(externalListener) {}
Songchun Fan3c82a302019-11-29 14:23:45 -0800142 // Callbacks interface
143 binder::Status onStatusChanged(MountId mount, int newStatus) override;
144
145 private:
146 IncrementalService& incrementalService;
Alex Buynytskyy04f73912020-02-10 08:34:18 -0800147 DataLoaderStatusListener externalListener;
Songchun Fan3c82a302019-11-29 14:23:45 -0800148 };
149
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700150 class AppOpsListener : public android::BnAppOpsCallback {
151 public:
152 AppOpsListener(IncrementalService& incrementalService, std::string packageName) : incrementalService(incrementalService), packageName(std::move(packageName)) {}
153 void opChanged(int32_t op, const String16& packageName) override;
154
155 private:
156 IncrementalService& incrementalService;
157 const std::string packageName;
158 };
159
Songchun Fan3c82a302019-11-29 14:23:45 -0800160private:
161 struct IncFsMount {
162 struct Bind {
163 StorageId storage;
164 std::string savedFilename;
165 std::string sourceDir;
166 BindKind kind;
167 };
168
169 struct Storage {
170 std::string name;
Songchun Fan3c82a302019-11-29 14:23:45 -0800171 };
172
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800173 using Control = incfs::UniqueControl;
Songchun Fan3c82a302019-11-29 14:23:45 -0800174
175 using BindMap = std::map<std::string, Bind>;
176 using StorageMap = std::unordered_map<StorageId, Storage>;
177
178 mutable std::mutex lock;
179 const std::string root;
180 Control control;
181 /*const*/ MountId mountId;
182 StorageMap storages;
183 BindMap bindPoints;
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700184 DataLoaderParamsParcel dataLoaderParams;
185 DataLoaderFilesystemParams dataLoaderFilesystemParams;
Songchun Fan3c82a302019-11-29 14:23:45 -0800186 std::atomic<int> nextStorageDirNo{0};
187 std::atomic<int> dataLoaderStatus = -1;
Alex Buynytskyybf1c0632020-03-10 15:49:29 -0700188 bool dataLoaderStartRequested = false;
Songchun Fan3c82a302019-11-29 14:23:45 -0800189 const IncrementalService& incrementalService;
190
191 IncFsMount(std::string root, MountId mountId, Control control,
192 const IncrementalService& incrementalService)
193 : root(std::move(root)),
194 control(std::move(control)),
195 mountId(mountId),
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700196 incrementalService(incrementalService) {
197 dataLoaderFilesystemParams.readLogsEnabled = false;
198 }
Songchun Fan3c82a302019-11-29 14:23:45 -0800199 IncFsMount(IncFsMount&&) = delete;
200 IncFsMount& operator=(IncFsMount&&) = delete;
201 ~IncFsMount();
202
203 StorageMap::iterator makeStorage(StorageId id);
204
205 static void cleanupFilesystem(std::string_view root);
206 };
207
208 using IfsMountPtr = std::shared_ptr<IncFsMount>;
209 using MountMap = std::unordered_map<MountId, IfsMountPtr>;
210 using BindPathMap = std::map<std::string, IncFsMount::BindMap::iterator, path::PathLess>;
211
212 void mountExistingImages();
Yurii Zubrytskyi107ae352020-04-03 13:12:51 -0700213 bool mountExistingImage(std::string_view root);
Songchun Fan3c82a302019-11-29 14:23:45 -0800214
215 IfsMountPtr getIfs(StorageId storage) const;
216 const IfsMountPtr& getIfsLocked(StorageId storage) const;
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800217 int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
218 std::string&& source, std::string&& target, BindKind kind,
219 std::unique_lock<std::mutex>& mainLock);
Songchun Fan3c82a302019-11-29 14:23:45 -0800220
221 int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800222 std::string&& source, std::string&& target, BindKind kind,
Songchun Fan3c82a302019-11-29 14:23:45 -0800223 std::unique_lock<std::mutex>& mainLock);
224
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700225 bool prepareDataLoader(IncFsMount& ifs, const DataLoaderStatusListener* externalListener = nullptr);
Alex Buynytskyybf1c0632020-03-10 15:49:29 -0700226 bool startDataLoader(MountId mountId) const;
227
Songchun Fan3c82a302019-11-29 14:23:45 -0800228 BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
229 StorageId findStorageId(std::string_view path) const;
230
231 void deleteStorage(IncFsMount& ifs);
232 void deleteStorageLocked(IncFsMount& ifs, std::unique_lock<std::mutex>&& ifsLock);
233 MountMap::iterator getStorageSlotLocked();
Songchun Fan103ba1d2020-02-03 17:32:32 -0800234 std::string normalizePathToStorage(const IfsMountPtr incfs, StorageId storage,
235 std::string_view path);
Songchun Fan3c82a302019-11-29 14:23:45 -0800236
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700237 int applyStorageParams(IncFsMount& ifs);
238
239 void registerAppOpsCallback(const std::string& packageName);
240 void onAppOppChanged(const std::string& packageName);
241
Songchun Fan3c82a302019-11-29 14:23:45 -0800242 // Member variables
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700243 std::unique_ptr<VoldServiceWrapper> const mVold;
244 std::unique_ptr<DataLoaderManagerWrapper> const mDataLoaderManager;
245 std::unique_ptr<IncFsWrapper> const mIncFs;
246 std::unique_ptr<AppOpsManagerWrapper> const mAppOpsManager;
Songchun Fan3c82a302019-11-29 14:23:45 -0800247 const std::string mIncrementalDir;
248
249 mutable std::mutex mLock;
250 mutable std::mutex mMountOperationLock;
251 MountMap mMounts;
252 BindPathMap mBindsByPath;
253
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700254 std::mutex mCallbacksLock;
255 std::set<std::string> mCallbackRegistered;
256
Songchun Fan3c82a302019-11-29 14:23:45 -0800257 std::atomic_bool mSystemReady = false;
258 StorageId mNextId = 0;
259 std::promise<void> mPrepareDataLoaders;
260};
261
262} // namespace android::incremental