Wait for APK to be fully downloaded for full APK digests.
Bug: 160605420
Test: atest ChecksumsTest
Change-Id: Ib9fd591c67290786268b6dcdc57c7db153612e01
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index 41945a2..87ae4d7 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -237,6 +237,13 @@
return ok();
}
+binder::Status BinderIncrementalService::isFileFullyLoaded(int32_t storageId,
+ const std::string& path,
+ int32_t* _aidl_return) {
+ *_aidl_return = mImpl.isFileFullyLoaded(storageId, path);
+ return ok();
+}
+
binder::Status BinderIncrementalService::getLoadingProgress(int32_t storageId,
float* _aidl_return) {
*_aidl_return = mImpl.getLoadingProgress(storageId);
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 8b40350..8478142 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -66,6 +66,8 @@
int32_t destStorageId, const std::string& destPath,
int32_t* _aidl_return) final;
binder::Status unlink(int32_t storageId, const std::string& path, int32_t* _aidl_return) final;
+ binder::Status isFileFullyLoaded(int32_t storageId, const std::string& path,
+ int32_t* _aidl_return) final;
binder::Status getLoadingProgress(int32_t storageId, float* _aidl_return) final;
binder::Status getMetadataByPath(int32_t storageId, const std::string& path,
std::vector<uint8_t>* _aidl_return) final;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 9836262e..447ee55 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1603,7 +1603,8 @@
const auto writeFd = mIncFs->openForSpecialOps(ifs->control, libFileId);
if (!writeFd.ok()) {
- LOG(ERROR) << "Failed to open write fd for: " << targetLibPath << " errno: " << writeFd;
+ LOG(ERROR) << "Failed to open write fd for: " << targetLibPath
+ << " errno: " << writeFd.get();
return;
}
@@ -1673,6 +1674,37 @@
return mRunning;
}
+int IncrementalService::isFileFullyLoaded(StorageId storage, const std::string& path) const {
+ std::unique_lock l(mLock);
+ const auto ifs = getIfsLocked(storage);
+ if (!ifs) {
+ LOG(ERROR) << "isFileFullyLoaded failed, invalid storageId: " << storage;
+ return -EINVAL;
+ }
+ const auto storageInfo = ifs->storages.find(storage);
+ if (storageInfo == ifs->storages.end()) {
+ LOG(ERROR) << "isFileFullyLoaded failed, no storage: " << storage;
+ return -EINVAL;
+ }
+ l.unlock();
+ return isFileFullyLoadedFromPath(*ifs, path);
+}
+
+int IncrementalService::isFileFullyLoadedFromPath(const IncFsMount& ifs,
+ std::string_view filePath) const {
+ const auto [filledBlocks, totalBlocks] = mIncFs->countFilledBlocks(ifs.control, filePath);
+ if (filledBlocks < 0) {
+ LOG(ERROR) << "isFileFullyLoadedFromPath failed to get filled blocks count for: "
+ << filePath << " errno: " << filledBlocks;
+ return filledBlocks;
+ }
+ if (totalBlocks < filledBlocks) {
+ LOG(ERROR) << "isFileFullyLoadedFromPath failed to get total num of blocks";
+ return -EINVAL;
+ }
+ return totalBlocks - filledBlocks;
+}
+
float IncrementalService::getLoadingProgress(StorageId storage) const {
std::unique_lock l(mLock);
const auto ifs = getIfsLocked(storage);
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index cd6bfed..267458d 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -132,6 +132,7 @@
std::string_view newPath);
int unlink(StorageId storage, std::string_view path);
+ int isFileFullyLoaded(StorageId storage, const std::string& path) const;
float getLoadingProgress(StorageId storage) const;
RawMetadata getMetadata(StorageId storage, std::string_view path) const;
@@ -339,6 +340,7 @@
int makeDirs(const IncFsMount& ifs, StorageId storageId, std::string_view path, int mode);
binder::Status applyStorageParams(IncFsMount& ifs, bool enableReadLogs);
+ int isFileFullyLoadedFromPath(const IncFsMount& ifs, std::string_view filePath) const;
float getLoadingProgressFromPath(const IncFsMount& ifs, std::string_view path) const;
void registerAppOpsCallback(const std::string& packageName);
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 1ed46c4..f6d89c5 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -195,8 +195,8 @@
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()};
+ incfs::UniqueFd openForSpecialOps(const Control& control, FileId id) const final {
+ return incfs::openForSpecialOps(control, id);
}
ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 82a1704..6376d86 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -74,6 +74,7 @@
using Control = incfs::Control;
using FileId = incfs::FileId;
using ErrorCode = incfs::ErrorCode;
+ using UniqueFd = incfs::UniqueFd;
using WaitResult = incfs::WaitResult;
using ExistingMountCallback =
@@ -96,7 +97,7 @@
virtual ErrorCode link(const Control& control, std::string_view from,
std::string_view to) const = 0;
virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0;
- virtual base::unique_fd openForSpecialOps(const Control& control, FileId id) const = 0;
+ virtual UniqueFd openForSpecialOps(const Control& control, FileId id) const = 0;
virtual ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const = 0;
virtual WaitResult waitForPendingReads(
const Control& control, std::chrono::milliseconds timeout,
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index d1000e56..a290a17 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -289,7 +289,7 @@
ErrorCode(const Control& control, std::string_view from,
std::string_view to));
MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path));
- MOCK_CONST_METHOD2(openForSpecialOps, base::unique_fd(const Control& control, FileId id));
+ MOCK_CONST_METHOD2(openForSpecialOps, UniqueFd(const Control& control, FileId id));
MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
MOCK_CONST_METHOD3(waitForPendingReads,
WaitResult(const Control& control, std::chrono::milliseconds timeout,
@@ -304,6 +304,10 @@
ON_CALL(*this, countFilledBlocks(_, _)).WillByDefault(Return(std::make_pair(1, 2)));
}
+ void countFilledBlocksFullyLoaded() {
+ ON_CALL(*this, countFilledBlocks(_, _)).WillByDefault(Return(std::make_pair(10000, 10000)));
+ }
+
void countFilledBlocksFails() {
ON_CALL(*this, countFilledBlocks(_, _)).WillByDefault(Return(std::make_pair(-1, -1)));
}
@@ -1069,6 +1073,53 @@
ASSERT_EQ(res, 0);
}
+TEST_F(IncrementalServiceTest, testIsFileFullyLoadedFailsWithNoFile) {
+ mIncFs->countFilledBlocksFails();
+ mFs->hasNoFile();
+
+ TemporaryDir tempDir;
+ int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew,
+ {}, {}, {});
+ ASSERT_EQ(-1, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
+}
+
+TEST_F(IncrementalServiceTest, testIsFileFullyLoadedFailsWithFailedRanges) {
+ mIncFs->countFilledBlocksFails();
+ mFs->hasFiles();
+
+ 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"));
+}
+
+TEST_F(IncrementalServiceTest, testIsFileFullyLoadedSuccessWithEmptyRanges) {
+ mIncFs->countFilledBlocksEmpty();
+ mFs->hasFiles();
+
+ 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"));
+}
+
+TEST_F(IncrementalServiceTest, testIsFileFullyLoadedSuccess) {
+ mIncFs->countFilledBlocksFullyLoaded();
+ mFs->hasFiles();
+
+ 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"));
+}
+
TEST_F(IncrementalServiceTest, testGetLoadingProgressSuccessWithNoFile) {
mIncFs->countFilledBlocksSuccess();
mFs->hasNoFile();