DataLoader lifecycle.
- mark disconnected DataLoaders as non-existent (destroyed),
- remove storage destroy on DataLoader destroy,
- more robust destroy on destruct handling,
- less race-conditions.
Bug: b/153874006
Test: atest PackageManagerShellCommandTest PackageManagerShellCommandIncrementalTest IncrementalServiceTest
Change-Id: Ib77302aac546d66ce40c5345417c7b424a1d601b
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 149dfa6..8d084cd 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -258,10 +258,6 @@
mountExistingImages();
}
-FileId IncrementalService::idFromMetadata(std::span<const uint8_t> metadata) {
- return IncFs_FileIdFromMetadata({(const char*)metadata.data(), metadata.size()});
-}
-
IncrementalService::~IncrementalService() {
{
std::lock_guard lock(mJobMutex);
@@ -1016,7 +1012,7 @@
return false;
}
}
- return dataLoaderStub->start();
+ return dataLoaderStub->requestStart();
}
void IncrementalService::mountExistingImages() {
@@ -1475,12 +1471,15 @@
}
IncrementalService::DataLoaderStub::~DataLoaderStub() {
- CHECK(mStatus == -1 || mStatus == IDataLoaderStatusListener::DATA_LOADER_DESTROYED)
- << "Dataloader has to be destroyed prior to destructor: " << mId
- << ", status: " << mStatus;
+ waitForDestroy();
}
bool IncrementalService::DataLoaderStub::create() {
+ {
+ std::unique_lock lock(mStatusMutex);
+ mStartRequested = false;
+ mDestroyRequested = false;
+ }
bool created = false;
auto status = mService.mDataLoaderManager->initializeDataLoader(mId, mParams, mControl, this,
&created);
@@ -1491,12 +1490,18 @@
return true;
}
-bool IncrementalService::DataLoaderStub::start() {
- if (mStatus != IDataLoaderStatusListener::DATA_LOADER_CREATED) {
+bool IncrementalService::DataLoaderStub::requestStart() {
+ {
+ std::unique_lock lock(mStatusMutex);
mStartRequested = true;
- return true;
+ if (mStatus != IDataLoaderStatusListener::DATA_LOADER_CREATED) {
+ return true;
+ }
}
+ return start();
+}
+bool IncrementalService::DataLoaderStub::start() {
sp<IDataLoader> dataloader;
auto status = mService.mDataLoaderManager->getDataLoader(mId, &dataloader);
if (!status.isOk()) {
@@ -1513,8 +1518,21 @@
}
void IncrementalService::DataLoaderStub::destroy() {
- mDestroyRequested = true;
+ {
+ std::unique_lock lock(mStatusMutex);
+ mDestroyRequested = true;
+ }
mService.mDataLoaderManager->destroyDataLoader(mId);
+
+ waitForDestroy();
+}
+
+bool IncrementalService::DataLoaderStub::waitForDestroy() {
+ auto now = std::chrono::steady_clock::now();
+ std::unique_lock lock(mStatusMutex);
+ return mStatusCondition.wait_until(lock, now + 60s, [this] {
+ return mStatus == IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
+ });
}
binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mountId, int newStatus) {
@@ -1523,34 +1541,36 @@
}
if (mListener) {
- // Give an external listener a chance to act before we destroy something.
mListener->onStatusChanged(mountId, newStatus);
}
+ bool startRequested;
+ bool destroyRequested;
{
- std::unique_lock l(mService.mLock);
- const auto& ifs = mService.getIfsLocked(mountId);
- if (!ifs) {
- LOG(WARNING) << "Received data loader status " << int(newStatus)
- << " for unknown mount " << mountId;
+ std::unique_lock lock(mStatusMutex);
+ if (mStatus == newStatus) {
return binder::Status::ok();
}
- mStatus = newStatus;
- if (!mDestroyRequested && newStatus == IDataLoaderStatusListener::DATA_LOADER_DESTROYED) {
- mService.deleteStorageLocked(*ifs, std::move(l));
- return binder::Status::ok();
- }
+ startRequested = mStartRequested;
+ destroyRequested = mDestroyRequested;
+
+ mStatus = newStatus;
}
switch (newStatus) {
case IDataLoaderStatusListener::DATA_LOADER_CREATED: {
- if (mStartRequested) {
+ if (startRequested) {
+ LOG(WARNING) << "Start was requested, triggering, for mount: " << mountId;
start();
}
break;
}
case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: {
+ if (!destroyRequested) {
+ LOG(WARNING) << "DataLoader destroyed, reconnecting, for mount: " << mountId;
+ create();
+ }
break;
}
case IDataLoaderStatusListener::DATA_LOADER_STARTED: {
@@ -1589,4 +1609,8 @@
return binder::Status::ok();
}
+FileId IncrementalService::idFromMetadata(std::span<const uint8_t> metadata) {
+ return IncFs_FileIdFromMetadata({(const char*)metadata.data(), metadata.size()});
+}
+
} // namespace android::incremental