Merge "Make Rollback fields private and add accessors."

This commit is contained in:
Oli Lan
2019-09-10 14:07:16 +00:00
committed by Android (Google) Code Review
4 changed files with 233 additions and 63 deletions

View File

@@ -65,7 +65,7 @@ class Rollback {
/**
* The directory where the rollback data is stored.
*/
public final File backupDir;
private final File mBackupDir;
/**
* The time when the upgrade occurred, for purposes of expiring
@@ -74,24 +74,24 @@ class Rollback {
* The timestamp is not applicable for all rollback states, but we make
* sure to keep it non-null to avoid potential errors there.
*/
public @NonNull Instant timestamp;
private @NonNull Instant mTimestamp;
/**
* The session ID for the staged session if this rollback data represents a staged session,
* {@code -1} otherwise.
*/
public final int stagedSessionId;
private final int mStagedSessionId;
/**
* The current state of the rollback.
* ENABLING, AVAILABLE, or COMMITTED.
*/
public @RollbackState int state;
private @RollbackState int mState;
/**
* The id of the post-reboot apk session for a staged install, if any.
*/
public int apkSessionId = -1;
private int mApkSessionId = -1;
/**
* True if we are expecting the package manager to call restoreUserData
@@ -99,7 +99,7 @@ class Rollback {
* has not yet been fully applied.
*/
// NOTE: All accesses to this field are from the RollbackManager handler thread.
public boolean restoreUserDataInProgress = false;
private boolean mRestoreUserDataInProgress = false;
/**
* Constructs a new, empty Rollback instance.
@@ -114,10 +114,10 @@ class Rollback {
/* isStaged */ stagedSessionId != -1,
/* causePackages */ new ArrayList<>(),
/* committedSessionId */ -1);
this.backupDir = backupDir;
this.stagedSessionId = stagedSessionId;
this.state = ROLLBACK_STATE_ENABLING;
this.timestamp = Instant.now();
mBackupDir = backupDir;
mStagedSessionId = stagedSessionId;
mState = ROLLBACK_STATE_ENABLING;
mTimestamp = Instant.now();
}
/**
@@ -126,21 +126,115 @@ class Rollback {
Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
@RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress) {
this.info = info;
this.backupDir = backupDir;
this.timestamp = timestamp;
this.stagedSessionId = stagedSessionId;
this.state = state;
this.apkSessionId = apkSessionId;
this.restoreUserDataInProgress = restoreUserDataInProgress;
mBackupDir = backupDir;
mTimestamp = timestamp;
mStagedSessionId = stagedSessionId;
mState = state;
mApkSessionId = apkSessionId;
mRestoreUserDataInProgress = restoreUserDataInProgress;
}
/**
* Whether the rollback is for rollback of a staged install.
*/
public boolean isStaged() {
boolean isStaged() {
return info.isStaged();
}
/**
* Returns the directory in which rollback data should be stored.
*/
File getBackupDir() {
return mBackupDir;
}
/**
* Returns the time when the upgrade occurred, for purposes of expiring rollback data.
*/
Instant getTimestamp() {
return mTimestamp;
}
/**
* Sets the time at which upgrade occurred.
*/
void setTimestamp(Instant timestamp) {
mTimestamp = timestamp;
}
/**
* Returns the session ID for the staged session if this rollback data represents a staged
* session, or {@code -1} otherwise.
*/
int getStagedSessionId() {
return mStagedSessionId;
}
/**
* Returns true if the rollback is in the ENABLING state.
*/
boolean isEnabling() {
return mState == ROLLBACK_STATE_ENABLING;
}
/**
* Returns true if the rollback is in the AVAILABLE state.
*/
boolean isAvailable() {
return mState == ROLLBACK_STATE_AVAILABLE;
}
/**
* Returns true if the rollback is in the COMMITTED state.
*/
boolean isCommitted() {
return mState == ROLLBACK_STATE_COMMITTED;
}
/**
* Sets the state of the rollback to AVAILABLE.
*/
void setAvailable() {
mState = ROLLBACK_STATE_AVAILABLE;
}
/**
* Sets the state of the rollback to COMMITTED.
*/
void setCommitted() {
mState = ROLLBACK_STATE_COMMITTED;
}
/**
* Returns the id of the post-reboot apk session for a staged install, if any.
*/
int getApkSessionId() {
return mApkSessionId;
}
/**
* Sets the id of the post-reboot apk session for a staged install.
*/
void setApkSessionId(int apkSessionId) {
mApkSessionId = apkSessionId;
}
/**
* Returns true if we are expecting the package manager to call restoreUserData for this
* rollback because it has just been committed but the rollback has not yet been fully applied.
*/
boolean isRestoreUserDataInProgress() {
return mRestoreUserDataInProgress;
}
/**
* Sets whether we are expecting the package manager to call restoreUserData for this
* rollback because it has just been committed but the rollback has not yet been fully applied.
*/
void setRestoreUserDataInProgress(boolean restoreUserDataInProgress) {
mRestoreUserDataInProgress = restoreUserDataInProgress;
}
static String rollbackStateToString(@RollbackState int state) {
switch (state) {
case Rollback.ROLLBACK_STATE_ENABLING: return "enabling";
@@ -160,7 +254,7 @@ class Rollback {
throw new ParseException("Invalid rollback state: " + state, 0);
}
public String getStateAsString() {
return rollbackStateToString(state);
String getStateAsString() {
return rollbackStateToString(mState);
}
}

View File

@@ -282,7 +282,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
List<RollbackInfo> rollbacks = new ArrayList<>();
for (int i = 0; i < mRollbacks.size(); ++i) {
Rollback rollback = mRollbacks.get(i);
if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE) {
if (rollback.isAvailable()) {
rollbacks.add(rollback.info);
}
}
@@ -298,7 +298,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
List<RollbackInfo> rollbacks = new ArrayList<>();
for (int i = 0; i < mRollbacks.size(); ++i) {
Rollback rollback = mRollbacks.get(i);
if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) {
if (rollback.isCommitted()) {
rollbacks.add(rollback.info);
}
}
@@ -332,7 +332,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) {
Rollback rollback = iter.next();
rollback.timestamp = rollback.timestamp.plusMillis(timeDifference);
rollback.setTimestamp(rollback.getTimestamp().plusMillis(timeDifference));
saveRollback(rollback);
}
}
@@ -358,7 +358,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Slog.i(TAG, "Initiating rollback");
Rollback rollback = getRollbackForId(rollbackId);
if (rollback == null || rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) {
if (rollback == null || !rollback.isAvailable()) {
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
"Rollback unavailable");
return;
@@ -454,8 +454,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// TODO: Could this cause a rollback to be
// resurrected if it should otherwise have
// expired by now?
rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE;
rollback.restoreUserDataInProgress = false;
rollback.setAvailable();
rollback.setRestoreUserDataInProgress(false);
}
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_INSTALL,
"Rollback downgrade install failed: "
@@ -468,7 +468,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
if (!rollback.isStaged()) {
// All calls to restoreUserData should have
// completed by now for a non-staged install.
rollback.restoreUserDataInProgress = false;
rollback.setRestoreUserDataInProgress(false);
}
rollback.info.setCommittedSessionId(parentSessionId);
@@ -490,8 +490,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
);
synchronized (mLock) {
rollback.state = Rollback.ROLLBACK_STATE_COMMITTED;
rollback.restoreUserDataInProgress = true;
rollback.setCommitted();
rollback.setRestoreUserDataInProgress(true);
}
parentSession.commit(receiver.getIntentSender());
} catch (IOException e) {
@@ -618,9 +618,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
synchronized (mLock) {
for (Rollback rollback : mRollbacks) {
if (rollback.isStaged()) {
if (rollback.state == Rollback.ROLLBACK_STATE_ENABLING) {
if (rollback.isEnabling()) {
enabling.add(rollback);
} else if (rollback.restoreUserDataInProgress) {
} else if (rollback.isRestoreUserDataInProgress()) {
restoreInProgress.add(rollback);
}
@@ -635,8 +635,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
for (Rollback rollback : enabling) {
PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo session = installer.getSessionInfo(
rollback.stagedSessionId);
PackageInstaller.SessionInfo session =
installer.getSessionInfo(rollback.getStagedSessionId());
if (session == null || session.isStagedSessionFailed()) {
// TODO: Do we need to remove this from
// mRollbacks, or is it okay to leave as
@@ -650,13 +650,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
for (Rollback rollback : restoreInProgress) {
PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo session = installer.getSessionInfo(
rollback.stagedSessionId);
PackageInstaller.SessionInfo session =
installer.getSessionInfo(rollback.getStagedSessionId());
// TODO: What if session is null?
if (session != null) {
if (session.isStagedSessionApplied() || session.isStagedSessionFailed()) {
synchronized (mLock) {
rollback.restoreUserDataInProgress = false;
rollback.setRestoreUserDataInProgress(false);
}
saveRollback(rollback);
}
@@ -694,8 +694,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
while (iter.hasNext()) {
Rollback rollback = iter.next();
// TODO: Should we remove rollbacks in the ENABLING state here?
if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE
|| rollback.state == Rollback.ROLLBACK_STATE_ENABLING) {
if (rollback.isEnabling() || rollback.isAvailable()) {
for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName)
&& !packageVersionsEqual(
@@ -761,15 +760,16 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) {
Rollback rollback = iter.next();
if (rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) {
if (!rollback.isAvailable()) {
continue;
}
if (!now.isBefore(
rollback.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) {
rollback.getTimestamp()
.plusMillis(mRollbackLifetimeDurationInMillis))) {
iter.remove();
deleteRollback(rollback);
} else if (oldest == null || oldest.isAfter(rollback.timestamp)) {
oldest = rollback.timestamp;
} else if (oldest == null || oldest.isAfter(rollback.getTimestamp())) {
oldest = rollback.getTimestamp();
}
}
}
@@ -877,7 +877,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) {
Rollback rollback = mRollbacks.get(i);
if (rollback.apkSessionId == parentSession.getSessionId()) {
if (rollback.getApkSessionId() == parentSession.getSessionId()) {
// This is the apk session for a staged session with rollback enabled. We do not
// need to create a new rollback for this session.
return true;
@@ -1020,7 +1020,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// staged installs
for (int i = 0; i < mRollbacks.size(); i++) {
Rollback rollback = mRollbacks.get(i);
if (rollback.state != Rollback.ROLLBACK_STATE_ENABLING) {
if (!rollback.isEnabling()) {
continue;
}
@@ -1053,7 +1053,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) {
Rollback candidate = mRollbacks.get(i);
if (candidate.restoreUserDataInProgress) {
if (candidate.isRestoreUserDataInProgress()) {
info = getPackageRollbackInfo(candidate, packageName);
if (info != null) {
rollback = candidate;
@@ -1146,8 +1146,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) {
Rollback candidate = mRollbacks.get(i);
if (candidate.stagedSessionId == originalSessionId) {
candidate.apkSessionId = apkSessionId;
if (candidate.getStagedSessionId() == originalSessionId) {
candidate.setApkSessionId(apkSessionId);
rollback = candidate;
break;
}
@@ -1333,8 +1333,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// to a new package being installed. Won't this revive an expired
// rollback? Consider adding a ROLLBACK_STATE_EXPIRED to address this.
synchronized (mLock) {
rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE;
rollback.timestamp = Instant.now();
rollback.setAvailable();
rollback.setTimestamp(Instant.now());
}
saveRollback(rollback);
@@ -1434,9 +1434,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
ipw.println(info.getRollbackId() + ":");
ipw.increaseIndent();
ipw.println("-state: " + rollback.getStateAsString());
ipw.println("-timestamp: " + rollback.timestamp);
if (rollback.stagedSessionId != -1) {
ipw.println("-stagedSessionId: " + rollback.stagedSessionId);
ipw.println("-timestamp: " + rollback.getTimestamp());
if (rollback.getStagedSessionId() != -1) {
ipw.println("-stagedSessionId: " + rollback.getStagedSessionId());
}
ipw.println("-packages:");
ipw.increaseIndent();
@@ -1446,7 +1446,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
+ " -> " + pkg.getVersionRolledBackTo().getLongVersionCode());
}
ipw.decreaseIndent();
if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) {
if (rollback.isCommitted()) {
ipw.println("-causePackages:");
ipw.increaseIndent();
for (VersionedPackage cPkg : info.getCausePackages()) {

View File

@@ -17,7 +17,6 @@
package com.android.server.rollback;
import static com.android.server.rollback.Rollback.rollbackStateFromString;
import static com.android.server.rollback.Rollback.rollbackStateToString;
import android.annotation.NonNull;
import android.content.pm.VersionedPackage;
@@ -216,7 +215,7 @@ class RollbackStore {
static void backupPackageCodePath(Rollback rollback, String packageName, String codePath)
throws IOException {
File sourceFile = new File(codePath);
File targetDir = new File(rollback.backupDir, packageName);
File targetDir = new File(rollback.getBackupDir(), packageName);
targetDir.mkdirs();
File targetFile = new File(targetDir, sourceFile.getName());
@@ -229,7 +228,7 @@ class RollbackStore {
* Includes the base apk and any splits. Returns null if none found.
*/
static File[] getPackageCodePaths(Rollback rollback, String packageName) {
File targetDir = new File(rollback.backupDir, packageName);
File targetDir = new File(rollback.getBackupDir(), packageName);
File[] files = targetDir.listFiles();
if (files == null || files.length == 0) {
return null;
@@ -243,7 +242,7 @@ class RollbackStore {
*/
static void deletePackageCodePaths(Rollback rollback) {
for (PackageRollbackInfo info : rollback.info.getPackages()) {
File targetDir = new File(rollback.backupDir, info.getPackageName());
File targetDir = new File(rollback.getBackupDir(), info.getPackageName());
removeFile(targetDir);
}
}
@@ -255,13 +254,13 @@ class RollbackStore {
try {
JSONObject dataJson = new JSONObject();
dataJson.put("info", rollbackInfoToJson(rollback.info));
dataJson.put("timestamp", rollback.timestamp.toString());
dataJson.put("stagedSessionId", rollback.stagedSessionId);
dataJson.put("state", rollbackStateToString(rollback.state));
dataJson.put("apkSessionId", rollback.apkSessionId);
dataJson.put("restoreUserDataInProgress", rollback.restoreUserDataInProgress);
dataJson.put("timestamp", rollback.getTimestamp().toString());
dataJson.put("stagedSessionId", rollback.getStagedSessionId());
dataJson.put("state", rollback.getStateAsString());
dataJson.put("apkSessionId", rollback.getApkSessionId());
dataJson.put("restoreUserDataInProgress", rollback.isRestoreUserDataInProgress());
PrintWriter pw = new PrintWriter(new File(rollback.backupDir, "rollback.json"));
PrintWriter pw = new PrintWriter(new File(rollback.getBackupDir(), "rollback.json"));
pw.println(dataJson.toString());
pw.close();
} catch (JSONException e) {
@@ -273,7 +272,7 @@ class RollbackStore {
* Removes all persistent storage associated with the given rollback.
*/
void deleteRollback(Rollback rollback) {
removeFile(rollback.backupDir);
removeFile(rollback.getBackupDir());
}
/**

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.rollback;
import static com.google.common.truth.Truth.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.File;
@RunWith(JUnit4.class)
public class RollbackUnitTest {
@Test
public void newEmptyStagedRollbackDefaults() {
int rollbackId = 123;
int sessionId = 567;
File file = new File("/test/testing");
Rollback rollback = new Rollback(rollbackId, file, sessionId);
assertThat(rollback.isEnabling()).isTrue();
assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
assertThat(rollback.isStaged()).isTrue();
assertThat(rollback.getStagedSessionId()).isEqualTo(567);
}
@Test
public void newEmptyNonStagedRollbackDefaults() {
int rollbackId = 123;
File file = new File("/test/testing");
Rollback rollback = new Rollback(rollbackId, file, -1);
assertThat(rollback.isEnabling()).isTrue();
assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
assertThat(rollback.isStaged()).isFalse();
}
@Test
public void rollbackStateChanges() {
Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
assertThat(rollback.isEnabling()).isTrue();
assertThat(rollback.isAvailable()).isFalse();
assertThat(rollback.isCommitted()).isFalse();
rollback.setAvailable();
assertThat(rollback.isEnabling()).isFalse();
assertThat(rollback.isAvailable()).isTrue();
assertThat(rollback.isCommitted()).isFalse();
rollback.setCommitted();
assertThat(rollback.isEnabling()).isFalse();
assertThat(rollback.isAvailable()).isFalse();
assertThat(rollback.isCommitted()).isTrue();
}
}