Merge changes Ie95789c9,I3d800491,I31f6b981,Ia3a4116b,I7edd3cf7

* changes:
  Rewrite handling of failed sessions (2/n)
  Rewrite the broadcast receiver for ACTION_CANCEL_ENABLE_ROLLBACK (1/n)
  Remove #mNewRollbacks (10/n)
  Put rollbacks into #mRollbacks (9/n)
  Add a flag to facilitate merging 2 rollback collections (8/n)
This commit is contained in:
JW Wang
2020-02-07 14:36:33 +00:00
committed by Android (Google) Code Review
3 changed files with 67 additions and 62 deletions

View File

@@ -216,6 +216,10 @@ public final class RollbackManager {
* across device reboot, by simulating what happens on reboot without
* actually rebooting the device.
*
* Note rollbacks in the process of enabling will be lost after calling
* this method since they are not persisted yet. Don't call this method
* in the middle of the install process.
*
* @throws SecurityException if the caller does not have appropriate permissions.
*
* @hide

View File

@@ -181,6 +181,15 @@ class Rollback {
@GuardedBy("mLock")
private int mNumPackageSessionsWithSuccess;
/**
* A temp flag to facilitate merging of the 2 rollback collections managed by
* RollbackManagerServiceImpl. True if this rollback is in the process of enabling and was
* originally managed by RollbackManagerServiceImpl#mNewRollbacks.
* TODO: remove this flag when merge is completed.
*/
@GuardedBy("mLock")
private boolean mIsNewRollback = false;
/**
* Constructs a new, empty Rollback instance.
*
@@ -829,6 +838,18 @@ class Rollback {
}
}
void setIsNewRollback(boolean newRollback) {
synchronized (mLock) {
mIsNewRollback = newRollback;
}
}
boolean isNewRollback() {
synchronized (mLock) {
return mIsNewRollback;
}
}
static String rollbackStateToString(@RollbackState int state) {
switch (state) {
case Rollback.ROLLBACK_STATE_ENABLING: return "enabling";

View File

@@ -19,6 +19,7 @@ package com.android.server.rollback;
import android.Manifest;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.AppOpsManager;
@@ -50,7 +51,6 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Log;
import android.util.LongArrayQueue;
@@ -121,10 +121,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
@GuardedBy("mLock")
private final SparseBooleanArray mAllocatedRollbackIds = new SparseBooleanArray();
// Rollbacks we are in the process of enabling.
@GuardedBy("mLock")
private final Set<Rollback> mNewRollbacks = new ArraySet<>();
// The list of all rollbacks, including available and committed rollbacks.
@GuardedBy("mLock")
private final List<Rollback> mRollbacks;
@@ -240,17 +236,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Slog.v(TAG, "broadcast=ACTION_CANCEL_ENABLE_ROLLBACK token=" + token);
}
synchronized (mLock) {
Rollback found = null;
for (Rollback newRollback : mNewRollbacks) {
if (newRollback.hasToken(token)) {
found = newRollback;
for (int i = 0; i < mRollbacks.size(); ++i) {
Rollback rollback = mRollbacks.get(i);
if (rollback.hasToken(token) && rollback.isEnabling()) {
mRollbacks.remove(i);
rollback.delete(mAppDataRollbackHelper);
break;
}
}
if (found != null) {
mNewRollbacks.remove(found);
found.delete(mAppDataRollbackHelper);
}
}
}
}
@@ -442,15 +435,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
rollback.delete(mAppDataRollbackHelper);
}
}
Iterator<Rollback> iter2 = mNewRollbacks.iterator();
while (iter2.hasNext()) {
Rollback newRollback = iter2.next();
if (newRollback.includesPackage(packageName)) {
iter2.remove();
newRollback.delete(mAppDataRollbackHelper);
}
}
}
}
@@ -810,7 +794,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
newRollback = getNewRollbackForPackageSessionLocked(packageSession.getSessionId());
if (newRollback == null) {
newRollback = createNewRollbackLocked(parentSession);
mNewRollbacks.add(newRollback);
mRollbacks.add(newRollback);
newRollback.setIsNewRollback(true);
}
}
newRollback.addToken(token);
@@ -818,34 +803,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
return enableRollbackForPackageSession(newRollback, packageSession);
}
@WorkerThread
private void removeRollbackForPackageSessionId(int sessionId) {
if (LOCAL_LOGV) {
Slog.v(TAG, "removeRollbackForPackageSessionId=" + sessionId);
}
synchronized (mLock) {
Rollback newRollback = getNewRollbackForPackageSessionLocked(sessionId);
if (newRollback != null) {
Slog.w(TAG, "Delete new rollback id=" + newRollback.info.getRollbackId()
+ " for session id=" + sessionId);
mNewRollbacks.remove(newRollback);
newRollback.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
@@ -966,15 +923,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
+ " users=" + Arrays.toString(userIds));
}
synchronized (mLock) {
// staged installs
for (int i = 0; i < mRollbacks.size(); i++) {
Rollback rollback = mRollbacks.get(i);
rollback.snapshotUserData(packageName, userIds, mAppDataRollbackHelper);
}
// non-staged installs
for (Rollback rollback : mNewRollbacks) {
rollback.snapshotUserData(packageName, userIds, mAppDataRollbackHelper);
}
}
}
@@ -1200,7 +1152,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
synchronized (mLock) {
newRollback = getNewRollbackForPackageSessionLocked(sessionId);
if (newRollback != null && newRollback.notifySessionWithSuccess()) {
mNewRollbacks.remove(newRollback);
mRollbacks.remove(newRollback);
newRollback.setIsNewRollback(false);
} else {
// Not all child sessions finished with success.
// Don't enable the rollback yet.
@@ -1215,7 +1168,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
}
} else {
removeRollbackForPackageSessionId(sessionId);
synchronized (mLock) {
Rollback rollback = getRollbackForSessionLocked(sessionId);
if (rollback != null && rollback.isEnabling()) {
Slog.w(TAG, "Delete rollback id=" + rollback.info.getRollbackId()
+ " for failed session id=" + sessionId);
mRollbacks.remove(rollback);
rollback.delete(mAppDataRollbackHelper);
}
}
}
}
}
@@ -1375,6 +1336,25 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
return rollback;
}
/**
* Returns the Rollback associated with the given session if parent or child session id matches.
* Returns null if not found.
*/
@WorkerThread
@GuardedBy("mLock")
@Nullable
private Rollback getRollbackForSessionLocked(int sessionId) {
// We expect mRollbacks to be a very small list; linear search should be plenty fast.
for (int i = 0; i < mRollbacks.size(); ++i) {
Rollback rollback = mRollbacks.get(i);
if (rollback.getStagedSessionId() == sessionId
|| rollback.containsSessionId(sessionId)) {
return rollback;
}
}
return null;
}
/**
* Returns the NewRollback associated with the given package session.
* Returns null if no NewRollback is found for the given package
@@ -1383,11 +1363,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
@WorkerThread
@GuardedBy("mLock")
Rollback getNewRollbackForPackageSessionLocked(int packageSessionId) {
// We expect mNewRollbacks to be a very small list; linear search
// We expect mRollbacks to be a very small list; linear search
// should be plenty fast.
for (Rollback newRollback: mNewRollbacks) {
if (newRollback.containsSessionId(packageSessionId)) {
return newRollback;
for (Rollback rollback: mRollbacks) {
if (rollback.isNewRollback() && rollback.containsSessionId(packageSessionId)) {
return rollback;
}
}
return null;