Lifecycle: detecting pending reads.

Once pending read detected, try to start the dataloader.

Bug: 153874006
Test: test PackageManagerShellCommandTest PackageManagerShellCommandIncrementalTest IncrementalServiceTest

Change-Id: Ia8169ccbb0f710317715e6fddb9bc6a718543766
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 2205bfe..325218d 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -242,6 +242,9 @@
     void setDataLoaderStatusDestroyed() {
         mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
     }
+    void setDataLoaderStatusUnavailable() {
+        mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE);
+    }
     binder::Status unbindFromDataLoaderOk(int32_t id) {
         if (mDataLoader) {
             if (auto status = mDataLoader->destroy(id); !status.isOk()) {
@@ -286,6 +289,14 @@
 
     void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
     void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }
+    void openMountSuccess() {
+        ON_CALL(*this, openMount(_)).WillByDefault(Invoke(this, &MockIncFs::openMountForHealth));
+    }
+
+    static constexpr auto kPendingReadsFd = 42;
+    Control openMountForHealth(std::string_view) {
+        return UniqueControl(IncFs_CreateControl(-1, kPendingReadsFd, -1));
+    }
 
     RawMetadata getMountInfoMetadata(const Control& control, std::string_view path) {
         metadata::Mount m;
@@ -346,7 +357,42 @@
 public:
     MOCK_CONST_METHOD0(initializeForCurrentThread, void());
 
-    MockJniWrapper() { EXPECT_CALL(*this, initializeForCurrentThread()).Times(1); }
+    MockJniWrapper() { EXPECT_CALL(*this, initializeForCurrentThread()).Times(2); }
+};
+
+class MockLooperWrapper : public LooperWrapper {
+public:
+    MOCK_METHOD5(addFd, int(int, int, int, android::Looper_callbackFunc, void*));
+    MOCK_METHOD1(removeFd, int(int));
+    MOCK_METHOD0(wake, void());
+    MOCK_METHOD1(pollAll, int(int));
+
+    MockLooperWrapper() {
+        ON_CALL(*this, addFd(_, _, _, _, _))
+                .WillByDefault(Invoke(this, &MockLooperWrapper::storeCallback));
+        ON_CALL(*this, removeFd(_)).WillByDefault(Invoke(this, &MockLooperWrapper::clearCallback));
+        ON_CALL(*this, pollAll(_)).WillByDefault(Invoke(this, &MockLooperWrapper::sleepFor));
+    }
+
+    int storeCallback(int, int, int, android::Looper_callbackFunc callback, void* data) {
+        mCallback = callback;
+        mCallbackData = data;
+        return 0;
+    }
+
+    int clearCallback(int) {
+        mCallback = nullptr;
+        mCallbackData = nullptr;
+        return 0;
+    }
+
+    int sleepFor(int timeoutMillis) {
+        std::this_thread::sleep_for(std::chrono::milliseconds(timeoutMillis));
+        return 0;
+    }
+
+    android::Looper_callbackFunc mCallback = nullptr;
+    void* mCallbackData = nullptr;
 };
 
 class MockServiceManager : public ServiceManagerWrapper {
@@ -355,12 +401,14 @@
                        std::unique_ptr<MockDataLoaderManager> dataLoaderManager,
                        std::unique_ptr<MockIncFs> incfs,
                        std::unique_ptr<MockAppOpsManager> appOpsManager,
-                       std::unique_ptr<MockJniWrapper> jni)
+                       std::unique_ptr<MockJniWrapper> jni,
+                       std::unique_ptr<MockLooperWrapper> looper)
           : mVold(std::move(vold)),
             mDataLoaderManager(std::move(dataLoaderManager)),
             mIncFs(std::move(incfs)),
             mAppOpsManager(std::move(appOpsManager)),
-            mJni(std::move(jni)) {}
+            mJni(std::move(jni)),
+            mLooper(std::move(looper)) {}
     std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
     std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final {
         return std::move(mDataLoaderManager);
@@ -368,6 +416,7 @@
     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); }
+    std::unique_ptr<LooperWrapper> getLooper() final { return std::move(mLooper); }
 
 private:
     std::unique_ptr<MockVoldService> mVold;
@@ -375,6 +424,7 @@
     std::unique_ptr<MockIncFs> mIncFs;
     std::unique_ptr<MockAppOpsManager> mAppOpsManager;
     std::unique_ptr<MockJniWrapper> mJni;
+    std::unique_ptr<MockLooperWrapper> mLooper;
 };
 
 // --- IncrementalServiceTest ---
@@ -394,13 +444,16 @@
         mAppOpsManager = appOps.get();
         auto jni = std::make_unique<NiceMock<MockJniWrapper>>();
         mJni = jni.get();
+        auto looper = std::make_unique<NiceMock<MockLooperWrapper>>();
+        mLooper = looper.get();
         mIncrementalService =
                 std::make_unique<IncrementalService>(MockServiceManager(std::move(vold),
                                                                         std::move(
                                                                                 dataloaderManager),
                                                                         std::move(incFs),
                                                                         std::move(appOps),
-                                                                        std::move(jni)),
+                                                                        std::move(jni),
+                                                                        std::move(looper)),
                                                      mRootDir.path);
         mDataLoaderParcel.packageName = "com.test";
         mDataLoaderParcel.arguments = "uri";
@@ -430,12 +483,13 @@
     }
 
 protected:
-    NiceMock<MockVoldService>* mVold;
-    NiceMock<MockIncFs>* mIncFs;
-    NiceMock<MockDataLoaderManager>* mDataLoaderManager;
-    NiceMock<MockAppOpsManager>* mAppOpsManager;
-    NiceMock<MockJniWrapper>* mJni;
-    NiceMock<MockDataLoader>* mDataLoader;
+    NiceMock<MockVoldService>* mVold = nullptr;
+    NiceMock<MockIncFs>* mIncFs = nullptr;
+    NiceMock<MockDataLoaderManager>* mDataLoaderManager = nullptr;
+    NiceMock<MockAppOpsManager>* mAppOpsManager = nullptr;
+    NiceMock<MockJniWrapper>* mJni = nullptr;
+    NiceMock<MockLooperWrapper>* mLooper = nullptr;
+    NiceMock<MockDataLoader>* mDataLoader = nullptr;
     std::unique_ptr<IncrementalService> mIncrementalService;
     TemporaryDir mRootDir;
     DataLoaderParamsParcel mDataLoaderParcel;
@@ -593,6 +647,54 @@
     mDataLoaderManager->setDataLoaderStatusCreated();
 }
 
+TEST_F(IncrementalServiceTest, testStartDataLoaderCreateUnavailable) {
+    mVold->mountIncFsSuccess();
+    mIncFs->makeFileSuccess();
+    mVold->bindMountSuccess();
+    mDataLoader->initializeCreateOkNoStatus();
+    mDataLoaderManager->bindToDataLoaderSuccess();
+    mDataLoaderManager->getDataLoaderSuccess();
+    EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(1);
+    EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
+    EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(1);
+    EXPECT_CALL(*mDataLoader, start(_)).Times(0);
+    EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
+    EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+    TemporaryDir tempDir;
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
+                                               IncrementalService::CreateOptions::CreateNew);
+    ASSERT_GE(storageId, 0);
+    mDataLoaderManager->setDataLoaderStatusUnavailable();
+}
+
+TEST_F(IncrementalServiceTest, testStartDataLoaderRecreateOnPendingReads) {
+    mVold->mountIncFsSuccess();
+    mIncFs->makeFileSuccess();
+    mIncFs->openMountSuccess();
+    mVold->bindMountSuccess();
+    mDataLoader->initializeCreateOkNoStatus();
+    mDataLoaderManager->bindToDataLoaderSuccess();
+    mDataLoaderManager->getDataLoaderSuccess();
+    EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(2);
+    EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
+    EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(2);
+    EXPECT_CALL(*mDataLoader, start(_)).Times(0);
+    EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
+    EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+    EXPECT_CALL(*mLooper, addFd(MockIncFs::kPendingReadsFd, _, _, _, _)).Times(1);
+    EXPECT_CALL(*mLooper, removeFd(MockIncFs::kPendingReadsFd)).Times(1);
+    TemporaryDir tempDir;
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
+                                               IncrementalService::CreateOptions::CreateNew);
+    ASSERT_GE(storageId, 0);
+    mDataLoaderManager->setDataLoaderStatusUnavailable();
+    ASSERT_NE(nullptr, mLooper->mCallback);
+    ASSERT_NE(nullptr, mLooper->mCallbackData);
+    mLooper->mCallback(-1, -1, mLooper->mCallbackData);
+}
+
 TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccess) {
     mVold->mountIncFsSuccess();
     mIncFs->makeFileSuccess();