Incremental apps removal on data loader failures.
Test: adb install --incremental megacity.apk over USB2.0, remove usb connection
after installed.
Bug: b/15041101
Change-Id: Ib848640dbe49c76021f7cf544de4413599c2c763
diff --git a/core/java/android/content/pm/IDataLoaderStatusListener.aidl b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
index 5011faa..9819b5d 100644
--- a/core/java/android/content/pm/IDataLoaderStatusListener.aidl
+++ b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
@@ -31,9 +31,7 @@
const int DATA_LOADER_IMAGE_READY = 4;
const int DATA_LOADER_IMAGE_NOT_READY = 5;
- const int DATA_LOADER_SLOW_CONNECTION = 6;
- const int DATA_LOADER_NO_CONNECTION = 7;
- const int DATA_LOADER_CONNECTION_OK = 8;
+ const int DATA_LOADER_UNRECOVERABLE = 6;
/** Data loader status callback */
void onStatusChanged(in int dataLoaderId, in int status);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 45a25a0..9edc886 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1487,6 +1487,18 @@
return e;
}
+ private void onDataLoaderUnrecoverable() {
+ final PackageManagerService packageManagerService = mPm;
+ final String packageName = mPackageName;
+ mHandler.post(() -> {
+ if (packageManagerService.deletePackageX(packageName,
+ PackageManager.VERSION_CODE_HIGHEST, UserHandle.USER_SYSTEM,
+ PackageManager.DELETE_ALL_USERS) != PackageManager.DELETE_SUCCEEDED) {
+ Slog.e(TAG, "Failed to uninstall package with failed dataloader: " + packageName);
+ }
+ });
+ }
+
/**
* If session should be sealed, then it's sealed to prevent further modification.
* If the session can't be sealed then it's destroyed.
@@ -2564,11 +2576,20 @@
IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
@Override
public void onStatusChanged(int dataLoaderId, int status) {
- try {
- if (status == IDataLoaderStatusListener.DATA_LOADER_DESTROYED) {
+ switch (status) {
+ case IDataLoaderStatusListener.DATA_LOADER_STOPPED:
+ case IDataLoaderStatusListener.DATA_LOADER_DESTROYED:
return;
- }
+ case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
+ onDataLoaderUnrecoverable();
+ return;
+ }
+ if (mDestroyed || mDataLoaderFinished) {
+ return;
+ }
+
+ try {
IDataLoader dataLoader = dataLoaderManager.getDataLoader(dataLoaderId);
if (dataLoader == null) {
mDataLoaderFinished = true;
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 29b2cd6..5f0c8fe3 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -598,6 +598,9 @@
// IFS callbacks.
void onPendingReads(dataloader::PendingReads pendingReads) final {
std::lock_guard lock{mOutFdLock};
+ if (mOutFd < 0) {
+ return;
+ }
CHECK(mIfs);
for (auto&& pendingRead : pendingReads) {
const android::dataloader::FileId& fileId = pendingRead.id;
@@ -611,13 +614,9 @@
android::incfs::toString(fileId).c_str());
continue;
}
- if (mRequestedFiles.insert(fileIdx).second) {
- if (!sendRequest(mOutFd, PREFETCH, fileIdx, blockIdx)) {
- ALOGE("Failed to request prefetch for fileid=%s. Ignore.",
- android::incfs::toString(fileId).c_str());
- mRequestedFiles.erase(fileIdx);
- mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
- }
+ if (mRequestedFiles.insert(fileIdx).second &&
+ !sendRequest(mOutFd, PREFETCH, fileIdx, blockIdx)) {
+ mRequestedFiles.erase(fileIdx);
}
sendRequest(mOutFd, BLOCK_MISSING, fileIdx, blockIdx);
}
@@ -634,7 +633,7 @@
}
if (res < 0) {
ALOGE("Failed to poll. Abort.");
- mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_UNRECOVERABLE);
break;
}
if (res == mEventFd) {
@@ -644,7 +643,7 @@
}
if (!readChunk(inout, data)) {
ALOGE("Failed to read a message. Abort.");
- mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_UNRECOVERABLE);
break;
}
auto remainingData = std::span(data);
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 4da0091..e24b76c 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1248,14 +1248,6 @@
}
switch (newStatus) {
- case IDataLoaderStatusListener::DATA_LOADER_NO_CONNECTION: {
- // TODO(b/150411019): handle data loader connection loss
- break;
- }
- case IDataLoaderStatusListener::DATA_LOADER_CONNECTION_OK: {
- // TODO(b/150411019): handle data loader connection loss
- break;
- }
case IDataLoaderStatusListener::DATA_LOADER_CREATED: {
if (startRequested) {
incrementalService.startDataLoader(mountId);
@@ -1277,6 +1269,10 @@
case IDataLoaderStatusListener::DATA_LOADER_IMAGE_NOT_READY: {
break;
}
+ case IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE: {
+ // Nothing for now. Rely on externalListener to handle this.
+ break;
+ }
default: {
LOG(WARNING) << "Unknown data loader status: " << newStatus
<< " for mount: " << mountId;