Per package read timeouts.

Bug: 162345970
Test: atest PackageManagerShellCommandTest PackageManagerShellCommandIncrementalTest IncrementalServiceTest PackageManagerServiceTest

Change-Id: I2599db1ed8827fff16387c11254a5d607f27ea46
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 9b8cf40..02eaa2f 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -42,6 +42,7 @@
 
 using namespace android::incfs;
 using namespace android::content::pm;
+using PerUidReadTimeouts = android::os::incremental::PerUidReadTimeouts;
 
 namespace android::os::incremental {
 
@@ -307,6 +308,9 @@
     MOCK_CONST_METHOD3(waitForPendingReads,
                        WaitResult(const Control& control, std::chrono::milliseconds timeout,
                                   std::vector<incfs::ReadInfo>* pendingReadsBuffer));
+    MOCK_CONST_METHOD2(setUidReadTimeouts,
+                       ErrorCode(const Control& control,
+                                 const std::vector<PerUidReadTimeouts>& perUidReadTimeouts));
 
     MockIncFs() { ON_CALL(*this, listExistingMounts(_)).WillByDefault(Return()); }
 
@@ -665,7 +669,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -676,7 +680,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -689,7 +693,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -703,7 +707,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -721,7 +725,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -735,7 +739,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     mIncrementalService->deleteStorage(storageId);
 }
@@ -750,7 +754,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     // Simulated crash/other connection breakage.
     mDataLoaderManager->setDataLoaderStatusDestroyed();
@@ -767,7 +771,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     mDataLoaderManager->setDataLoaderStatusCreated();
     ASSERT_TRUE(mIncrementalService->startLoading(storageId));
@@ -785,7 +789,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_TRUE(mIncrementalService->startLoading(storageId));
     mDataLoaderManager->setDataLoaderStatusCreated();
@@ -802,7 +806,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     mDataLoaderManager->setDataLoaderStatusUnavailable();
 }
@@ -823,7 +827,7 @@
     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);
@@ -877,7 +881,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, std::move(params), listener);
+                                                       {}, std::move(params), listener, {});
     ASSERT_GE(storageId, 0);
 
     // Healthy state, registered for pending reads.
@@ -972,7 +976,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_GE(mDataLoader->setStorageParams(true), 0);
 }
@@ -993,11 +997,11 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_GE(mDataLoader->setStorageParams(true), 0);
     // Now disable.
-    mIncrementalService->disableReadLogs(storageId);
+    mIncrementalService->disallowReadLogs(storageId);
     ASSERT_EQ(mDataLoader->setStorageParams(true), -EPERM);
 }
 
@@ -1019,7 +1023,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_GE(mDataLoader->setStorageParams(true), 0);
     ASSERT_NE(nullptr, mAppOpsManager->mStoredCallback.get());
@@ -1038,7 +1042,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_LT(mDataLoader->setStorageParams(true), 0);
 }
@@ -1057,7 +1061,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_LT(mDataLoader->setStorageParams(true), 0);
 }
@@ -1066,7 +1070,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     std::string dir_path("test");
 
     // Expecting incfs to call makeDir on a path like:
@@ -1085,7 +1089,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     auto first = "first"sv;
     auto second = "second"sv;
     auto third = "third"sv;
@@ -1108,7 +1112,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     ASSERT_EQ(-1, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
 }
 
@@ -1119,7 +1123,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(1);
     ASSERT_EQ(-1, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
 }
@@ -1131,7 +1135,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(1);
     ASSERT_EQ(0, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
 }
@@ -1143,7 +1147,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(1);
     ASSERT_EQ(0, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
 }
@@ -1155,8 +1159,8 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
-    ASSERT_EQ(1, mIncrementalService->getLoadingProgress(storageId));
+                                                       {}, {}, {}, {});
+    ASSERT_EQ(1, mIncrementalService->getLoadingProgress(storageId).getProgress());
 }
 
 TEST_F(IncrementalServiceTest, testGetLoadingProgressFailsWithFailedRanges) {
@@ -1166,9 +1170,9 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(1);
-    ASSERT_EQ(-1, mIncrementalService->getLoadingProgress(storageId));
+    ASSERT_EQ(-1, mIncrementalService->getLoadingProgress(storageId).getProgress());
 }
 
 TEST_F(IncrementalServiceTest, testGetLoadingProgressSuccessWithEmptyRanges) {
@@ -1178,9 +1182,9 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(3);
-    ASSERT_EQ(1, mIncrementalService->getLoadingProgress(storageId));
+    ASSERT_EQ(1, mIncrementalService->getLoadingProgress(storageId).getProgress());
 }
 
 TEST_F(IncrementalServiceTest, testGetLoadingProgressSuccess) {
@@ -1190,9 +1194,9 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(3);
-    ASSERT_EQ(0.5, mIncrementalService->getLoadingProgress(storageId));
+    ASSERT_EQ(0.5, mIncrementalService->getLoadingProgress(storageId).getProgress());
 }
 
 TEST_F(IncrementalServiceTest, testRegisterLoadingProgressListenerSuccess) {
@@ -1202,7 +1206,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     sp<NiceMock<MockStorageLoadingProgressListener>> listener{
             new NiceMock<MockStorageLoadingProgressListener>};
     NiceMock<MockStorageLoadingProgressListener>* listenerMock = listener.get();
@@ -1227,7 +1231,7 @@
     TemporaryDir tempDir;
     int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                        IncrementalService::CreateOptions::CreateNew,
-                                                       {}, {}, {});
+                                                       {}, {}, {}, {});
     sp<NiceMock<MockStorageLoadingProgressListener>> listener{
             new NiceMock<MockStorageLoadingProgressListener>};
     NiceMock<MockStorageLoadingProgressListener>* listenerMock = listener.get();
@@ -1242,9 +1246,10 @@
     NiceMock<MockStorageHealthListener>* newListenerMock = newListener.get();
 
     TemporaryDir tempDir;
-    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
-                                                       IncrementalService::CreateOptions::CreateNew,
-                                                       {}, StorageHealthCheckParams{}, listener);
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                               IncrementalService::CreateOptions::CreateNew, {},
+                                               StorageHealthCheckParams{}, listener, {});
     ASSERT_GE(storageId, 0);
     StorageHealthCheckParams newParams;
     newParams.blockedTimeoutMs = 10000;
@@ -1313,4 +1318,123 @@
     mTimedQueue->clearJob(storageId);
 }
 
+static std::vector<PerUidReadTimeouts> createPerUidTimeouts(
+        std::initializer_list<std::tuple<int, int, int, int>> tuples) {
+    std::vector<PerUidReadTimeouts> result;
+    for (auto&& tuple : tuples) {
+        result.emplace_back();
+        auto& timeouts = result.back();
+        timeouts.uid = std::get<0>(tuple);
+        timeouts.minTimeUs = std::get<1>(tuple);
+        timeouts.minPendingTimeUs = std::get<2>(tuple);
+        timeouts.maxPendingTimeUs = std::get<3>(tuple);
+    }
+    return result;
+}
+
+static ErrorCode checkPerUidTimeouts(const Control& control,
+                                     const std::vector<PerUidReadTimeouts>& perUidReadTimeouts) {
+    std::vector<PerUidReadTimeouts> expected =
+            createPerUidTimeouts({{0, 1, 2, 3}, {1, 2, 3, 4}, {2, 3, 4, 100000000}});
+    EXPECT_EQ(expected, perUidReadTimeouts);
+    return 0;
+}
+
+static ErrorCode checkPerUidTimeoutsEmpty(
+        const Control& control, const std::vector<PerUidReadTimeouts>& perUidReadTimeouts) {
+    EXPECT_EQ(0u, perUidReadTimeouts.size());
+    return 0;
+}
+
+TEST_F(IncrementalServiceTest, testPerUidTimeoutsTooShort) {
+    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(*mIncFs, setUidReadTimeouts(_, _)).Times(0);
+    EXPECT_CALL(*mTimedQueue, addJob(_, _, _)).Times(0);
+    EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+    TemporaryDir tempDir;
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                               IncrementalService::CreateOptions::CreateNew, {}, {},
+                                               {},
+                                               createPerUidTimeouts(
+                                                       {{0, 1, 2, 3}, {1, 2, 3, 4}, {2, 3, 4, 5}}));
+    ASSERT_GE(storageId, 0);
+}
+
+TEST_F(IncrementalServiceTest, testPerUidTimeoutsSuccess) {
+    mVold->setIncFsMountOptionsSuccess();
+    mAppOpsManager->checkPermissionSuccess();
+    mFs->hasFiles();
+
+    EXPECT_CALL(*mIncFs, setUidReadTimeouts(_, _))
+            // First call.
+            .WillOnce(Invoke(&checkPerUidTimeouts))
+            // Fully loaded and no readlogs.
+            .WillOnce(Invoke(&checkPerUidTimeoutsEmpty));
+    EXPECT_CALL(*mTimedQueue, addJob(_, _, _)).Times(3);
+
+    // Empty storage.
+    mIncFs->countFilledBlocksEmpty();
+
+    TemporaryDir tempDir;
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                               IncrementalService::CreateOptions::CreateNew, {}, {},
+                                               {},
+                                               createPerUidTimeouts({{0, 1, 2, 3},
+                                                                     {1, 2, 3, 4},
+                                                                     {2, 3, 4, 100000000}}));
+    ASSERT_GE(storageId, 0);
+
+    {
+        // Timed callback present -> 0 progress.
+        ASSERT_EQ(storageId, mTimedQueue->mId);
+        ASSERT_GE(mTimedQueue->mAfter, std::chrono::seconds(1));
+        const auto timedCallback = mTimedQueue->mWhat;
+        mTimedQueue->clearJob(storageId);
+
+        // Still loading.
+        mIncFs->countFilledBlocksSuccess();
+
+        // Call it again.
+        timedCallback();
+    }
+
+    {
+        // Still present -> 0.5 progress.
+        ASSERT_EQ(storageId, mTimedQueue->mId);
+        ASSERT_GE(mTimedQueue->mAfter, std::chrono::seconds(1));
+        const auto timedCallback = mTimedQueue->mWhat;
+        mTimedQueue->clearJob(storageId);
+
+        // Fully loaded but readlogs collection enabled.
+        mIncFs->countFilledBlocksFullyLoaded();
+        ASSERT_GE(mDataLoader->setStorageParams(true), 0);
+
+        // Call it again.
+        timedCallback();
+    }
+
+    {
+        // Still present -> fully loaded + readlogs.
+        ASSERT_EQ(storageId, mTimedQueue->mId);
+        ASSERT_GE(mTimedQueue->mAfter, std::chrono::seconds(1));
+        const auto timedCallback = mTimedQueue->mWhat;
+        mTimedQueue->clearJob(storageId);
+
+        // Now disable readlogs.
+        ASSERT_GE(mDataLoader->setStorageParams(false), 0);
+
+        // Call it again.
+        timedCallback();
+    }
+
+    // No callbacks anymore -> fully loaded and no readlogs.
+    ASSERT_EQ(mTimedQueue->mAfter, Milliseconds());
+}
+
 } // namespace android::os::incremental