blob: 1ed46c49c5e12a25a5283aa124e69f211e5e8eca [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
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070017#define LOG_TAG "IncrementalService"
18
Songchun Fan3c82a302019-11-29 14:23:45 -080019#include "ServiceWrappers.h"
20
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070021#include <MountRegistry.h>
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070022#include <android-base/logging.h>
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070023#include <android/content/pm/IDataLoaderManager.h>
24#include <android/os/IVold.h>
25#include <binder/AppOpsManager.h>
Songchun Fan3c82a302019-11-29 14:23:45 -080026#include <utils/String16.h>
27
Songchun Fan374f7652020-08-20 08:40:29 -070028#include <filesystem>
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -070029#include <thread>
30
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070031#include "IncrementalServiceValidation.h"
32
Songchun Fan3c82a302019-11-29 14:23:45 -080033using namespace std::literals;
34
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070035namespace android::incremental {
Songchun Fan3c82a302019-11-29 14:23:45 -080036
37static constexpr auto kVoldServiceName = "vold"sv;
Songchun Fan68645c42020-02-27 15:57:35 -080038static constexpr auto kDataLoaderManagerName = "dataloader_manager"sv;
Songchun Fan3c82a302019-11-29 14:23:45 -080039
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070040class RealVoldService : public VoldServiceWrapper {
41public:
Yurii Zubrytskyi510037b2020-04-22 15:46:21 -070042 RealVoldService(sp<os::IVold> vold) : mInterface(std::move(vold)) {}
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070043 ~RealVoldService() = default;
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070044 binder::Status mountIncFs(
45 const std::string& backingPath, const std::string& targetDir, int32_t flags,
46 os::incremental::IncrementalFileSystemControlParcel* _aidl_return) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070047 return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
48 }
49 binder::Status unmountIncFs(const std::string& dir) const final {
50 return mInterface->unmountIncFs(dir);
51 }
52 binder::Status bindMount(const std::string& sourceDir,
53 const std::string& targetDir) const final {
54 return mInterface->bindMount(sourceDir, targetDir);
55 }
56 binder::Status setIncFsMountOptions(
57 const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
58 bool enableReadLogs) const final {
59 return mInterface->setIncFsMountOptions(control, enableReadLogs);
60 }
61
62private:
63 sp<os::IVold> mInterface;
64};
65
66class RealDataLoaderManager : public DataLoaderManagerWrapper {
67public:
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070068 RealDataLoaderManager(sp<content::pm::IDataLoaderManager> manager)
69 : mInterface(std::move(manager)) {}
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070070 ~RealDataLoaderManager() = default;
Alex Buynytskyyea1390f2020-04-22 16:08:50 -070071 binder::Status bindToDataLoader(MountId mountId,
72 const content::pm::DataLoaderParamsParcel& params,
73 const sp<content::pm::IDataLoaderStatusListener>& listener,
74 bool* _aidl_return) const final {
75 return mInterface->bindToDataLoader(mountId, params, listener, _aidl_return);
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070076 }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070077 binder::Status getDataLoader(MountId mountId,
78 sp<content::pm::IDataLoader>* _aidl_return) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070079 return mInterface->getDataLoader(mountId, _aidl_return);
80 }
Alex Buynytskyyea1390f2020-04-22 16:08:50 -070081 binder::Status unbindFromDataLoader(MountId mountId) const final {
82 return mInterface->unbindFromDataLoader(mountId);
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070083 }
84
85private:
86 sp<content::pm::IDataLoaderManager> mInterface;
87};
88
89class RealAppOpsManager : public AppOpsManagerWrapper {
90public:
91 ~RealAppOpsManager() = default;
92 binder::Status checkPermission(const char* permission, const char* operation,
93 const char* package) const final {
94 return android::incremental::CheckPermissionForDataDelivery(permission, operation, package);
95 }
96 void startWatchingMode(int32_t op, const String16& packageName,
97 const sp<IAppOpsCallback>& callback) final {
98 mAppOpsManager.startWatchingMode(op, packageName, callback);
99 }
100 void stopWatchingMode(const sp<IAppOpsCallback>& callback) final {
101 mAppOpsManager.stopWatchingMode(callback);
102 }
103
104private:
105 android::AppOpsManager mAppOpsManager;
106};
107
108class RealJniWrapper final : public JniWrapper {
109public:
110 RealJniWrapper(JavaVM* jvm);
111 void initializeForCurrentThread() const final;
112
113 static JavaVM* getJvm(JNIEnv* env);
114
115private:
116 JavaVM* const mJvm;
117};
118
Alex Buynytskyycca2c112020-05-05 12:48:41 -0700119class RealLooperWrapper final : public LooperWrapper {
120public:
121 int addFd(int fd, int ident, int events, android::Looper_callbackFunc callback,
122 void* data) final {
123 return mLooper.addFd(fd, ident, events, callback, data);
124 }
125 int removeFd(int fd) final { return mLooper.removeFd(fd); }
126 void wake() final { return mLooper.wake(); }
127 int pollAll(int timeoutMillis) final { return mLooper.pollAll(timeoutMillis); }
128
129private:
130 struct Looper : public android::Looper {
131 Looper() : android::Looper(/*allowNonCallbacks=*/false) {}
132 ~Looper() {}
133 } mLooper;
134};
135
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700136class RealIncFs : public IncFsWrapper {
137public:
138 RealIncFs() = default;
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700139 ~RealIncFs() final = default;
140 void listExistingMounts(const ExistingMountCallback& cb) const final {
141 for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
142 auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
143 cb(mount.root(), mount.backingDir(), binds);
144 }
145 }
146 Control openMount(std::string_view path) const final { return incfs::open(path); }
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700147 Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const final {
148 return incfs::createControl(cmd, pendingReads, logs);
149 }
150 ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700151 incfs::NewFileParams params) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700152 return incfs::makeFile(control, path, mode, id, params);
153 }
154 ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
155 return incfs::makeDir(control, path, mode);
156 }
Yurii Zubrytskyiefebb452020-04-22 13:59:06 -0700157 ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const final {
158 return incfs::makeDirs(control, path, mode);
159 }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700160 incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700161 return incfs::getMetadata(control, fileid);
162 }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700163 incfs::RawMetadata getMetadata(const Control& control, std::string_view path) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700164 return incfs::getMetadata(control, path);
165 }
166 FileId getFileId(const Control& control, std::string_view path) const final {
167 return incfs::getFileId(control, path);
168 }
Songchun Fan374f7652020-08-20 08:40:29 -0700169 std::pair<IncFsBlockIndex, IncFsBlockIndex> countFilledBlocks(
170 const Control& control, std::string_view path) const final {
171 const auto fileId = incfs::getFileId(control, path);
172 const auto fd = incfs::openForSpecialOps(control, fileId);
173 int res = fd.get();
174 if (!fd.ok()) {
175 return {res, res};
176 }
177 const auto ranges = incfs::getFilledRanges(res);
178 res = ranges.first;
179 if (res) {
180 return {res, res};
181 }
182 const auto totalBlocksCount = ranges.second.internalRawRanges().endIndex;
183 int filledBlockCount = 0;
184 for (const auto& dataRange : ranges.second.dataRanges()) {
185 filledBlockCount += dataRange.size();
186 }
187 for (const auto& hashRange : ranges.second.hashRanges()) {
188 filledBlockCount += hashRange.size();
189 }
190 return {filledBlockCount, totalBlocksCount};
191 }
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700192 ErrorCode link(const Control& control, std::string_view from, std::string_view to) const final {
193 return incfs::link(control, from, to);
194 }
195 ErrorCode unlink(const Control& control, std::string_view path) const final {
196 return incfs::unlink(control, path);
197 }
198 base::unique_fd openForSpecialOps(const Control& control, FileId id) const final {
199 return base::unique_fd{incfs::openForSpecialOps(control, id).release()};
200 }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700201 ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
202 return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700203 }
Alex Buynytskyy8ef61ae2020-05-08 16:18:52 -0700204 WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
205 std::vector<incfs::ReadInfo>* pendingReadsBuffer) const final {
206 return incfs::waitForPendingReads(control, timeout, pendingReadsBuffer);
207 }
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700208};
209
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700210static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);
211
212class RealTimedQueueWrapper : public TimedQueueWrapper {
213public:
214 RealTimedQueueWrapper(JavaVM* jvm) {
215 mThread = std::thread([this, jvm]() {
216 (void)getOrAttachJniEnv(jvm);
217 runTimers();
218 });
219 }
220 ~RealTimedQueueWrapper() final {
221 CHECK(!mRunning) << "call stop first";
222 CHECK(!mThread.joinable()) << "call stop first";
223 }
224
225 void addJob(MountId id, Milliseconds after, Job what) final {
226 const auto now = Clock::now();
227 {
228 std::unique_lock lock(mMutex);
229 mJobs.insert(TimedJob{id, now + after, std::move(what)});
230 }
231 mCondition.notify_all();
232 }
233 void removeJobs(MountId id) final {
234 std::unique_lock lock(mMutex);
235 std::erase_if(mJobs, [id](auto&& item) { return item.id == id; });
236 }
237 void stop() final {
238 {
239 std::unique_lock lock(mMutex);
240 mRunning = false;
241 }
242 mCondition.notify_all();
243 mThread.join();
244 mJobs.clear();
245 }
246
247private:
248 void runTimers() {
249 static constexpr TimePoint kInfinityTs{Clock::duration::max()};
250 TimePoint nextJobTs = kInfinityTs;
251 std::unique_lock lock(mMutex);
252 for (;;) {
253 mCondition.wait_until(lock, nextJobTs, [this, nextJobTs]() {
254 const auto now = Clock::now();
255 const auto firstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
256 return !mRunning || firstJobTs <= now || firstJobTs < nextJobTs;
257 });
258 if (!mRunning) {
259 return;
260 }
261
262 const auto now = Clock::now();
263 auto it = mJobs.begin();
264 // Always acquire begin(). We can't use it after unlock as mTimedJobs can change.
265 for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) {
266 auto job = std::move(it->what);
267 mJobs.erase(it);
268
269 lock.unlock();
270 job();
271 lock.lock();
272 }
273 nextJobTs = it != mJobs.end() ? it->when : kInfinityTs;
274 }
275 }
276
277 struct TimedJob {
278 MountId id;
279 TimePoint when;
280 Job what;
281 friend bool operator<(const TimedJob& lhs, const TimedJob& rhs) {
282 return lhs.when < rhs.when;
283 }
284 };
285 bool mRunning = true;
286 std::set<TimedJob> mJobs;
287 std::condition_variable mCondition;
288 std::mutex mMutex;
289 std::thread mThread;
290};
291
Songchun Fan374f7652020-08-20 08:40:29 -0700292class RealFsWrapper : public FsWrapper {
293public:
294 RealFsWrapper() = default;
295 ~RealFsWrapper() = default;
296
297 std::vector<std::string> listFilesRecursive(std::string_view directoryPath) const final {
298 std::vector<std::string> files;
299 for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) {
300 if (!entry.is_regular_file()) {
301 continue;
302 }
303 files.push_back(entry.path().c_str());
304 }
305 return files;
306 }
307};
308
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700309RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)
310 : mServiceManager(std::move(serviceManager)), mJvm(RealJniWrapper::getJvm(env)) {}
Songchun Fan3c82a302019-11-29 14:23:45 -0800311
312template <class INTERFACE>
313sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800314 sp<IBinder> binder =
315 mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
316 if (!binder) {
317 return nullptr;
Songchun Fan3c82a302019-11-29 14:23:45 -0800318 }
319 return interface_cast<INTERFACE>(binder);
320}
321
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800322std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
Songchun Fan3c82a302019-11-29 14:23:45 -0800323 sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
324 if (vold != 0) {
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800325 return std::make_unique<RealVoldService>(vold);
Songchun Fan3c82a302019-11-29 14:23:45 -0800326 }
327 return nullptr;
328}
329
Songchun Fan68645c42020-02-27 15:57:35 -0800330std::unique_ptr<DataLoaderManagerWrapper> RealServiceManager::getDataLoaderManager() {
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700331 sp<content::pm::IDataLoaderManager> manager =
332 RealServiceManager::getRealService<content::pm::IDataLoaderManager>(
333 kDataLoaderManagerName);
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800334 if (manager) {
Songchun Fan68645c42020-02-27 15:57:35 -0800335 return std::make_unique<RealDataLoaderManager>(manager);
Songchun Fan3c82a302019-11-29 14:23:45 -0800336 }
337 return nullptr;
338}
339
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800340std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
341 return std::make_unique<RealIncFs>();
Songchun Fan3c82a302019-11-29 14:23:45 -0800342}
343
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700344std::unique_ptr<AppOpsManagerWrapper> RealServiceManager::getAppOpsManager() {
345 return std::make_unique<RealAppOpsManager>();
346}
347
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700348std::unique_ptr<JniWrapper> RealServiceManager::getJni() {
349 return std::make_unique<RealJniWrapper>(mJvm);
350}
351
Alex Buynytskyycca2c112020-05-05 12:48:41 -0700352std::unique_ptr<LooperWrapper> RealServiceManager::getLooper() {
353 return std::make_unique<RealLooperWrapper>();
354}
355
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700356std::unique_ptr<TimedQueueWrapper> RealServiceManager::getTimedQueue() {
357 return std::make_unique<RealTimedQueueWrapper>(mJvm);
358}
359
Songchun Fan374f7652020-08-20 08:40:29 -0700360std::unique_ptr<FsWrapper> RealServiceManager::getFs() {
361 return std::make_unique<RealFsWrapper>();
362}
363
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700364static JavaVM* getJavaVm(JNIEnv* env) {
365 CHECK(env);
366 JavaVM* jvm = nullptr;
367 env->GetJavaVM(&jvm);
368 CHECK(jvm);
369 return jvm;
370}
371
372static JNIEnv* getJniEnv(JavaVM* vm) {
373 JNIEnv* env;
374 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
375 return nullptr;
376 }
377 return env;
378}
379
380static JNIEnv* getOrAttachJniEnv(JavaVM* jvm) {
381 if (!jvm) {
382 LOG(ERROR) << "No JVM instance";
383 return nullptr;
384 }
385
386 JNIEnv* env = getJniEnv(jvm);
387 if (!env) {
388 int result = jvm->AttachCurrentThread(&env, nullptr);
389 if (result != JNI_OK) {
390 LOG(ERROR) << "JVM thread attach failed: " << result;
391 return nullptr;
392 }
393 struct VmDetacher {
394 VmDetacher(JavaVM* vm) : mVm(vm) {}
395 ~VmDetacher() { mVm->DetachCurrentThread(); }
396
397 private:
398 JavaVM* const mVm;
399 };
400 static thread_local VmDetacher detacher(jvm);
401 }
402
403 return env;
404}
405
406RealJniWrapper::RealJniWrapper(JavaVM* jvm) : mJvm(jvm) {
407 CHECK(!!mJvm) << "JVM is unavailable";
408}
409
410void RealJniWrapper::initializeForCurrentThread() const {
411 (void)getOrAttachJniEnv(mJvm);
412}
413
414JavaVM* RealJniWrapper::getJvm(JNIEnv* env) {
415 return getJavaVm(env);
416}
417
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700418} // namespace android::incremental