summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Samiul Islam <samiul@google.com>2020-10-29 18:23:30 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-10-29 18:23:30 +0000
commit2a83bfec54dceedff82ab60134846151ea5222c6 (patch)
tree28cec72e2beafc929a844a8a9e27fa05974d3b6a
parenta7753a9961630c9ce4b44c7a3f46ee017b01466d (diff)
parent7a5bf6ccd835ddfca146d876085d6c1d1278d768 (diff)
Merge "Prevent exceptions during staged install from crashing system server"
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java90
1 files changed, 47 insertions, 43 deletions
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 8dbd46482ae2..e99e301e6da1 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -485,7 +485,8 @@ public class StagingManager {
}
}
- private void resumeSession(@NonNull PackageInstallerSession session) {
+ private void resumeSession(@NonNull PackageInstallerSession session)
+ throws PackageManagerException {
Slog.d(TAG, "Resuming session " + session.sessionId);
final boolean hasApex = session.containsApexSession();
@@ -550,10 +551,8 @@ public class StagingManager {
if (apexSessionInfo == null) {
final String errorMsg = "apexd did not know anything about a staged session "
+ "supposed to be activated";
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- errorMsg);
- abortCheckpoint(session.sessionId, errorMsg);
- return;
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
}
if (isApexSessionFailed(apexSessionInfo)) {
String errorMsg = "APEX activation failed. Check logcat messages from apexd "
@@ -562,10 +561,8 @@ public class StagingManager {
errorMsg = "Session reverted due to crashing native process: "
+ mNativeFailureReason;
}
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- errorMsg);
- abortCheckpoint(session.sessionId, errorMsg);
- return;
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
}
if (!apexSessionInfo.isActivated && !apexSessionInfo.isSuccess) {
// Apexd did not apply the session for some unknown reason. There is no
@@ -573,43 +570,22 @@ public class StagingManager {
// it as failed.
final String errorMsg = "Staged session " + session.sessionId + "at boot "
+ "didn't activate nor fail. Marking it as failed anyway.";
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- errorMsg);
- abortCheckpoint(session.sessionId, errorMsg);
- return;
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
}
}
- // Handle apk and apk-in-apex installation
- try {
- if (hasApex) {
- checkInstallationOfApkInApexSuccessful(session);
- checkDuplicateApkInApex(session);
- snapshotAndRestoreForApexSession(session);
- Slog.i(TAG, "APEX packages in session " + session.sessionId
- + " were successfully activated. Proceeding with APK packages, if any");
- }
- // The APEX part of the session is activated, proceed with the installation of APKs.
- Slog.d(TAG, "Installing APK packages in session " + session.sessionId);
- installApksInSession(session);
- } catch (PackageManagerException e) {
- session.setStagedSessionFailed(e.error, e.getMessage());
- abortCheckpoint(session.sessionId, e.getMessage());
-
- // If checkpoint is not supported, we have to handle failure for one staged session.
- if (!hasApex) {
- return;
- }
- if (!mApexManager.revertActiveSessions()) {
- Slog.e(TAG, "Failed to abort APEXd session");
- } else {
- Slog.e(TAG,
- "Successfully aborted apexd session. Rebooting device in order to revert "
- + "to the previous state of APEXd.");
- mPowerManager.reboot(null);
- }
- return;
+ // Handle apk and apk-in-apex installation
+ if (hasApex) {
+ checkInstallationOfApkInApexSuccessful(session);
+ checkDuplicateApkInApex(session);
+ snapshotAndRestoreForApexSession(session);
+ Slog.i(TAG, "APEX packages in session " + session.sessionId
+ + " were successfully activated. Proceeding with APK packages, if any");
}
+ // The APEX part of the session is activated, proceed with the installation of APKs.
+ Slog.d(TAG, "Installing APK packages in session " + session.sessionId);
+ installApksInSession(session);
Slog.d(TAG, "Marking session " + session.sessionId + " as applied");
session.setStagedSessionApplied();
@@ -633,6 +609,25 @@ public class StagingManager {
}
}
+ void onInstallationFailure(PackageInstallerSession session, PackageManagerException e) {
+ session.setStagedSessionFailed(e.error, e.getMessage());
+ abortCheckpoint(session.sessionId, e.getMessage());
+
+ // If checkpoint is not supported, we have to handle failure for one staged session.
+ if (!session.containsApexSession()) {
+ return;
+ }
+
+ if (!mApexManager.revertActiveSessions()) {
+ Slog.e(TAG, "Failed to abort APEXd session");
+ } else {
+ Slog.e(TAG,
+ "Successfully aborted apexd session. Rebooting device in order to revert "
+ + "to the previous state of APEXd.");
+ mPowerManager.reboot(null);
+ }
+ }
+
private String getReasonForRevert() {
if (!TextUtils.isEmpty(mFailureReason)) {
return mFailureReason;
@@ -933,7 +928,16 @@ public class StagingManager {
} else {
// Session had already being marked ready. Start the checks to verify if there is any
// follow-up work.
- resumeSession(session);
+ try {
+ resumeSession(session);
+ } catch (PackageManagerException e) {
+ onInstallationFailure(session, e);
+ } catch (Exception e) {
+ final String errorMsg = "Staged install failed due to unhandled exception";
+ Slog.e(TAG, errorMsg, e);
+ onInstallationFailure(session, new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg));
+ }
}
}