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 <thread>
29 
30 #include "IncrementalServiceValidation.h"
31 
32 using namespace std::literals;
33 
34 namespace android::incremental {
35 
36 static constexpr auto kVoldServiceName = "vold"sv;
37 static constexpr auto kDataLoaderManagerName = "dataloader_manager"sv;
38 
39 class RealVoldService : public VoldServiceWrapper {
40 public:
RealVoldService(sp<os::IVold> vold)41     RealVoldService(sp<os::IVold> vold) : mInterface(std::move(vold)) {}
42     ~RealVoldService() = default;
mountIncFs(const std::string & backingPath,const std::string & targetDir,int32_t flags,os::incremental::IncrementalFileSystemControlParcel * _aidl_return) const43     binder::Status mountIncFs(
44             const std::string& backingPath, const std::string& targetDir, int32_t flags,
45             os::incremental::IncrementalFileSystemControlParcel* _aidl_return) const final {
46         return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
47     }
unmountIncFs(const std::string & dir) const48     binder::Status unmountIncFs(const std::string& dir) const final {
49         return mInterface->unmountIncFs(dir);
50     }
bindMount(const std::string & sourceDir,const std::string & targetDir) const51     binder::Status bindMount(const std::string& sourceDir,
52                              const std::string& targetDir) const final {
53         return mInterface->bindMount(sourceDir, targetDir);
54     }
setIncFsMountOptions(const::android::os::incremental::IncrementalFileSystemControlParcel & control,bool enableReadLogs) const55     binder::Status setIncFsMountOptions(
56             const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
57             bool enableReadLogs) const final {
58         return mInterface->setIncFsMountOptions(control, enableReadLogs);
59     }
60 
61 private:
62     sp<os::IVold> mInterface;
63 };
64 
65 class RealDataLoaderManager : public DataLoaderManagerWrapper {
66 public:
RealDataLoaderManager(sp<content::pm::IDataLoaderManager> manager)67     RealDataLoaderManager(sp<content::pm::IDataLoaderManager> manager)
68           : mInterface(std::move(manager)) {}
69     ~RealDataLoaderManager() = default;
bindToDataLoader(MountId mountId,const content::pm::DataLoaderParamsParcel & params,const sp<content::pm::IDataLoaderStatusListener> & listener,bool * _aidl_return) const70     binder::Status bindToDataLoader(MountId mountId,
71                                     const content::pm::DataLoaderParamsParcel& params,
72                                     const sp<content::pm::IDataLoaderStatusListener>& listener,
73                                     bool* _aidl_return) const final {
74         return mInterface->bindToDataLoader(mountId, params, listener, _aidl_return);
75     }
getDataLoader(MountId mountId,sp<content::pm::IDataLoader> * _aidl_return) const76     binder::Status getDataLoader(MountId mountId,
77                                  sp<content::pm::IDataLoader>* _aidl_return) const final {
78         return mInterface->getDataLoader(mountId, _aidl_return);
79     }
unbindFromDataLoader(MountId mountId) const80     binder::Status unbindFromDataLoader(MountId mountId) const final {
81         return mInterface->unbindFromDataLoader(mountId);
82     }
83 
84 private:
85     sp<content::pm::IDataLoaderManager> mInterface;
86 };
87 
88 class RealAppOpsManager : public AppOpsManagerWrapper {
89 public:
90     ~RealAppOpsManager() = default;
checkPermission(const char * permission,const char * operation,const char * package) const91     binder::Status checkPermission(const char* permission, const char* operation,
92                                    const char* package) const final {
93         return android::incremental::CheckPermissionForDataDelivery(permission, operation, package);
94     }
startWatchingMode(int32_t op,const String16 & packageName,const sp<IAppOpsCallback> & callback)95     void startWatchingMode(int32_t op, const String16& packageName,
96                            const sp<IAppOpsCallback>& callback) final {
97         mAppOpsManager.startWatchingMode(op, packageName, callback);
98     }
stopWatchingMode(const sp<IAppOpsCallback> & callback)99     void stopWatchingMode(const sp<IAppOpsCallback>& callback) final {
100         mAppOpsManager.stopWatchingMode(callback);
101     }
102 
103 private:
104     android::AppOpsManager mAppOpsManager;
105 };
106 
107 class RealJniWrapper final : public JniWrapper {
108 public:
109     RealJniWrapper(JavaVM* jvm);
110     void initializeForCurrentThread() const final;
111 
112     static JavaVM* getJvm(JNIEnv* env);
113 
114 private:
115     JavaVM* const mJvm;
116 };
117 
118 class RealLooperWrapper final : public LooperWrapper {
119 public:
addFd(int fd,int ident,int events,android::Looper_callbackFunc callback,void * data)120     int addFd(int fd, int ident, int events, android::Looper_callbackFunc callback,
121               void* data) final {
122         return mLooper.addFd(fd, ident, events, callback, data);
123     }
removeFd(int fd)124     int removeFd(int fd) final { return mLooper.removeFd(fd); }
wake()125     void wake() final { return mLooper.wake(); }
pollAll(int timeoutMillis)126     int pollAll(int timeoutMillis) final { return mLooper.pollAll(timeoutMillis); }
127 
128 private:
129     struct Looper : public android::Looper {
Looperandroid::incremental::RealLooperWrapper::Looper130         Looper() : android::Looper(/*allowNonCallbacks=*/false) {}
~Looperandroid::incremental::RealLooperWrapper::Looper131         ~Looper() {}
132     } mLooper;
133 };
134 
135 class RealIncFs : public IncFsWrapper {
136 public:
137     RealIncFs() = default;
138     ~RealIncFs() final = default;
listExistingMounts(const ExistingMountCallback & cb) const139     void listExistingMounts(const ExistingMountCallback& cb) const final {
140         for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
141             auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
142             cb(mount.root(), mount.backingDir(), binds);
143         }
144     }
openMount(std::string_view path) const145     Control openMount(std::string_view path) const final { return incfs::open(path); }
createControl(IncFsFd cmd,IncFsFd pendingReads,IncFsFd logs) const146     Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const final {
147         return incfs::createControl(cmd, pendingReads, logs);
148     }
makeFile(const Control & control,std::string_view path,int mode,FileId id,incfs::NewFileParams params) const149     ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
150                        incfs::NewFileParams params) const final {
151         return incfs::makeFile(control, path, mode, id, params);
152     }
makeDir(const Control & control,std::string_view path,int mode) const153     ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
154         return incfs::makeDir(control, path, mode);
155     }
makeDirs(const Control & control,std::string_view path,int mode) const156     ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const final {
157         return incfs::makeDirs(control, path, mode);
158     }
getMetadata(const Control & control,FileId fileid) const159     incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const final {
160         return incfs::getMetadata(control, fileid);
161     }
getMetadata(const Control & control,std::string_view path) const162     incfs::RawMetadata getMetadata(const Control& control, std::string_view path) const final {
163         return incfs::getMetadata(control, path);
164     }
getFileId(const Control & control,std::string_view path) const165     FileId getFileId(const Control& control, std::string_view path) const final {
166         return incfs::getFileId(control, path);
167     }
link(const Control & control,std::string_view from,std::string_view to) const168     ErrorCode link(const Control& control, std::string_view from, std::string_view to) const final {
169         return incfs::link(control, from, to);
170     }
unlink(const Control & control,std::string_view path) const171     ErrorCode unlink(const Control& control, std::string_view path) const final {
172         return incfs::unlink(control, path);
173     }
openForSpecialOps(const Control & control,FileId id) const174     base::unique_fd openForSpecialOps(const Control& control, FileId id) const final {
175         return base::unique_fd{incfs::openForSpecialOps(control, id).release()};
176     }
writeBlocks(std::span<const incfs::DataBlock> blocks) const177     ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
178         return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
179     }
waitForPendingReads(const Control & control,std::chrono::milliseconds timeout,std::vector<incfs::ReadInfo> * pendingReadsBuffer) const180     WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
181                                    std::vector<incfs::ReadInfo>* pendingReadsBuffer) const final {
182         return incfs::waitForPendingReads(control, timeout, pendingReadsBuffer);
183     }
184 };
185 
186 static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);
187 
188 class RealTimedQueueWrapper : public TimedQueueWrapper {
189 public:
RealTimedQueueWrapper(JavaVM * jvm)190     RealTimedQueueWrapper(JavaVM* jvm) {
191         mThread = std::thread([this, jvm]() {
192             (void)getOrAttachJniEnv(jvm);
193             runTimers();
194         });
195     }
~RealTimedQueueWrapper()196     ~RealTimedQueueWrapper() final {
197         CHECK(!mRunning) << "call stop first";
198         CHECK(!mThread.joinable()) << "call stop first";
199     }
200 
addJob(MountId id,Milliseconds after,Job what)201     void addJob(MountId id, Milliseconds after, Job what) final {
202         const auto now = Clock::now();
203         {
204             std::unique_lock lock(mMutex);
205             mJobs.insert(TimedJob{id, now + after, std::move(what)});
206         }
207         mCondition.notify_all();
208     }
removeJobs(MountId id)209     void removeJobs(MountId id) final {
210         std::unique_lock lock(mMutex);
211         std::erase_if(mJobs, [id](auto&& item) { return item.id == id; });
212     }
stop()213     void stop() final {
214         {
215             std::unique_lock lock(mMutex);
216             mRunning = false;
217         }
218         mCondition.notify_all();
219         mThread.join();
220         mJobs.clear();
221     }
222 
223 private:
runTimers()224     void runTimers() {
225         static constexpr TimePoint kInfinityTs{Clock::duration::max()};
226         TimePoint nextJobTs = kInfinityTs;
227         std::unique_lock lock(mMutex);
228         for (;;) {
229             mCondition.wait_until(lock, nextJobTs, [this, nextJobTs]() {
230                 const auto now = Clock::now();
231                 const auto firstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
232                 return !mRunning || firstJobTs <= now || firstJobTs < nextJobTs;
233             });
234             if (!mRunning) {
235                 return;
236             }
237 
238             const auto now = Clock::now();
239             auto it = mJobs.begin();
240             // Always acquire begin(). We can't use it after unlock as mTimedJobs can change.
241             for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) {
242                 auto job = std::move(it->what);
243                 mJobs.erase(it);
244 
245                 lock.unlock();
246                 job();
247                 lock.lock();
248             }
249             nextJobTs = it != mJobs.end() ? it->when : kInfinityTs;
250         }
251     }
252 
253     struct TimedJob {
254         MountId id;
255         TimePoint when;
256         Job what;
operator <(const TimedJob & lhs,const TimedJob & rhs)257         friend bool operator<(const TimedJob& lhs, const TimedJob& rhs) {
258             return lhs.when < rhs.when;
259         }
260     };
261     bool mRunning = true;
262     std::set<TimedJob> mJobs;
263     std::condition_variable mCondition;
264     std::mutex mMutex;
265     std::thread mThread;
266 };
267 
RealServiceManager(sp<IServiceManager> serviceManager,JNIEnv * env)268 RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)
269       : mServiceManager(std::move(serviceManager)), mJvm(RealJniWrapper::getJvm(env)) {}
270 
271 template <class INTERFACE>
getRealService(std::string_view serviceName) const272 sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
273     sp<IBinder> binder =
274             mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
275     if (!binder) {
276         return nullptr;
277     }
278     return interface_cast<INTERFACE>(binder);
279 }
280 
getVoldService()281 std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
282     sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
283     if (vold != 0) {
284         return std::make_unique<RealVoldService>(vold);
285     }
286     return nullptr;
287 }
288 
getDataLoaderManager()289 std::unique_ptr<DataLoaderManagerWrapper> RealServiceManager::getDataLoaderManager() {
290     sp<content::pm::IDataLoaderManager> manager =
291             RealServiceManager::getRealService<content::pm::IDataLoaderManager>(
292                     kDataLoaderManagerName);
293     if (manager) {
294         return std::make_unique<RealDataLoaderManager>(manager);
295     }
296     return nullptr;
297 }
298 
getIncFs()299 std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
300     return std::make_unique<RealIncFs>();
301 }
302 
getAppOpsManager()303 std::unique_ptr<AppOpsManagerWrapper> RealServiceManager::getAppOpsManager() {
304     return std::make_unique<RealAppOpsManager>();
305 }
306 
getJni()307 std::unique_ptr<JniWrapper> RealServiceManager::getJni() {
308     return std::make_unique<RealJniWrapper>(mJvm);
309 }
310 
getLooper()311 std::unique_ptr<LooperWrapper> RealServiceManager::getLooper() {
312     return std::make_unique<RealLooperWrapper>();
313 }
314 
getTimedQueue()315 std::unique_ptr<TimedQueueWrapper> RealServiceManager::getTimedQueue() {
316     return std::make_unique<RealTimedQueueWrapper>(mJvm);
317 }
318 
getJavaVm(JNIEnv * env)319 static JavaVM* getJavaVm(JNIEnv* env) {
320     CHECK(env);
321     JavaVM* jvm = nullptr;
322     env->GetJavaVM(&jvm);
323     CHECK(jvm);
324     return jvm;
325 }
326 
getJniEnv(JavaVM * vm)327 static JNIEnv* getJniEnv(JavaVM* vm) {
328     JNIEnv* env;
329     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
330         return nullptr;
331     }
332     return env;
333 }
334 
getOrAttachJniEnv(JavaVM * jvm)335 static JNIEnv* getOrAttachJniEnv(JavaVM* jvm) {
336     if (!jvm) {
337         LOG(ERROR) << "No JVM instance";
338         return nullptr;
339     }
340 
341     JNIEnv* env = getJniEnv(jvm);
342     if (!env) {
343         int result = jvm->AttachCurrentThread(&env, nullptr);
344         if (result != JNI_OK) {
345             LOG(ERROR) << "JVM thread attach failed: " << result;
346             return nullptr;
347         }
348         struct VmDetacher {
349             VmDetacher(JavaVM* vm) : mVm(vm) {}
350             ~VmDetacher() { mVm->DetachCurrentThread(); }
351 
352         private:
353             JavaVM* const mVm;
354         };
355         static thread_local VmDetacher detacher(jvm);
356     }
357 
358     return env;
359 }
360 
RealJniWrapper(JavaVM * jvm)361 RealJniWrapper::RealJniWrapper(JavaVM* jvm) : mJvm(jvm) {
362     CHECK(!!mJvm) << "JVM is unavailable";
363 }
364 
initializeForCurrentThread() const365 void RealJniWrapper::initializeForCurrentThread() const {
366     (void)getOrAttachJniEnv(mJvm);
367 }
368 
getJvm(JNIEnv * env)369 JavaVM* RealJniWrapper::getJvm(JNIEnv* env) {
370     return getJavaVm(env);
371 }
372 
373 } // namespace android::incremental
374