blob: 68a28b25b2a443aac44e4e2619f38876a9735fd2 [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,
Songchun Fanf949c372021-04-27 11:26:25 -070046 const std::string& sysfsName,
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070047 os::incremental::IncrementalFileSystemControlParcel* _aidl_return) const final {
Songchun Fanf949c372021-04-27 11:26:25 -070048 return mInterface->mountIncFs(backingPath, targetDir, flags, sysfsName, _aidl_return);
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070049 }
50 binder::Status unmountIncFs(const std::string& dir) const final {
51 return mInterface->unmountIncFs(dir);
52 }
53 binder::Status bindMount(const std::string& sourceDir,
54 const std::string& targetDir) const final {
55 return mInterface->bindMount(sourceDir, targetDir);
56 }
57 binder::Status setIncFsMountOptions(
58 const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
Alex Buynytskyyc144cc42021-03-31 22:19:42 -070059 bool enableReadLogs, bool enableReadTimeouts) const final {
60 return mInterface->setIncFsMountOptions(control, enableReadLogs, enableReadTimeouts);
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070061 }
62
63private:
64 sp<os::IVold> mInterface;
65};
66
67class RealDataLoaderManager : public DataLoaderManagerWrapper {
68public:
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070069 RealDataLoaderManager(sp<content::pm::IDataLoaderManager> manager)
70 : mInterface(std::move(manager)) {}
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070071 ~RealDataLoaderManager() = default;
Alex Buynytskyyea1390f2020-04-22 16:08:50 -070072 binder::Status bindToDataLoader(MountId mountId,
73 const content::pm::DataLoaderParamsParcel& params,
Alex Buynytskyyb19ee3e2021-02-06 20:31:43 -080074 int bindDelayMs,
Alex Buynytskyyea1390f2020-04-22 16:08:50 -070075 const sp<content::pm::IDataLoaderStatusListener>& listener,
76 bool* _aidl_return) const final {
Alex Buynytskyyb19ee3e2021-02-06 20:31:43 -080077 return mInterface->bindToDataLoader(mountId, params, bindDelayMs, listener, _aidl_return);
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070078 }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -070079 binder::Status getDataLoader(MountId mountId,
80 sp<content::pm::IDataLoader>* _aidl_return) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070081 return mInterface->getDataLoader(mountId, _aidl_return);
82 }
Alex Buynytskyyea1390f2020-04-22 16:08:50 -070083 binder::Status unbindFromDataLoader(MountId mountId) const final {
84 return mInterface->unbindFromDataLoader(mountId);
Yurii Zubrytskyi86321402020-04-09 19:22:30 -070085 }
86
87private:
88 sp<content::pm::IDataLoaderManager> mInterface;
89};
90
91class RealAppOpsManager : public AppOpsManagerWrapper {
92public:
93 ~RealAppOpsManager() = default;
94 binder::Status checkPermission(const char* permission, const char* operation,
95 const char* package) const final {
96 return android::incremental::CheckPermissionForDataDelivery(permission, operation, package);
97 }
98 void startWatchingMode(int32_t op, const String16& packageName,
99 const sp<IAppOpsCallback>& callback) final {
100 mAppOpsManager.startWatchingMode(op, packageName, callback);
101 }
102 void stopWatchingMode(const sp<IAppOpsCallback>& callback) final {
103 mAppOpsManager.stopWatchingMode(callback);
104 }
105
106private:
107 android::AppOpsManager mAppOpsManager;
108};
109
110class RealJniWrapper final : public JniWrapper {
111public:
112 RealJniWrapper(JavaVM* jvm);
113 void initializeForCurrentThread() const final;
114
115 static JavaVM* getJvm(JNIEnv* env);
116
117private:
118 JavaVM* const mJvm;
119};
120
Alex Buynytskyycca2c112020-05-05 12:48:41 -0700121class RealLooperWrapper final : public LooperWrapper {
122public:
123 int addFd(int fd, int ident, int events, android::Looper_callbackFunc callback,
124 void* data) final {
125 return mLooper.addFd(fd, ident, events, callback, data);
126 }
127 int removeFd(int fd) final { return mLooper.removeFd(fd); }
128 void wake() final { return mLooper.wake(); }
129 int pollAll(int timeoutMillis) final { return mLooper.pollAll(timeoutMillis); }
130
131private:
132 struct Looper : public android::Looper {
133 Looper() : android::Looper(/*allowNonCallbacks=*/false) {}
134 ~Looper() {}
135 } mLooper;
136};
137
Yurii Zubrytskyi4375a742021-03-18 16:59:47 -0700138std::string IncFsWrapper::toString(FileId fileId) {
139 return incfs::toString(fileId);
140}
141
Yurii Zubrytskyia5946f72021-02-17 14:24:14 -0800142class RealIncFs final : public IncFsWrapper {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700143public:
144 RealIncFs() = default;
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700145 ~RealIncFs() final = default;
Yurii Zubrytskyia5946f72021-02-17 14:24:14 -0800146 Features features() const final { return incfs::features(); }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700147 void listExistingMounts(const ExistingMountCallback& cb) const final {
148 for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
149 auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
150 cb(mount.root(), mount.backingDir(), binds);
151 }
152 }
153 Control openMount(std::string_view path) const final { return incfs::open(path); }
Yurii Zubrytskyi5f692922020-12-08 07:35:24 -0800154 Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
155 IncFsFd blocksWritten) const final {
156 return incfs::createControl(cmd, pendingReads, logs, blocksWritten);
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700157 }
158 ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700159 incfs::NewFileParams params) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700160 return incfs::makeFile(control, path, mode, id, params);
161 }
Yurii Zubrytskyia5946f72021-02-17 14:24:14 -0800162 ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
163 incfs::NewMappedFileParams params) const final {
164 return incfs::makeMappedFile(control, path, mode, params);
165 }
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700166 ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
167 return incfs::makeDir(control, path, mode);
168 }
Yurii Zubrytskyiefebb452020-04-22 13:59:06 -0700169 ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const final {
170 return incfs::makeDirs(control, path, mode);
171 }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700172 incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700173 return incfs::getMetadata(control, fileid);
174 }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700175 incfs::RawMetadata getMetadata(const Control& control, std::string_view path) const final {
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700176 return incfs::getMetadata(control, path);
177 }
178 FileId getFileId(const Control& control, std::string_view path) const final {
179 return incfs::getFileId(control, path);
180 }
Songchun Fan374f7652020-08-20 08:40:29 -0700181 std::pair<IncFsBlockIndex, IncFsBlockIndex> countFilledBlocks(
182 const Control& control, std::string_view path) const final {
Yurii Zubrytskyi4375a742021-03-18 16:59:47 -0700183 if (incfs::features() & Features::v2) {
184 const auto counts = incfs::getBlockCount(control, path);
185 if (!counts) {
186 return {-errno, -errno};
187 }
188 return {counts->filledDataBlocks + counts->filledHashBlocks,
189 counts->totalDataBlocks + counts->totalHashBlocks};
190 }
Songchun Fan374f7652020-08-20 08:40:29 -0700191 const auto fileId = incfs::getFileId(control, path);
192 const auto fd = incfs::openForSpecialOps(control, fileId);
193 int res = fd.get();
194 if (!fd.ok()) {
195 return {res, res};
196 }
197 const auto ranges = incfs::getFilledRanges(res);
198 res = ranges.first;
199 if (res) {
200 return {res, res};
201 }
202 const auto totalBlocksCount = ranges.second.internalRawRanges().endIndex;
203 int filledBlockCount = 0;
204 for (const auto& dataRange : ranges.second.dataRanges()) {
205 filledBlockCount += dataRange.size();
206 }
207 for (const auto& hashRange : ranges.second.hashRanges()) {
208 filledBlockCount += hashRange.size();
209 }
210 return {filledBlockCount, totalBlocksCount};
211 }
Yurii Zubrytskyi256a1a42021-03-18 14:21:54 -0700212 incfs::LoadingState isFileFullyLoaded(const Control& control,
213 std::string_view path) const final {
214 return incfs::isFullyLoaded(control, path);
215 }
Yurii Zubrytskyi4cd24922021-03-24 00:46:29 -0700216 incfs::LoadingState isFileFullyLoaded(const Control& control, FileId id) const final {
217 return incfs::isFullyLoaded(control, id);
218 }
Yurii Zubrytskyi256a1a42021-03-18 14:21:54 -0700219 incfs::LoadingState isEverythingFullyLoaded(const Control& control) const final {
220 return incfs::isEverythingFullyLoaded(control);
221 }
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700222 ErrorCode link(const Control& control, std::string_view from, std::string_view to) const final {
223 return incfs::link(control, from, to);
224 }
225 ErrorCode unlink(const Control& control, std::string_view path) const final {
226 return incfs::unlink(control, path);
227 }
Alex Buynytskyybc0a7e62020-08-25 12:45:22 -0700228 incfs::UniqueFd openForSpecialOps(const Control& control, FileId id) const final {
229 return incfs::openForSpecialOps(control, id);
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700230 }
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700231 ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
232 return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700233 }
Yurii Zubrytskyi4cd24922021-03-24 00:46:29 -0700234 ErrorCode reserveSpace(const Control& control, FileId id, IncFsSize size) const final {
235 return incfs::reserveSpace(control, id, size);
Yurii Zubrytskyi65fc38a2021-03-17 13:18:30 -0700236 }
Alex Buynytskyyc144cc42021-03-31 22:19:42 -0700237 WaitResult waitForPendingReads(
238 const Control& control, std::chrono::milliseconds timeout,
239 std::vector<incfs::ReadInfoWithUid>* pendingReadsBuffer) const final {
Alex Buynytskyy8ef61ae2020-05-08 16:18:52 -0700240 return incfs::waitForPendingReads(control, timeout, pendingReadsBuffer);
241 }
Alex Buynytskyyaa8e95e2020-12-14 21:50:04 -0800242 ErrorCode setUidReadTimeouts(const Control& control,
243 const std::vector<android::os::incremental::PerUidReadTimeouts>&
244 perUidReadTimeouts) const final {
Yurii Zubrytskyi4cd24922021-03-24 00:46:29 -0700245 std::vector<incfs::UidReadTimeouts> timeouts(perUidReadTimeouts.size());
Alex Buynytskyyfe6b4c02021-01-26 13:29:24 -0800246 for (int i = 0, size = perUidReadTimeouts.size(); i < size; ++i) {
Yurii Zubrytskyi4cd24922021-03-24 00:46:29 -0700247 auto& timeout = timeouts[i];
Alex Buynytskyyfe6b4c02021-01-26 13:29:24 -0800248 const auto& perUidTimeout = perUidReadTimeouts[i];
249 timeout.uid = perUidTimeout.uid;
250 timeout.minTimeUs = perUidTimeout.minTimeUs;
251 timeout.minPendingTimeUs = perUidTimeout.minPendingTimeUs;
252 timeout.maxPendingTimeUs = perUidTimeout.maxPendingTimeUs;
253 }
254 return incfs::setUidReadTimeouts(control, timeouts);
Alex Buynytskyyaa8e95e2020-12-14 21:50:04 -0800255 }
Yurii Zubrytskyi4cd24922021-03-24 00:46:29 -0700256 ErrorCode forEachFile(const Control& control, FileCallback cb) const final {
257 return incfs::forEachFile(control,
258 [&](auto& control, FileId id) { return cb(control, id); });
259 }
260 ErrorCode forEachIncompleteFile(const Control& control, FileCallback cb) const final {
261 return incfs::forEachIncompleteFile(control, [&](auto& control, FileId id) {
262 return cb(control, id);
263 });
264 }
Songchun Fanf949c372021-04-27 11:26:25 -0700265 std::optional<Metrics> getMetrics(std::string_view sysfsName) const final {
266 return incfs::getMetrics(sysfsName);
267 }
Songchun Fand48a25e2021-04-30 09:50:58 -0700268 std::optional<LastReadError> getLastReadError(const Control& control) const final {
269 return incfs::getLastReadError(control);
270 }
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700271};
272
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700273static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);
274
Yurii Zubrytskyi0583e7f2021-03-19 17:00:12 -0700275class RealTimedQueueWrapper final : public TimedQueueWrapper {
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700276public:
277 RealTimedQueueWrapper(JavaVM* jvm) {
278 mThread = std::thread([this, jvm]() {
279 (void)getOrAttachJniEnv(jvm);
280 runTimers();
281 });
282 }
283 ~RealTimedQueueWrapper() final {
284 CHECK(!mRunning) << "call stop first";
285 CHECK(!mThread.joinable()) << "call stop first";
286 }
287
Yurii Zubrytskyi0583e7f2021-03-19 17:00:12 -0700288 void addJob(MountId id, Milliseconds timeout, Job what) final {
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700289 const auto now = Clock::now();
290 {
291 std::unique_lock lock(mMutex);
Yurii Zubrytskyi0583e7f2021-03-19 17:00:12 -0700292 mJobs.insert(TimedJob{id, now + timeout, std::move(what)});
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700293 }
294 mCondition.notify_all();
295 }
296 void removeJobs(MountId id) final {
297 std::unique_lock lock(mMutex);
298 std::erase_if(mJobs, [id](auto&& item) { return item.id == id; });
299 }
300 void stop() final {
301 {
302 std::unique_lock lock(mMutex);
303 mRunning = false;
304 }
305 mCondition.notify_all();
306 mThread.join();
307 mJobs.clear();
308 }
309
310private:
311 void runTimers() {
312 static constexpr TimePoint kInfinityTs{Clock::duration::max()};
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700313 std::unique_lock lock(mMutex);
314 for (;;) {
Yurii Zubrytskyi0583e7f2021-03-19 17:00:12 -0700315 const TimePoint nextJobTs = mJobs.empty() ? kInfinityTs : mJobs.begin()->when;
316 mCondition.wait_until(lock, nextJobTs, [this, oldNextJobTs = nextJobTs]() {
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700317 const auto now = Clock::now();
Yurii Zubrytskyi0583e7f2021-03-19 17:00:12 -0700318 const auto newFirstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
319 return newFirstJobTs <= now || newFirstJobTs < oldNextJobTs || !mRunning;
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700320 });
321 if (!mRunning) {
322 return;
323 }
324
325 const auto now = Clock::now();
Yurii Zubrytskyi0583e7f2021-03-19 17:00:12 -0700326 // Always re-acquire begin(). We can't use it after unlock as mTimedJobs can change.
327 for (auto it = mJobs.begin(); it != mJobs.end() && it->when <= now;
328 it = mJobs.begin()) {
Yurii Zubrytskyi3fde5722021-02-19 00:08:36 -0800329 auto jobNode = mJobs.extract(it);
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700330
331 lock.unlock();
Yurii Zubrytskyi3fde5722021-02-19 00:08:36 -0800332 jobNode.value().what();
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700333 lock.lock();
334 }
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700335 }
336 }
337
338 struct TimedJob {
339 MountId id;
340 TimePoint when;
341 Job what;
342 friend bool operator<(const TimedJob& lhs, const TimedJob& rhs) {
343 return lhs.when < rhs.when;
344 }
345 };
346 bool mRunning = true;
Yurii Zubrytskyi0583e7f2021-03-19 17:00:12 -0700347 std::multiset<TimedJob> mJobs;
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700348 std::condition_variable mCondition;
349 std::mutex mMutex;
350 std::thread mThread;
351};
352
Yurii Zubrytskyi3fde5722021-02-19 00:08:36 -0800353class RealFsWrapper final : public FsWrapper {
Songchun Fan374f7652020-08-20 08:40:29 -0700354public:
355 RealFsWrapper() = default;
356 ~RealFsWrapper() = default;
357
Yurii Zubrytskyi3fde5722021-02-19 00:08:36 -0800358 void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const final {
Songchun Fan374f7652020-08-20 08:40:29 -0700359 for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) {
360 if (!entry.is_regular_file()) {
361 continue;
362 }
Yurii Zubrytskyi3fde5722021-02-19 00:08:36 -0800363 if (!onFile(entry.path().native())) {
364 break;
365 }
Songchun Fan374f7652020-08-20 08:40:29 -0700366 }
Songchun Fan374f7652020-08-20 08:40:29 -0700367 }
368};
369
Alex Buynytskyy7e06d712021-03-09 19:24:23 -0800370class RealClockWrapper final : public ClockWrapper {
371public:
372 RealClockWrapper() = default;
373 ~RealClockWrapper() = default;
374
375 TimePoint now() const final { return Clock::now(); }
376};
377
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700378RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)
379 : mServiceManager(std::move(serviceManager)), mJvm(RealJniWrapper::getJvm(env)) {}
Songchun Fan3c82a302019-11-29 14:23:45 -0800380
381template <class INTERFACE>
382sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800383 sp<IBinder> binder =
384 mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
385 if (!binder) {
386 return nullptr;
Songchun Fan3c82a302019-11-29 14:23:45 -0800387 }
388 return interface_cast<INTERFACE>(binder);
389}
390
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800391std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
Songchun Fan3c82a302019-11-29 14:23:45 -0800392 sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
393 if (vold != 0) {
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800394 return std::make_unique<RealVoldService>(vold);
Songchun Fan3c82a302019-11-29 14:23:45 -0800395 }
396 return nullptr;
397}
398
Songchun Fan68645c42020-02-27 15:57:35 -0800399std::unique_ptr<DataLoaderManagerWrapper> RealServiceManager::getDataLoaderManager() {
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700400 sp<content::pm::IDataLoaderManager> manager =
401 RealServiceManager::getRealService<content::pm::IDataLoaderManager>(
402 kDataLoaderManagerName);
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800403 if (manager) {
Songchun Fan68645c42020-02-27 15:57:35 -0800404 return std::make_unique<RealDataLoaderManager>(manager);
Songchun Fan3c82a302019-11-29 14:23:45 -0800405 }
406 return nullptr;
407}
408
Yurii Zubrytskyi4a25dfb2020-01-10 11:53:24 -0800409std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
410 return std::make_unique<RealIncFs>();
Songchun Fan3c82a302019-11-29 14:23:45 -0800411}
412
Alex Buynytskyy96e350b2020-04-02 20:03:47 -0700413std::unique_ptr<AppOpsManagerWrapper> RealServiceManager::getAppOpsManager() {
414 return std::make_unique<RealAppOpsManager>();
415}
416
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700417std::unique_ptr<JniWrapper> RealServiceManager::getJni() {
418 return std::make_unique<RealJniWrapper>(mJvm);
419}
420
Alex Buynytskyycca2c112020-05-05 12:48:41 -0700421std::unique_ptr<LooperWrapper> RealServiceManager::getLooper() {
422 return std::make_unique<RealLooperWrapper>();
423}
424
Alex Buynytskyy46d3ddb2020-05-29 12:05:05 -0700425std::unique_ptr<TimedQueueWrapper> RealServiceManager::getTimedQueue() {
426 return std::make_unique<RealTimedQueueWrapper>(mJvm);
427}
428
Songchun Fana7098592020-09-03 11:45:53 -0700429std::unique_ptr<TimedQueueWrapper> RealServiceManager::getProgressUpdateJobQueue() {
430 return std::make_unique<RealTimedQueueWrapper>(mJvm);
431}
432
Songchun Fan374f7652020-08-20 08:40:29 -0700433std::unique_ptr<FsWrapper> RealServiceManager::getFs() {
434 return std::make_unique<RealFsWrapper>();
435}
436
Alex Buynytskyy7e06d712021-03-09 19:24:23 -0800437std::unique_ptr<ClockWrapper> RealServiceManager::getClock() {
438 return std::make_unique<RealClockWrapper>();
439}
440
Yurii Zubrytskyi86321402020-04-09 19:22:30 -0700441static JavaVM* getJavaVm(JNIEnv* env) {
442 CHECK(env);
443 JavaVM* jvm = nullptr;
444 env->GetJavaVM(&jvm);
445 CHECK(jvm);
446 return jvm;
447}
448
449static JNIEnv* getJniEnv(JavaVM* vm) {
450 JNIEnv* env;
451 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
452 return nullptr;
453 }
454 return env;
455}
456
457static JNIEnv* getOrAttachJniEnv(JavaVM* jvm) {
458 if (!jvm) {
459 LOG(ERROR) << "No JVM instance";
460 return nullptr;
461 }
462
463 JNIEnv* env = getJniEnv(jvm);
464 if (!env) {
465 int result = jvm->AttachCurrentThread(&env, nullptr);
466 if (result != JNI_OK) {
467 LOG(ERROR) << "JVM thread attach failed: " << result;
468 return nullptr;
469 }
470 struct VmDetacher {
471 VmDetacher(JavaVM* vm) : mVm(vm) {}
472 ~VmDetacher() { mVm->DetachCurrentThread(); }
473
474 private:
475 JavaVM* const mVm;
476 };
477 static thread_local VmDetacher detacher(jvm);
478 }
479
480 return env;
481}
482
483RealJniWrapper::RealJniWrapper(JavaVM* jvm) : mJvm(jvm) {
484 CHECK(!!mJvm) << "JVM is unavailable";
485}
486
487void RealJniWrapper::initializeForCurrentThread() const {
488 (void)getOrAttachJniEnv(mJvm);
489}
490
491JavaVM* RealJniWrapper::getJvm(JNIEnv* env) {
492 return getJavaVm(env);
493}
494
Yurii Zubrytskyi629051fd2020-04-17 23:13:47 -0700495} // namespace android::incremental