Loading services/core/java/com/android/server/pm/StagingManager.java +35 −13 Original line number Diff line number Diff line Loading @@ -77,7 +77,11 @@ import com.android.server.pm.parsing.pkg.AndroidPackageUtils; import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.rollback.WatchdogRollbackLogger; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; Loading @@ -102,6 +106,9 @@ public class StagingManager { private final PreRebootVerificationHandler mPreRebootVerificationHandler; private final Supplier<PackageParser2> mPackageParserSupplier; private final File mFailureReasonFile = new File("/metadata/staged-install/failure_reason.txt"); private String mFailureReason; @GuardedBy("mStagedSessions") private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>(); Loading @@ -125,6 +132,12 @@ public class StagingManager { mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mPreRebootVerificationHandler = new PreRebootVerificationHandler( BackgroundThread.get().getLooper()); if (mFailureReasonFile.exists()) { try (BufferedReader reader = new BufferedReader(new FileReader(mFailureReasonFile))) { mFailureReason = reader.readLine(); } catch (Exception ignore) { } } } /** Loading Loading @@ -383,10 +396,19 @@ public class StagingManager { } // Reverts apex sessions and user data (if checkpoint is supported). Also reboots the device. private void abortCheckpoint(String errorMsg) { Slog.e(TAG, "Aborting checkpoint: " + errorMsg); private void abortCheckpoint(int sessionId, String errorMsg) { String failureReason = "Failed to install sessionId: " + sessionId + " Error: " + errorMsg; Slog.e(TAG, failureReason); try { if (supportsCheckpoint() && needsCheckpoint()) { // Store failure reason for next reboot try (BufferedWriter writer = new BufferedWriter(new FileWriter(mFailureReasonFile))) { writer.write(failureReason); } catch (Exception e) { Slog.w(TAG, "Failed to save failure reason: ", e); } // Only revert apex sessions if device supports updating apex if (mApexManager.isApexSupported()) { mApexManager.revertActiveSessions(); Loading Loading @@ -592,14 +614,12 @@ public class StagingManager { // If checkpoint is supported, then we only resume sessions if we are in checkpointing // mode. If not, we fail all sessions. if (supportsCheckpoint() && !needsCheckpoint()) { // TODO(b/146343545): Persist failure reason across checkpoint reboot Slog.d(TAG, "Reverting back to safe state. Marking " + session.sessionId + " as failed."); String errorMsg = "Reverting back to safe state"; if (!TextUtils.isEmpty(mNativeFailureReason)) { errorMsg = "Entered fs-rollback mode and reverted session due to crashing " + "native process: " + mNativeFailureReason; String errorMsg = "Reverting back to safe state. Marking " + session.sessionId + " as failed"; if (!TextUtils.isEmpty(mFailureReason)) { errorMsg = errorMsg + ": " + mFailureReason; } Slog.d(TAG, errorMsg); session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, errorMsg); return; } Loading @@ -624,7 +644,7 @@ public class StagingManager { + "supposed to be activated"; session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg); abortCheckpoint(errorMsg); abortCheckpoint(session.sessionId, errorMsg); return; } if (isApexSessionFailed(apexSessionInfo)) { Loading @@ -636,7 +656,7 @@ public class StagingManager { } session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg); abortCheckpoint(errorMsg); abortCheckpoint(session.sessionId, errorMsg); return; } if (!apexSessionInfo.isActivated && !apexSessionInfo.isSuccess) { Loading @@ -647,7 +667,7 @@ public class StagingManager { + "didn't activate nor fail. Marking it as failed anyway."; session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg); abortCheckpoint(errorMsg); abortCheckpoint(session.sessionId, errorMsg); return; } } Loading @@ -664,7 +684,7 @@ public class StagingManager { installApksInSession(session); } catch (PackageManagerException e) { session.setStagedSessionFailed(e.error, e.getMessage()); abortCheckpoint(e.getMessage()); abortCheckpoint(session.sessionId, e.getMessage()); // If checkpoint is not supported, we have to handle failure for one staged session. if (!hasApex) { Loading Loading @@ -1189,6 +1209,8 @@ public class StagingManager { ctx.unregisterReceiver(this); } }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); mFailureReasonFile.delete(); } private static class LocalIntentReceiverAsync { Loading Loading
services/core/java/com/android/server/pm/StagingManager.java +35 −13 Original line number Diff line number Diff line Loading @@ -77,7 +77,11 @@ import com.android.server.pm.parsing.pkg.AndroidPackageUtils; import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.rollback.WatchdogRollbackLogger; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; Loading @@ -102,6 +106,9 @@ public class StagingManager { private final PreRebootVerificationHandler mPreRebootVerificationHandler; private final Supplier<PackageParser2> mPackageParserSupplier; private final File mFailureReasonFile = new File("/metadata/staged-install/failure_reason.txt"); private String mFailureReason; @GuardedBy("mStagedSessions") private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>(); Loading @@ -125,6 +132,12 @@ public class StagingManager { mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mPreRebootVerificationHandler = new PreRebootVerificationHandler( BackgroundThread.get().getLooper()); if (mFailureReasonFile.exists()) { try (BufferedReader reader = new BufferedReader(new FileReader(mFailureReasonFile))) { mFailureReason = reader.readLine(); } catch (Exception ignore) { } } } /** Loading Loading @@ -383,10 +396,19 @@ public class StagingManager { } // Reverts apex sessions and user data (if checkpoint is supported). Also reboots the device. private void abortCheckpoint(String errorMsg) { Slog.e(TAG, "Aborting checkpoint: " + errorMsg); private void abortCheckpoint(int sessionId, String errorMsg) { String failureReason = "Failed to install sessionId: " + sessionId + " Error: " + errorMsg; Slog.e(TAG, failureReason); try { if (supportsCheckpoint() && needsCheckpoint()) { // Store failure reason for next reboot try (BufferedWriter writer = new BufferedWriter(new FileWriter(mFailureReasonFile))) { writer.write(failureReason); } catch (Exception e) { Slog.w(TAG, "Failed to save failure reason: ", e); } // Only revert apex sessions if device supports updating apex if (mApexManager.isApexSupported()) { mApexManager.revertActiveSessions(); Loading Loading @@ -592,14 +614,12 @@ public class StagingManager { // If checkpoint is supported, then we only resume sessions if we are in checkpointing // mode. If not, we fail all sessions. if (supportsCheckpoint() && !needsCheckpoint()) { // TODO(b/146343545): Persist failure reason across checkpoint reboot Slog.d(TAG, "Reverting back to safe state. Marking " + session.sessionId + " as failed."); String errorMsg = "Reverting back to safe state"; if (!TextUtils.isEmpty(mNativeFailureReason)) { errorMsg = "Entered fs-rollback mode and reverted session due to crashing " + "native process: " + mNativeFailureReason; String errorMsg = "Reverting back to safe state. Marking " + session.sessionId + " as failed"; if (!TextUtils.isEmpty(mFailureReason)) { errorMsg = errorMsg + ": " + mFailureReason; } Slog.d(TAG, errorMsg); session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, errorMsg); return; } Loading @@ -624,7 +644,7 @@ public class StagingManager { + "supposed to be activated"; session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg); abortCheckpoint(errorMsg); abortCheckpoint(session.sessionId, errorMsg); return; } if (isApexSessionFailed(apexSessionInfo)) { Loading @@ -636,7 +656,7 @@ public class StagingManager { } session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg); abortCheckpoint(errorMsg); abortCheckpoint(session.sessionId, errorMsg); return; } if (!apexSessionInfo.isActivated && !apexSessionInfo.isSuccess) { Loading @@ -647,7 +667,7 @@ public class StagingManager { + "didn't activate nor fail. Marking it as failed anyway."; session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg); abortCheckpoint(errorMsg); abortCheckpoint(session.sessionId, errorMsg); return; } } Loading @@ -664,7 +684,7 @@ public class StagingManager { installApksInSession(session); } catch (PackageManagerException e) { session.setStagedSessionFailed(e.error, e.getMessage()); abortCheckpoint(e.getMessage()); abortCheckpoint(session.sessionId, e.getMessage()); // If checkpoint is not supported, we have to handle failure for one staged session. if (!hasApex) { Loading Loading @@ -1189,6 +1209,8 @@ public class StagingManager { ctx.unregisterReceiver(this); } }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); mFailureReasonFile.delete(); } private static class LocalIntentReceiverAsync { Loading