Merge "Prevent exceptions during staged install from crashing system server"
This commit is contained in:
committed by
Android (Google) Code Review
commit
2a83bfec54
@@ -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;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user