diff options
-rw-r--r-- | services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java | 87 |
1 files changed, 68 insertions, 19 deletions
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 9a65ae6dba4d..1475ab9df37b 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -780,6 +780,33 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { return enableRollbackForPackageSession(newRollback.rollback, packageSession); } + private void removeRollbackForPackageSessionId(int sessionId) { + if (LOCAL_LOGV) { + Slog.v(TAG, "removeRollbackForPackageSessionId=" + sessionId); + } + + synchronized (mLock) { + NewRollback newRollback = getNewRollbackForPackageSessionLocked(sessionId); + if (newRollback != null) { + Slog.w(TAG, "Delete new rollback id=" + newRollback.rollback.info.getRollbackId() + + " for session id=" + sessionId); + mNewRollbacks.remove(newRollback); + newRollback.rollback.delete(mAppDataRollbackHelper); + } + Iterator<Rollback> iter = mRollbacks.iterator(); + while (iter.hasNext()) { + Rollback rollback = iter.next(); + if (rollback.getStagedSessionId() == sessionId) { + Slog.w(TAG, "Delete rollback id=" + rollback.info.getRollbackId() + + " for session id=" + sessionId); + iter.remove(); + rollback.delete(mAppDataRollbackHelper); + break; + } + } + } + } + /** * Do code and userdata backups to enable rollback of the given session. * In case of multiPackage sessions, <code>session</code> should be one of @@ -944,7 +971,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } } - Rollback rollback = completeEnableRollback(newRollback, true); + Rollback rollback = completeEnableRollback(newRollback); if (rollback == null) { result.offer(-1); } else { @@ -1089,19 +1116,28 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { if (LOCAL_LOGV) { Slog.v(TAG, "SessionCallback.onFinished id=" + sessionId + " success=" + success); } - NewRollback newRollback; - synchronized (mLock) { - newRollback = getNewRollbackForPackageSessionLocked(sessionId); - if (newRollback != null) { - mNewRollbacks.remove(newRollback); + + if (success) { + NewRollback newRollback; + synchronized (mLock) { + newRollback = getNewRollbackForPackageSessionLocked(sessionId); + if (newRollback != null && newRollback.notifySessionWithSuccess()) { + mNewRollbacks.remove(newRollback); + } else { + // Not all child sessions finished with success. + // Don't enable the rollback yet. + newRollback = null; + } } - } - if (newRollback != null) { - Rollback rollback = completeEnableRollback(newRollback, success); - if (rollback != null && !rollback.isStaged()) { - makeRollbackAvailable(rollback); + if (newRollback != null) { + Rollback rollback = completeEnableRollback(newRollback); + if (rollback != null && !rollback.isStaged()) { + makeRollbackAvailable(rollback); + } } + } else { + removeRollbackForPackageSessionId(sessionId); } // Clear the queue so it will never be leaked to next tests. @@ -1116,16 +1152,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { * @return the Rollback instance for a successfully enable-completed rollback, * or null on error. */ - private Rollback completeEnableRollback(NewRollback newRollback, boolean success) { + private Rollback completeEnableRollback(NewRollback newRollback) { Rollback rollback = newRollback.rollback; if (LOCAL_LOGV) { - Slog.v(TAG, "completeEnableRollback id=" - + rollback.info.getRollbackId() + " success=" + success); - } - if (!success) { - // The install session was aborted, clean up the pending install. - rollback.delete(mAppDataRollbackHelper); - return null; + Slog.v(TAG, "completeEnableRollback id=" + rollback.info.getRollbackId()); } if (newRollback.isCancelled()) { @@ -1251,6 +1281,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @GuardedBy("mNewRollbackLock") private boolean mIsCancelled = false; + /** + * The number of sessions in the install which are notified with success by + * {@link PackageInstaller.SessionCallback#onFinished(int, boolean)}. + * This NewRollback will be enabled only after all child sessions finished with success. + */ + @GuardedBy("mNewRollbackLock") + private int mNumPackageSessionsWithSuccess; + private final Object mNewRollbackLock = new Object(); NewRollback(Rollback rollback, int[] packageSessionIds) { @@ -1322,6 +1360,17 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { int getPackageSessionIdCount() { return mPackageSessionIds.length; } + + /** + * Called when a child session finished with success. + * Returns true when all child sessions are notified with success. This NewRollback will be + * enabled only after all child sessions finished with success. + */ + boolean notifySessionWithSuccess() { + synchronized (mNewRollbackLock) { + return ++mNumPackageSessionsWithSuccess == mPackageSessionIds.length; + } + } } @GuardedBy("mLock") |