[incfs] Fix a crash in worker thread calling JNI

Worker thread has to initialize JNI separately to be able
to call into managed binders implemented in the same
system_server process, e.g. DataLoaderManager

Bug: 153513507
Test: adb install megacity.nov4.apk; adb install megacity.v4.apk
Change-Id: I668e8664361cd2fb3353ec50efd689c7d613658f
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index e99a264..76b1713 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -135,7 +135,7 @@
 
 static jlong android_server_SystemServer_startIncrementalService(JNIEnv* env, jclass klass,
                                                                  jobject self) {
-    return Incremental_IncrementalService_Start();
+    return Incremental_IncrementalService_Start(env);
 }
 
 static void android_server_SystemServer_setIncrementalServiceSystemReady(JNIEnv* env, jclass klass,
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 853eba7..e32a343 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -410,6 +410,8 @@
 
     // Installation.
     bool onPrepareImage(dataloader::DataLoaderInstallationFiles addedFiles) final {
+        ALOGE("onPrepareImage: start.");
+
         JNIEnv* env = GetOrAttachJNIEnvironment(mJvm);
         const auto& jni = jniIds(env);
 
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index ebebf60..fc8c6fe 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -58,10 +58,10 @@
     return true;
 }
 
-BinderIncrementalService::BinderIncrementalService(const sp<IServiceManager>& sm)
-      : mImpl(RealServiceManager(sm), getIncrementalDir()) {}
+BinderIncrementalService::BinderIncrementalService(const sp<IServiceManager>& sm, JNIEnv* env)
+      : mImpl(RealServiceManager(sm, env), getIncrementalDir()) {}
 
-BinderIncrementalService* BinderIncrementalService::start() {
+BinderIncrementalService* BinderIncrementalService::start(JNIEnv* env) {
     if (!incFsEnabled()) {
         return nullptr;
     }
@@ -81,7 +81,7 @@
         return nullptr;
     }
 
-    sp<BinderIncrementalService> self(new BinderIncrementalService(sm));
+    sp<BinderIncrementalService> self(new BinderIncrementalService(sm, env));
     status_t ret = sm->addService(String16{getServiceName()}, self);
     if (ret != android::OK) {
         return nullptr;
@@ -290,8 +290,8 @@
 
 } // namespace android::os::incremental
 
-jlong Incremental_IncrementalService_Start() {
-    return (jlong)android::os::incremental::BinderIncrementalService::start();
+jlong Incremental_IncrementalService_Start(JNIEnv* env) {
+    return (jlong)android::os::incremental::BinderIncrementalService::start(env);
 }
 void Incremental_IncrementalService_OnSystemReady(jlong self) {
     if (self) {
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index aca10ab..5a7d5da 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -18,6 +18,7 @@
 
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
+#include <jni.h>
 
 #include "IncrementalService.h"
 #include "android/os/incremental/BnIncrementalService.h"
@@ -28,9 +29,9 @@
 class BinderIncrementalService : public BnIncrementalService,
                                  public BinderService<BinderIncrementalService> {
 public:
-    BinderIncrementalService(const sp<IServiceManager>& sm);
+    BinderIncrementalService(const sp<IServiceManager>& sm, JNIEnv* env);
 
-    static BinderIncrementalService* start();
+    static BinderIncrementalService* start(JNIEnv* env);
     static const char16_t* getServiceName() { return u"incremental"; }
     status_t dump(int fd, const Vector<String16>& args) final;
 
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 400388e..2c6bf0a 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -237,6 +237,7 @@
         mDataLoaderManager(sm.getDataLoaderManager()),
         mIncFs(sm.getIncFs()),
         mAppOpsManager(sm.getAppOpsManager()),
+        mJni(sm.getJni()),
         mIncrementalDir(rootDir) {
     if (!mVold) {
         LOG(FATAL) << "Vold service is unavailable";
@@ -249,7 +250,10 @@
     }
 
     mJobQueue.reserve(16);
-    mJobProcessor = std::thread([this]() { runJobProcessing(); });
+    mJobProcessor = std::thread([this]() {
+        mJni->initializeForCurrentThread();
+        runJobProcessing();
+    });
 
     mountExistingImages();
 }
@@ -1248,9 +1252,10 @@
             continue;
         }
 
-        jobQueue.emplace_back([this, zipFile, entry, ifs, libFileId,
-                               libPath = std::move(targetLibPath), makeFileTs]() mutable {
-            extractZipFile(ifs, zipFile.get(), entry, libFileId, libPath, makeFileTs);
+        jobQueue.emplace_back([this, zipFile, entry, ifs = std::weak_ptr<IncFsMount>(ifs),
+                               libFileId, libPath = std::move(targetLibPath),
+                               makeFileTs]() mutable {
+            extractZipFile(ifs.lock(), zipFile.get(), entry, libFileId, libPath, makeFileTs);
         });
 
         if (sEnablePerfLogging) {
@@ -1296,6 +1301,11 @@
                                         ZipEntry& entry, const incfs::FileId& libFileId,
                                         std::string_view targetLibPath,
                                         Clock::time_point scheduledTs) {
+    if (!ifs) {
+        LOG(INFO) << "Skipping zip file " << targetLibPath << " extraction for an expired mount";
+        return;
+    }
+
     auto libName = path::basename(targetLibPath);
     auto startedTs = Clock::now();
 
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 4fdce4b..e7705df 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -289,10 +289,11 @@
                         Clock::time_point scheduledTs);
 
 private:
-    std::unique_ptr<VoldServiceWrapper> const mVold;
-    std::unique_ptr<DataLoaderManagerWrapper> const mDataLoaderManager;
-    std::unique_ptr<IncFsWrapper> const mIncFs;
-    std::unique_ptr<AppOpsManagerWrapper> const mAppOpsManager;
+    const std::unique_ptr<VoldServiceWrapper> mVold;
+    const std::unique_ptr<DataLoaderManagerWrapper> mDataLoaderManager;
+    const std::unique_ptr<IncFsWrapper> mIncFs;
+    const std::unique_ptr<AppOpsManagerWrapper> mAppOpsManager;
+    const std::unique_ptr<JniWrapper> mJni;
     const std::string mIncrementalDir;
 
     mutable std::mutex mLock;
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 9f4192f..bf8e696 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "IncrementalService"
+
 #include "ServiceWrappers.h"
 
+#include <android-base/logging.h>
 #include <utils/String16.h>
 
 using namespace std::literals;
@@ -25,8 +28,123 @@
 static constexpr auto kVoldServiceName = "vold"sv;
 static constexpr auto kDataLoaderManagerName = "dataloader_manager"sv;
 
-RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager)
-      : mServiceManager(std::move(serviceManager)) {}
+class RealVoldService : public VoldServiceWrapper {
+public:
+    RealVoldService(const sp<os::IVold> vold) : mInterface(std::move(vold)) {}
+    ~RealVoldService() = default;
+    binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
+                              int32_t flags,
+                              IncrementalFileSystemControlParcel* _aidl_return) const final {
+        return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
+    }
+    binder::Status unmountIncFs(const std::string& dir) const final {
+        return mInterface->unmountIncFs(dir);
+    }
+    binder::Status bindMount(const std::string& sourceDir,
+                             const std::string& targetDir) const final {
+        return mInterface->bindMount(sourceDir, targetDir);
+    }
+    binder::Status setIncFsMountOptions(
+            const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
+            bool enableReadLogs) const final {
+        return mInterface->setIncFsMountOptions(control, enableReadLogs);
+    }
+
+private:
+    sp<os::IVold> mInterface;
+};
+
+class RealDataLoaderManager : public DataLoaderManagerWrapper {
+public:
+    RealDataLoaderManager(const sp<content::pm::IDataLoaderManager> manager)
+          : mInterface(manager) {}
+    ~RealDataLoaderManager() = default;
+    binder::Status initializeDataLoader(MountId mountId, const DataLoaderParamsParcel& params,
+                                        const FileSystemControlParcel& control,
+                                        const sp<IDataLoaderStatusListener>& listener,
+                                        bool* _aidl_return) const final {
+        return mInterface->initializeDataLoader(mountId, params, control, listener, _aidl_return);
+    }
+    binder::Status getDataLoader(MountId mountId, sp<IDataLoader>* _aidl_return) const final {
+        return mInterface->getDataLoader(mountId, _aidl_return);
+    }
+    binder::Status destroyDataLoader(MountId mountId) const final {
+        return mInterface->destroyDataLoader(mountId);
+    }
+
+private:
+    sp<content::pm::IDataLoaderManager> mInterface;
+};
+
+class RealAppOpsManager : public AppOpsManagerWrapper {
+public:
+    ~RealAppOpsManager() = default;
+    binder::Status checkPermission(const char* permission, const char* operation,
+                                   const char* package) const final {
+        return android::incremental::CheckPermissionForDataDelivery(permission, operation, package);
+    }
+    void startWatchingMode(int32_t op, const String16& packageName,
+                           const sp<IAppOpsCallback>& callback) final {
+        mAppOpsManager.startWatchingMode(op, packageName, callback);
+    }
+    void stopWatchingMode(const sp<IAppOpsCallback>& callback) final {
+        mAppOpsManager.stopWatchingMode(callback);
+    }
+
+private:
+    android::AppOpsManager mAppOpsManager;
+};
+
+class RealJniWrapper final : public JniWrapper {
+public:
+    RealJniWrapper(JavaVM* jvm);
+    void initializeForCurrentThread() const final;
+
+    static JavaVM* getJvm(JNIEnv* env);
+
+private:
+    JavaVM* const mJvm;
+};
+
+class RealIncFs : public IncFsWrapper {
+public:
+    RealIncFs() = default;
+    ~RealIncFs() = default;
+    Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const final {
+        return incfs::createControl(cmd, pendingReads, logs);
+    }
+    ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
+                       NewFileParams params) const final {
+        return incfs::makeFile(control, path, mode, id, params);
+    }
+    ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
+        return incfs::makeDir(control, path, mode);
+    }
+    RawMetadata getMetadata(const Control& control, FileId fileid) const final {
+        return incfs::getMetadata(control, fileid);
+    }
+    RawMetadata getMetadata(const Control& control, std::string_view path) const final {
+        return incfs::getMetadata(control, path);
+    }
+    FileId getFileId(const Control& control, std::string_view path) const final {
+        return incfs::getFileId(control, path);
+    }
+    ErrorCode link(const Control& control, std::string_view from, std::string_view to) const final {
+        return incfs::link(control, from, to);
+    }
+    ErrorCode unlink(const Control& control, std::string_view path) const final {
+        return incfs::unlink(control, path);
+    }
+    base::unique_fd openForSpecialOps(const Control& control, FileId id) const final {
+        return base::unique_fd{incfs::openForSpecialOps(control, id).release()};
+    }
+    ErrorCode writeBlocks(Span<const DataBlock> blocks) const final {
+        return incfs::writeBlocks(blocks);
+    }
+};
+
+RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)
+      : mServiceManager(std::move(serviceManager)), mJvm(RealJniWrapper::getJvm(env)) {}
 
 template <class INTERFACE>
 sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
@@ -63,4 +181,62 @@
     return std::make_unique<RealAppOpsManager>();
 }
 
+std::unique_ptr<JniWrapper> RealServiceManager::getJni() {
+    return std::make_unique<RealJniWrapper>(mJvm);
+}
+
+static JavaVM* getJavaVm(JNIEnv* env) {
+    CHECK(env);
+    JavaVM* jvm = nullptr;
+    env->GetJavaVM(&jvm);
+    CHECK(jvm);
+    return jvm;
+}
+
+static JNIEnv* getJniEnv(JavaVM* vm) {
+    JNIEnv* env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        return nullptr;
+    }
+    return env;
+}
+
+static JNIEnv* getOrAttachJniEnv(JavaVM* jvm) {
+    if (!jvm) {
+        LOG(ERROR) << "No JVM instance";
+        return nullptr;
+    }
+
+    JNIEnv* env = getJniEnv(jvm);
+    if (!env) {
+        int result = jvm->AttachCurrentThread(&env, nullptr);
+        if (result != JNI_OK) {
+            LOG(ERROR) << "JVM thread attach failed: " << result;
+            return nullptr;
+        }
+        struct VmDetacher {
+            VmDetacher(JavaVM* vm) : mVm(vm) {}
+            ~VmDetacher() { mVm->DetachCurrentThread(); }
+
+        private:
+            JavaVM* const mVm;
+        };
+        static thread_local VmDetacher detacher(jvm);
+    }
+
+    return env;
+}
+
+RealJniWrapper::RealJniWrapper(JavaVM* jvm) : mJvm(jvm) {
+    CHECK(!!mJvm) << "JVM is unavailable";
+}
+
+void RealJniWrapper::initializeForCurrentThread() const {
+    (void)getOrAttachJniEnv(mJvm);
+}
+
+JavaVM* RealJniWrapper::getJvm(JNIEnv* env) {
+    return getJavaVm(env);
+}
+
 } // namespace android::os::incremental
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 84bf1ff..142bf2e 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -29,6 +29,7 @@
 #include <binder/AppOpsManager.h>
 #include <binder/IServiceManager.h>
 #include <incfs.h>
+#include <jni.h>
 
 #include <memory>
 #include <string>
@@ -93,6 +94,12 @@
     virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
 };
 
+class JniWrapper {
+public:
+    virtual ~JniWrapper() = default;
+    virtual void initializeForCurrentThread() const = 0;
+};
+
 class ServiceManagerWrapper {
 public:
     virtual ~ServiceManagerWrapper() = default;
@@ -100,127 +107,26 @@
     virtual std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() = 0;
     virtual std::unique_ptr<IncFsWrapper> getIncFs() = 0;
     virtual std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() = 0;
+    virtual std::unique_ptr<JniWrapper> getJni() = 0;
 };
 
 // --- Real stuff ---
 
-class RealVoldService : public VoldServiceWrapper {
-public:
-    RealVoldService(const sp<os::IVold> vold) : mInterface(std::move(vold)) {}
-    ~RealVoldService() = default;
-    binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
-                              int32_t flags,
-                              IncrementalFileSystemControlParcel* _aidl_return) const final {
-        return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
-    }
-    binder::Status unmountIncFs(const std::string& dir) const final {
-        return mInterface->unmountIncFs(dir);
-    }
-    binder::Status bindMount(const std::string& sourceDir,
-                             const std::string& targetDir) const final {
-        return mInterface->bindMount(sourceDir, targetDir);
-    }
-    binder::Status setIncFsMountOptions(
-            const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
-            bool enableReadLogs) const final {
-        return mInterface->setIncFsMountOptions(control, enableReadLogs);
-    }
-
-private:
-    sp<os::IVold> mInterface;
-};
-
-class RealDataLoaderManager : public DataLoaderManagerWrapper {
-public:
-    RealDataLoaderManager(const sp<content::pm::IDataLoaderManager> manager)
-          : mInterface(manager) {}
-    ~RealDataLoaderManager() = default;
-    binder::Status initializeDataLoader(MountId mountId, const DataLoaderParamsParcel& params,
-                                        const FileSystemControlParcel& control,
-                                        const sp<IDataLoaderStatusListener>& listener,
-                                        bool* _aidl_return) const final {
-        return mInterface->initializeDataLoader(mountId, params, control, listener, _aidl_return);
-    }
-    binder::Status getDataLoader(MountId mountId, sp<IDataLoader>* _aidl_return) const final {
-        return mInterface->getDataLoader(mountId, _aidl_return);
-    }
-    binder::Status destroyDataLoader(MountId mountId) const final {
-        return mInterface->destroyDataLoader(mountId);
-    }
-
-private:
-    sp<content::pm::IDataLoaderManager> mInterface;
-};
-
-class RealAppOpsManager : public AppOpsManagerWrapper {
-public:
-    ~RealAppOpsManager() = default;
-    binder::Status checkPermission(const char* permission, const char* operation,
-                                   const char* package) const final {
-        return android::incremental::CheckPermissionForDataDelivery(permission, operation, package);
-    }
-    void startWatchingMode(int32_t op, const String16& packageName,
-                           const sp<IAppOpsCallback>& callback) final {
-        mAppOpsManager.startWatchingMode(op, packageName, callback);
-    }
-    void stopWatchingMode(const sp<IAppOpsCallback>& callback) final {
-        mAppOpsManager.stopWatchingMode(callback);
-    }
-
-private:
-    android::AppOpsManager mAppOpsManager;
-};
-
 class RealServiceManager : public ServiceManagerWrapper {
 public:
-    RealServiceManager(sp<IServiceManager> serviceManager);
+    RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env);
     ~RealServiceManager() = default;
     std::unique_ptr<VoldServiceWrapper> getVoldService() final;
     std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final;
     std::unique_ptr<IncFsWrapper> getIncFs() final;
     std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() final;
+    std::unique_ptr<JniWrapper> getJni() final;
 
 private:
     template <class INTERFACE>
     sp<INTERFACE> getRealService(std::string_view serviceName) const;
     sp<android::IServiceManager> mServiceManager;
-};
-
-class RealIncFs : public IncFsWrapper {
-public:
-    RealIncFs() = default;
-    ~RealIncFs() = default;
-    Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const final {
-        return incfs::createControl(cmd, pendingReads, logs);
-    }
-    ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
-                       NewFileParams params) const final {
-        return incfs::makeFile(control, path, mode, id, params);
-    }
-    ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
-        return incfs::makeDir(control, path, mode);
-    }
-    RawMetadata getMetadata(const Control& control, FileId fileid) const final {
-        return incfs::getMetadata(control, fileid);
-    }
-    RawMetadata getMetadata(const Control& control, std::string_view path) const final {
-        return incfs::getMetadata(control, path);
-    }
-    FileId getFileId(const Control& control, std::string_view path) const final {
-        return incfs::getFileId(control, path);
-    }
-    ErrorCode link(const Control& control, std::string_view from, std::string_view to) const final {
-        return incfs::link(control, from, to);
-    }
-    ErrorCode unlink(const Control& control, std::string_view path) const final {
-        return incfs::unlink(control, path);
-    }
-    base::unique_fd openForSpecialOps(const Control& control, FileId id) const final {
-        return base::unique_fd{incfs::openForSpecialOps(control, id).release()};
-    }
-    ErrorCode writeBlocks(Span<const DataBlock> blocks) const final {
-        return incfs::writeBlocks(blocks);
-    }
+    JavaVM* const mJvm;
 };
 
 } // namespace android::os::incremental
diff --git a/services/incremental/include/incremental_service.h b/services/incremental/include/incremental_service.h
index 4a34b11..3213875 100644
--- a/services/incremental/include/incremental_service.h
+++ b/services/incremental/include/incremental_service.h
@@ -24,7 +24,7 @@
 
 #define INCREMENTAL_LIBRARY_NAME "service.incremental.so"
 
-jlong Incremental_IncrementalService_Start();
+jlong Incremental_IncrementalService_Start(JNIEnv* env);
 void Incremental_IncrementalService_OnSystemReady(jlong self);
 void Incremental_IncrementalService_OnDump(jlong self, jint fd);
 
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 9911319..117dca8 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -261,28 +261,39 @@
     sp<IAppOpsCallback> mStoredCallback;
 };
 
+class MockJniWrapper : public JniWrapper {
+public:
+    MOCK_CONST_METHOD0(initializeForCurrentThread, void());
+
+    MockJniWrapper() { EXPECT_CALL(*this, initializeForCurrentThread()).Times(1); }
+};
+
 class MockServiceManager : public ServiceManagerWrapper {
 public:
     MockServiceManager(std::unique_ptr<MockVoldService> vold,
-                       std::unique_ptr<MockDataLoaderManager> manager,
+                       std::unique_ptr<MockDataLoaderManager> dataLoaderManager,
                        std::unique_ptr<MockIncFs> incfs,
-                       std::unique_ptr<MockAppOpsManager> appOpsManager)
+                       std::unique_ptr<MockAppOpsManager> appOpsManager,
+                       std::unique_ptr<MockJniWrapper> jni)
           : mVold(std::move(vold)),
-            mDataLoaderManager(std::move(manager)),
+            mDataLoaderManager(std::move(dataLoaderManager)),
             mIncFs(std::move(incfs)),
-            mAppOpsManager(std::move(appOpsManager)) {}
+            mAppOpsManager(std::move(appOpsManager)),
+            mJni(std::move(jni)) {}
     std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
     std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final {
         return std::move(mDataLoaderManager);
     }
     std::unique_ptr<IncFsWrapper> getIncFs() final { return std::move(mIncFs); }
     std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() final { return std::move(mAppOpsManager); }
+    std::unique_ptr<JniWrapper> getJni() final { return std::move(mJni); }
 
 private:
     std::unique_ptr<MockVoldService> mVold;
     std::unique_ptr<MockDataLoaderManager> mDataLoaderManager;
     std::unique_ptr<MockIncFs> mIncFs;
     std::unique_ptr<MockAppOpsManager> mAppOpsManager;
+    std::unique_ptr<MockJniWrapper> mJni;
 };
 
 // --- IncrementalServiceTest ---
@@ -298,11 +309,15 @@
         mIncFs = incFs.get();
         auto appOps = std::make_unique<NiceMock<MockAppOpsManager>>();
         mAppOpsManager = appOps.get();
+        auto jni = std::make_unique<NiceMock<MockJniWrapper>>();
+        mJni = jni.get();
         mIncrementalService =
                 std::make_unique<IncrementalService>(MockServiceManager(std::move(vold),
-                                                                        std::move(dataloaderManager),
+                                                                        std::move(
+                                                                                dataloaderManager),
                                                                         std::move(incFs),
-                                                                        std::move(appOps)),
+                                                                        std::move(appOps),
+                                                                        std::move(jni)),
                                                      mRootDir.path);
         mDataLoaderParcel.packageName = "com.test";
         mDataLoaderParcel.arguments = "uri";
@@ -336,6 +351,7 @@
     NiceMock<MockIncFs>* mIncFs;
     NiceMock<MockDataLoaderManager>* mDataLoaderManager;
     NiceMock<MockAppOpsManager>* mAppOpsManager;
+    NiceMock<MockJniWrapper>* mJni;
     std::unique_ptr<IncrementalService> mIncrementalService;
     TemporaryDir mRootDir;
     DataLoaderParamsParcel mDataLoaderParcel;