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