• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #define LOG_TAG "IncrementalService"
18 
19 #include "ServiceWrappers.h"
20 
21 #include <MountRegistry.h>
22 #include <android-base/logging.h>
23 #include <android/content/pm/IDataLoaderManager.h>
24 #include <android/os/IVold.h>
25 #include <binder/AppOpsManager.h>
26 #include <utils/String16.h>
27 
28 #include <filesystem>
29 #include <thread>
30 
31 #include "IncrementalServiceValidation.h"
32 
33 using namespace std::literals;
34 
35 namespace android::incremental {
36 
37 static constexpr auto kVoldServiceName = "vold"sv;
38 static constexpr auto kDataLoaderManagerName = "dataloader_manager"sv;
39 
40 class RealVoldService : public VoldServiceWrapper {
41 public:
RealVoldService(sp<os::IVold> vold)42     RealVoldService(sp<os::IVold> vold) : mInterface(std::move(vold)) {}
43     ~RealVoldService() = default;
mountIncFs(const std::string & backingPath,const std::string & targetDir,int32_t flags,const std::string & sysfsName,os::incremental::IncrementalFileSystemControlParcel * _aidl_return) const44     binder::Status mountIncFs(
45             const std::string& backingPath, const std::string& targetDir, int32_t flags,
46             const std::string& sysfsName,
47             os::incremental::IncrementalFileSystemControlParcel* _aidl_return) const final {
48         return mInterface->mountIncFs(backingPath, targetDir, flags, sysfsName, _aidl_return);
49     }
unmountIncFs(const std::string & dir) const50     binder::Status unmountIncFs(const std::string& dir) const final {
51         return mInterface->unmountIncFs(dir);
52     }
bindMount(const std::string & sourceDir,const std::string & targetDir) const53     binder::Status bindMount(const std::string& sourceDir,
54                              const std::string& targetDir) const final {
55         return mInterface->bindMount(sourceDir, targetDir);
56     }
setIncFsMountOptions(const::android::os::incremental::IncrementalFileSystemControlParcel & control,bool enableReadLogs,bool enableReadTimeouts,const std::string & sysfsName) const57     binder::Status setIncFsMountOptions(
58             const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
59             bool enableReadLogs, bool enableReadTimeouts,
60             const std::string& sysfsName) const final {
61         return mInterface->setIncFsMountOptions(control, enableReadLogs, enableReadTimeouts,
62                                                 sysfsName);
63     }
64 
65 private:
66     sp<os::IVold> mInterface;
67 };
68 
69 class RealDataLoaderManager : public DataLoaderManagerWrapper {
70 public:
RealDataLoaderManager(sp<content::pm::IDataLoaderManager> manager)71     RealDataLoaderManager(sp<content::pm::IDataLoaderManager> manager)
72           : mInterface(std::move(manager)) {}
73     ~RealDataLoaderManager() = default;
bindToDataLoader(MountId mountId,const content::pm::DataLoaderParamsParcel & params,int bindDelayMs,const sp<content::pm::IDataLoaderStatusListener> & listener,bool * _aidl_return) const74     binder::Status bindToDataLoader(MountId mountId,
75                                     const content::pm::DataLoaderParamsParcel& params,
76                                     int bindDelayMs,
77                                     const sp<content::pm::IDataLoaderStatusListener>& listener,
78                                     bool* _aidl_return) const final {
79         return mInterface->bindToDataLoader(mountId, params, bindDelayMs, listener, _aidl_return);
80     }
getDataLoader(MountId mountId,sp<content::pm::IDataLoader> * _aidl_return) const81     binder::Status getDataLoader(MountId mountId,
82                                  sp<content::pm::IDataLoader>* _aidl_return) const final {
83         return mInterface->getDataLoader(mountId, _aidl_return);
84     }
unbindFromDataLoader(MountId mountId) const85     binder::Status unbindFromDataLoader(MountId mountId) const final {
86         return mInterface->unbindFromDataLoader(mountId);
87     }
88 
89 private:
90     sp<content::pm::IDataLoaderManager> mInterface;
91 };
92 
93 class RealAppOpsManager : public AppOpsManagerWrapper {
94 public:
95     ~RealAppOpsManager() = default;
checkPermission(const char * permission,const char * operation,const char * package) const96     binder::Status checkPermission(const char* permission, const char* operation,
97                                    const char* package) const final {
98         return android::incremental::CheckPermissionForDataDelivery(permission, operation, package);
99     }
startWatchingMode(int32_t op,const String16 & packageName,const sp<IAppOpsCallback> & callback)100     void startWatchingMode(int32_t op, const String16& packageName,
101                            const sp<IAppOpsCallback>& callback) final {
102         mAppOpsManager.startWatchingMode(op, packageName, callback);
103     }
stopWatchingMode(const sp<IAppOpsCallback> & callback)104     void stopWatchingMode(const sp<IAppOpsCallback>& callback) final {
105         mAppOpsManager.stopWatchingMode(callback);
106     }
107 
108 private:
109     android::AppOpsManager mAppOpsManager;
110 };
111 
112 class RealJniWrapper final : public JniWrapper {
113 public:
114     RealJniWrapper(JavaVM* jvm);
115     void initializeForCurrentThread() const final;
116 
117     static JavaVM* getJvm(JNIEnv* env);
118 
119 private:
120     JavaVM* const mJvm;
121 };
122 
123 class RealLooperWrapper final : public LooperWrapper {
124 public:
addFd(int fd,int ident,int events,android::Looper_callbackFunc callback,void * data)125     int addFd(int fd, int ident, int events, android::Looper_callbackFunc callback,
126               void* data) final {
127         return mLooper.addFd(fd, ident, events, callback, data);
128     }
removeFd(int fd)129     int removeFd(int fd) final { return mLooper.removeFd(fd); }
wake()130     void wake() final { return mLooper.wake(); }
pollAll(int timeoutMillis)131     int pollAll(int timeoutMillis) final { return mLooper.pollAll(timeoutMillis); }
132 
133 private:
134     struct Looper : public android::Looper {
Looperandroid::incremental::RealLooperWrapper::Looper135         Looper() : android::Looper(/*allowNonCallbacks=*/false) {}
~Looperandroid::incremental::RealLooperWrapper::Looper136         ~Looper() {}
137     } mLooper;
138 };
139 
toString(FileId fileId)140 std::string IncFsWrapper::toString(FileId fileId) {
141     return incfs::toString(fileId);
142 }
143 
144 class RealIncFs final : public IncFsWrapper {
145 public:
146     RealIncFs() = default;
147     ~RealIncFs() final = default;
features() const148     Features features() const final { return incfs::features(); }
listExistingMounts(const ExistingMountCallback & cb) const149     void listExistingMounts(const ExistingMountCallback& cb) const final {
150         for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
151             auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
152             cb(mount.root(), mount.backingDir(), binds);
153         }
154     }
openMount(std::string_view path) const155     Control openMount(std::string_view path) const final { return incfs::open(path); }
createControl(IncFsFd cmd,IncFsFd pendingReads,IncFsFd logs,IncFsFd blocksWritten) const156     Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
157                           IncFsFd blocksWritten) const final {
158         return incfs::createControl(cmd, pendingReads, logs, blocksWritten);
159     }
makeFile(const Control & control,std::string_view path,int mode,FileId id,incfs::NewFileParams params) const160     ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
161                        incfs::NewFileParams params) const final {
162         return incfs::makeFile(control, path, mode, id, params);
163     }
makeMappedFile(const Control & control,std::string_view path,int mode,incfs::NewMappedFileParams params) const164     ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
165                              incfs::NewMappedFileParams params) const final {
166         return incfs::makeMappedFile(control, path, mode, params);
167     }
makeDir(const Control & control,std::string_view path,int mode) const168     ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
169         return incfs::makeDir(control, path, mode);
170     }
makeDirs(const Control & control,std::string_view path,int mode) const171     ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const final {
172         return incfs::makeDirs(control, path, mode);
173     }
getMetadata(const Control & control,FileId fileid) const174     incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const final {
175         return incfs::getMetadata(control, fileid);
176     }
getMetadata(const Control & control,std::string_view path) const177     incfs::RawMetadata getMetadata(const Control& control, std::string_view path) const final {
178         return incfs::getMetadata(control, path);
179     }
getFileId(const Control & control,std::string_view path) const180     FileId getFileId(const Control& control, std::string_view path) const final {
181         return incfs::getFileId(control, path);
182     }
countFilledBlocks(const Control & control,std::string_view path) const183     std::pair<IncFsBlockIndex, IncFsBlockIndex> countFilledBlocks(
184             const Control& control, std::string_view path) const final {
185         if (incfs::features() & Features::v2) {
186             const auto counts = incfs::getBlockCount(control, path);
187             if (!counts) {
188                 return {-errno, -errno};
189             }
190             return {counts->filledDataBlocks + counts->filledHashBlocks,
191                     counts->totalDataBlocks + counts->totalHashBlocks};
192         }
193         const auto fileId = incfs::getFileId(control, path);
194         const auto fd = incfs::openForSpecialOps(control, fileId);
195         int res = fd.get();
196         if (!fd.ok()) {
197             return {res, res};
198         }
199         const auto ranges = incfs::getFilledRanges(res);
200         res = ranges.first;
201         if (res) {
202             return {res, res};
203         }
204         const auto totalBlocksCount = ranges.second.internalRawRanges().endIndex;
205         int filledBlockCount = 0;
206         for (const auto& dataRange : ranges.second.dataRanges()) {
207             filledBlockCount += dataRange.size();
208         }
209         for (const auto& hashRange : ranges.second.hashRanges()) {
210             filledBlockCount += hashRange.size();
211         }
212         return {filledBlockCount, totalBlocksCount};
213     }
isFileFullyLoaded(const Control & control,std::string_view path) const214     incfs::LoadingState isFileFullyLoaded(const Control& control,
215                                           std::string_view path) const final {
216         return incfs::isFullyLoaded(control, path);
217     }
isFileFullyLoaded(const Control & control,FileId id) const218     incfs::LoadingState isFileFullyLoaded(const Control& control, FileId id) const final {
219         return incfs::isFullyLoaded(control, id);
220     }
isEverythingFullyLoaded(const Control & control) const221     incfs::LoadingState isEverythingFullyLoaded(const Control& control) const final {
222         return incfs::isEverythingFullyLoaded(control);
223     }
link(const Control & control,std::string_view from,std::string_view to) const224     ErrorCode link(const Control& control, std::string_view from, std::string_view to) const final {
225         return incfs::link(control, from, to);
226     }
unlink(const Control & control,std::string_view path) const227     ErrorCode unlink(const Control& control, std::string_view path) const final {
228         return incfs::unlink(control, path);
229     }
openForSpecialOps(const Control & control,FileId id) const230     incfs::UniqueFd openForSpecialOps(const Control& control, FileId id) const final {
231         return incfs::openForSpecialOps(control, id);
232     }
writeBlocks(std::span<const incfs::DataBlock> blocks) const233     ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
234         return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
235     }
reserveSpace(const Control & control,FileId id,IncFsSize size) const236     ErrorCode reserveSpace(const Control& control, FileId id, IncFsSize size) const final {
237         return incfs::reserveSpace(control, id, size);
238     }
waitForPendingReads(const Control & control,std::chrono::milliseconds timeout,std::vector<incfs::ReadInfoWithUid> * pendingReadsBuffer) const239     WaitResult waitForPendingReads(
240             const Control& control, std::chrono::milliseconds timeout,
241             std::vector<incfs::ReadInfoWithUid>* pendingReadsBuffer) const final {
242         return incfs::waitForPendingReads(control, timeout, pendingReadsBuffer);
243     }
setUidReadTimeouts(const Control & control,const std::vector<android::os::incremental::PerUidReadTimeouts> & perUidReadTimeouts) const244     ErrorCode setUidReadTimeouts(const Control& control,
245                                  const std::vector<android::os::incremental::PerUidReadTimeouts>&
246                                          perUidReadTimeouts) const final {
247         std::vector<incfs::UidReadTimeouts> timeouts(perUidReadTimeouts.size());
248         for (int i = 0, size = perUidReadTimeouts.size(); i < size; ++i) {
249             auto& timeout = timeouts[i];
250             const auto& perUidTimeout = perUidReadTimeouts[i];
251             timeout.uid = perUidTimeout.uid;
252             timeout.minTimeUs = perUidTimeout.minTimeUs;
253             timeout.minPendingTimeUs = perUidTimeout.minPendingTimeUs;
254             timeout.maxPendingTimeUs = perUidTimeout.maxPendingTimeUs;
255         }
256         return incfs::setUidReadTimeouts(control, timeouts);
257     }
forEachFile(const Control & control,FileCallback cb) const258     ErrorCode forEachFile(const Control& control, FileCallback cb) const final {
259         return incfs::forEachFile(control,
260                                   [&](auto& control, FileId id) { return cb(control, id); });
261     }
forEachIncompleteFile(const Control & control,FileCallback cb) const262     ErrorCode forEachIncompleteFile(const Control& control, FileCallback cb) const final {
263         return incfs::forEachIncompleteFile(control, [&](auto& control, FileId id) {
264             return cb(control, id);
265         });
266     }
getMetrics(std::string_view sysfsName) const267     std::optional<Metrics> getMetrics(std::string_view sysfsName) const final {
268         return incfs::getMetrics(sysfsName);
269     }
getLastReadError(const Control & control) const270     std::optional<LastReadError> getLastReadError(const Control& control) const final {
271         return incfs::getLastReadError(control);
272     }
273 };
274 
275 static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);
276 
277 class RealTimedQueueWrapper final : public TimedQueueWrapper {
278 public:
RealTimedQueueWrapper(JavaVM * jvm)279     RealTimedQueueWrapper(JavaVM* jvm) {
280         mThread = std::thread([this, jvm]() {
281             (void)getOrAttachJniEnv(jvm);
282             runTimers();
283         });
284     }
~RealTimedQueueWrapper()285     ~RealTimedQueueWrapper() final {
286         CHECK(!mRunning) << "call stop first";
287         CHECK(!mThread.joinable()) << "call stop first";
288     }
289 
addJob(MountId id,Milliseconds timeout,Job what)290     void addJob(MountId id, Milliseconds timeout, Job what) final {
291         const auto now = Clock::now();
292         {
293             std::unique_lock lock(mMutex);
294             mJobs.insert(TimedJob{id, now + timeout, std::move(what)});
295         }
296         mCondition.notify_all();
297     }
removeJobs(MountId id)298     void removeJobs(MountId id) final {
299         std::unique_lock lock(mMutex);
300         std::erase_if(mJobs, [id](auto&& item) { return item.id == id; });
301     }
stop()302     void stop() final {
303         {
304             std::unique_lock lock(mMutex);
305             mRunning = false;
306         }
307         mCondition.notify_all();
308         mThread.join();
309         mJobs.clear();
310     }
311 
312 private:
runTimers()313     void runTimers() {
314         static constexpr TimePoint kInfinityTs{Clock::duration::max()};
315         std::unique_lock lock(mMutex);
316         for (;;) {
317             const TimePoint nextJobTs = mJobs.empty() ? kInfinityTs : mJobs.begin()->when;
318             mCondition.wait_until(lock, nextJobTs, [this, oldNextJobTs = nextJobTs]() {
319                 const auto now = Clock::now();
320                 const auto newFirstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
321                 return newFirstJobTs <= now || newFirstJobTs < oldNextJobTs || !mRunning;
322             });
323             if (!mRunning) {
324                 return;
325             }
326 
327             const auto now = Clock::now();
328             // Always re-acquire begin(). We can't use it after unlock as mTimedJobs can change.
329             for (auto it = mJobs.begin(); it != mJobs.end() && it->when <= now;
330                  it = mJobs.begin()) {
331                 auto jobNode = mJobs.extract(it);
332 
333                 lock.unlock();
334                 jobNode.value().what();
335                 lock.lock();
336             }
337         }
338     }
339 
340     struct TimedJob {
341         MountId id;
342         TimePoint when;
343         Job what;
operator <(const TimedJob & lhs,const TimedJob & rhs)344         friend bool operator<(const TimedJob& lhs, const TimedJob& rhs) {
345             return lhs.when < rhs.when;
346         }
347     };
348     bool mRunning = true;
349     std::multiset<TimedJob> mJobs;
350     std::condition_variable mCondition;
351     std::mutex mMutex;
352     std::thread mThread;
353 };
354 
355 class RealFsWrapper final : public FsWrapper {
356 public:
357     RealFsWrapper() = default;
358     ~RealFsWrapper() = default;
359 
listFilesRecursive(std::string_view directoryPath,FileCallback onFile) const360     void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const final {
361         for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) {
362             if (!entry.is_regular_file()) {
363                 continue;
364             }
365             if (!onFile(entry.path().native())) {
366                 break;
367             }
368         }
369     }
370 };
371 
372 class RealClockWrapper final : public ClockWrapper {
373 public:
374     RealClockWrapper() = default;
375     ~RealClockWrapper() = default;
376 
now() const377     TimePoint now() const final { return Clock::now(); }
378 };
379 
RealServiceManager(sp<IServiceManager> serviceManager,JNIEnv * env)380 RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)
381       : mServiceManager(std::move(serviceManager)), mJvm(RealJniWrapper::getJvm(env)) {}
382 
383 template <class INTERFACE>
getRealService(std::string_view serviceName) const384 sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
385     sp<IBinder> binder =
386             mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
387     if (!binder) {
388         return nullptr;
389     }
390     return interface_cast<INTERFACE>(binder);
391 }
392 
getVoldService()393 std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
394     sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
395     if (vold != 0) {
396         return std::make_unique<RealVoldService>(vold);
397     }
398     return nullptr;
399 }
400 
getDataLoaderManager()401 std::unique_ptr<DataLoaderManagerWrapper> RealServiceManager::getDataLoaderManager() {
402     sp<content::pm::IDataLoaderManager> manager =
403             RealServiceManager::getRealService<content::pm::IDataLoaderManager>(
404                     kDataLoaderManagerName);
405     if (manager) {
406         return std::make_unique<RealDataLoaderManager>(manager);
407     }
408     return nullptr;
409 }
410 
getIncFs()411 std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
412     return std::make_unique<RealIncFs>();
413 }
414 
getAppOpsManager()415 std::unique_ptr<AppOpsManagerWrapper> RealServiceManager::getAppOpsManager() {
416     return std::make_unique<RealAppOpsManager>();
417 }
418 
getJni()419 std::unique_ptr<JniWrapper> RealServiceManager::getJni() {
420     return std::make_unique<RealJniWrapper>(mJvm);
421 }
422 
getLooper()423 std::unique_ptr<LooperWrapper> RealServiceManager::getLooper() {
424     return std::make_unique<RealLooperWrapper>();
425 }
426 
getTimedQueue()427 std::unique_ptr<TimedQueueWrapper> RealServiceManager::getTimedQueue() {
428     return std::make_unique<RealTimedQueueWrapper>(mJvm);
429 }
430 
getProgressUpdateJobQueue()431 std::unique_ptr<TimedQueueWrapper> RealServiceManager::getProgressUpdateJobQueue() {
432     return std::make_unique<RealTimedQueueWrapper>(mJvm);
433 }
434 
getFs()435 std::unique_ptr<FsWrapper> RealServiceManager::getFs() {
436     return std::make_unique<RealFsWrapper>();
437 }
438 
getClock()439 std::unique_ptr<ClockWrapper> RealServiceManager::getClock() {
440     return std::make_unique<RealClockWrapper>();
441 }
442 
getJavaVm(JNIEnv * env)443 static JavaVM* getJavaVm(JNIEnv* env) {
444     CHECK(env);
445     JavaVM* jvm = nullptr;
446     env->GetJavaVM(&jvm);
447     CHECK(jvm);
448     return jvm;
449 }
450 
getJniEnv(JavaVM * vm)451 static JNIEnv* getJniEnv(JavaVM* vm) {
452     JNIEnv* env;
453     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
454         return nullptr;
455     }
456     return env;
457 }
458 
getOrAttachJniEnv(JavaVM * jvm)459 static JNIEnv* getOrAttachJniEnv(JavaVM* jvm) {
460     if (!jvm) {
461         LOG(ERROR) << "No JVM instance";
462         return nullptr;
463     }
464 
465     JNIEnv* env = getJniEnv(jvm);
466     if (!env) {
467         int result = jvm->AttachCurrentThread(&env, nullptr);
468         if (result != JNI_OK) {
469             LOG(ERROR) << "JVM thread attach failed: " << result;
470             return nullptr;
471         }
472         struct VmDetacher {
473             VmDetacher(JavaVM* vm) : mVm(vm) {}
474             ~VmDetacher() { mVm->DetachCurrentThread(); }
475 
476         private:
477             JavaVM* const mVm;
478         };
479         static thread_local VmDetacher detacher(jvm);
480     }
481 
482     return env;
483 }
484 
RealJniWrapper(JavaVM * jvm)485 RealJniWrapper::RealJniWrapper(JavaVM* jvm) : mJvm(jvm) {
486     CHECK(!!mJvm) << "JVM is unavailable";
487 }
488 
initializeForCurrentThread() const489 void RealJniWrapper::initializeForCurrentThread() const {
490     (void)getOrAttachJniEnv(mJvm);
491 }
492 
getJvm(JNIEnv * env)493 JavaVM* RealJniWrapper::getJvm(JNIEnv* env) {
494     return getJavaVm(env);
495 }
496 
497 } // namespace android::incremental
498