From f712ee0633de9bd5bcfa43edffe9eff0903d8611 Mon Sep 17 00:00:00 2001
From: JW Wang
Date: Tue, 8 Sep 2020 11:00:17 +0800
Subject: [PATCH 1/5] Let #startPreRebootVerification take a session object
(1/n)
Most callers can pass a session object directly. We don't need to
call getStagedSession() to remap an id to a session object.
Bug: 167996901
Test: atest StagedInstallTest StagedInstallInternalTest
Change-Id: If5af54bc15b98a085f55fa4669da437ab9d2506e
---
.../java/com/android/server/pm/StagingManager.java | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index e5e94482da12b..58713c1efcb3c 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -558,7 +558,7 @@ public class StagingManager {
// failed when not in checkpoint mode, hence it is being processed separately.
Slog.d(TAG, "Found pending staged session " + session.sessionId + " still to "
+ "be verified, resuming pre-reboot verification");
- mPreRebootVerificationHandler.startPreRebootVerification(session.sessionId);
+ mPreRebootVerificationHandler.startPreRebootVerification(session);
return;
}
}
@@ -873,7 +873,7 @@ public class StagingManager {
void commitSession(@NonNull PackageInstallerSession session) {
updateStoredSession(session);
- mPreRebootVerificationHandler.startPreRebootVerification(session.sessionId);
+ mPreRebootVerificationHandler.startPreRebootVerification(session);
}
private int getSessionIdForParentOrSelf(PackageInstallerSession session) {
@@ -1106,7 +1106,7 @@ public class StagingManager {
if (!session.isStagedSessionReady()) {
// The framework got restarted before the pre-reboot verification could complete,
// restart the verification.
- mPreRebootVerificationHandler.startPreRebootVerification(session.sessionId);
+ mPreRebootVerificationHandler.startPreRebootVerification(session);
} else {
// Session had already being marked ready. Start the checks to verify if there is any
// follow-up work.
@@ -1261,14 +1261,16 @@ public class StagingManager {
mIsReady = true;
if (mPendingSessionIds != null) {
for (int i = 0; i < mPendingSessionIds.size(); i++) {
- startPreRebootVerification(mPendingSessionIds.get(i));
+ PackageInstallerSession session = getStagedSession(mPendingSessionIds.get(i));
+ startPreRebootVerification(session);
}
mPendingSessionIds = null;
}
}
// Method for starting the pre-reboot verification
- private synchronized void startPreRebootVerification(int sessionId) {
+ private synchronized void startPreRebootVerification(PackageInstallerSession session) {
+ int sessionId = session.sessionId;
if (!mIsReady) {
if (mPendingSessionIds == null) {
mPendingSessionIds = new IntArray();
@@ -1277,7 +1279,6 @@ public class StagingManager {
return;
}
- PackageInstallerSession session = getStagedSession(sessionId);
if (session != null && session.notifyStagedStartPreRebootVerification()) {
Slog.d(TAG, "Starting preRebootVerification for session " + sessionId);
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, 0).sendToTarget();
From dbe5e57ecf13a2e86c5b45d4d92a67ecf1501662 Mon Sep 17 00:00:00 2001
From: JW Wang
Date: Tue, 8 Sep 2020 11:20:06 +0800
Subject: [PATCH 2/5] Pass rollbackId to submitSessionToApexService() (2/n)
Do the plumbing to pass rollbackId from
handlePreRebootVerification_Start() all the way to
submitSessionToApexService().
This allows us to remove mSessionRollbackIds.
Bug: 167996901
Test: atest StagedInstallTest StagedInstallInternalTest
Change-Id: Icc357561a4743683b3aae796ed7723eec66e3a6e
---
.../com/android/server/pm/StagingManager.java | 55 +++++++++----------
1 file changed, 26 insertions(+), 29 deletions(-)
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 58713c1efcb3c..b00094cb813aa 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -60,7 +60,6 @@ import android.util.ArraySet;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.SparseIntArray;
import android.util.apk.ApkSignatureVerifier;
import com.android.internal.annotations.GuardedBy;
@@ -111,9 +110,6 @@ public class StagingManager {
@GuardedBy("mStagedSessions")
private final SparseArray mStagedSessions = new SparseArray<>();
- @GuardedBy("mStagedSessions")
- private final SparseIntArray mSessionRollbackIds = new SparseIntArray();
-
@GuardedBy("mFailedPackageNames")
private final List mFailedPackageNames = new ArrayList<>();
private String mNativeFailureReason;
@@ -236,8 +232,8 @@ public class StagingManager {
+ " compatible with the one currently installed on device");
}
- private List submitSessionToApexService(
- @NonNull PackageInstallerSession session) throws PackageManagerException {
+ private List submitSessionToApexService(@NonNull PackageInstallerSession session,
+ int rollbackId) throws PackageManagerException {
final IntArray childSessionIds = new IntArray();
if (session.isMultiPackage()) {
for (PackageInstallerSession s : session.getChildSessions()) {
@@ -251,14 +247,11 @@ public class StagingManager {
apexSessionParams.childSessionIds = childSessionIds.toArray();
if (session.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
apexSessionParams.isRollback = true;
- apexSessionParams.rollbackId = retrieveRollbackIdForCommitSession(session.sessionId);
+ apexSessionParams.rollbackId = rollbackId;
} else {
- synchronized (mStagedSessions) {
- int rollbackId = mSessionRollbackIds.get(session.sessionId, -1);
- if (rollbackId != -1) {
- apexSessionParams.hasRollbackEnabled = true;
- apexSessionParams.rollbackId = rollbackId;
- }
+ if (rollbackId != -1) {
+ apexSessionParams.hasRollbackEnabled = true;
+ apexSessionParams.rollbackId = rollbackId;
}
}
// submitStagedSession will throw a PackageManagerException if apexd verification fails,
@@ -997,7 +990,6 @@ public class StagingManager {
void abortSession(@NonNull PackageInstallerSession session) {
synchronized (mStagedSessions) {
mStagedSessions.remove(session.sessionId);
- mSessionRollbackIds.delete(session.sessionId);
}
}
@@ -1229,6 +1221,7 @@ public class StagingManager {
@Override
public void handleMessage(Message msg) {
final int sessionId = msg.arg1;
+ final int rollbackId = msg.arg2;
final PackageInstallerSession session = getStagedSession(sessionId);
if (session == null) {
Slog.wtf(TAG, "Session disappeared in the middle of pre-reboot verification: "
@@ -1245,7 +1238,7 @@ public class StagingManager {
handlePreRebootVerification_Start(session);
break;
case MSG_PRE_REBOOT_VERIFICATION_APEX:
- handlePreRebootVerification_Apex(session);
+ handlePreRebootVerification_Apex(session, rollbackId);
break;
case MSG_PRE_REBOOT_VERIFICATION_APK:
handlePreRebootVerification_Apk(session);
@@ -1281,7 +1274,7 @@ public class StagingManager {
if (session != null && session.notifyStagedStartPreRebootVerification()) {
Slog.d(TAG, "Starting preRebootVerification for session " + sessionId);
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, 0).sendToTarget();
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, -1).sendToTarget();
}
}
@@ -1303,16 +1296,16 @@ public class StagingManager {
session.notifyStagedEndPreRebootVerification();
}
- private void notifyPreRebootVerification_Start_Complete(int sessionId) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, sessionId, 0).sendToTarget();
+ private void notifyPreRebootVerification_Start_Complete(int sessionId, int rollbackId) {
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, sessionId, rollbackId).sendToTarget();
}
private void notifyPreRebootVerification_Apex_Complete(int sessionId) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, sessionId, 0).sendToTarget();
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, sessionId, -1).sendToTarget();
}
private void notifyPreRebootVerification_Apk_Complete(int sessionId) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, sessionId, 0).sendToTarget();
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, sessionId, -1).sendToTarget();
}
/**
@@ -1321,6 +1314,7 @@ public class StagingManager {
* See {@link PreRebootVerificationHandler} to see all nodes of pre reboot verification
*/
private void handlePreRebootVerification_Start(@NonNull PackageInstallerSession session) {
+ int rollbackId = -1;
if ((session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// If rollback is enabled for this session, we call through to the RollbackManager
// with the list of sessions it must enable rollback for. Note that
@@ -1330,19 +1324,21 @@ public class StagingManager {
try {
// NOTE: To stay consistent with the non-staged install flow, we don't fail the
// entire install if rollbacks can't be enabled.
- int rollbackId = rm.notifyStagedSession(session.sessionId);
- if (rollbackId != -1) {
- synchronized (mStagedSessions) {
- mSessionRollbackIds.put(session.sessionId, rollbackId);
- }
- }
+ rollbackId = rm.notifyStagedSession(session.sessionId);
} catch (RuntimeException re) {
Slog.e(TAG, "Failed to notifyStagedSession for session: "
+ session.sessionId, re);
}
+ } else if (session.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
+ try {
+ rollbackId = retrieveRollbackIdForCommitSession(session.sessionId);
+ } catch (PackageManagerException e) {
+ onPreRebootVerificationFailure(session, e.error, e.getMessage());
+ return;
+ }
}
- notifyPreRebootVerification_Start_Complete(session.sessionId);
+ notifyPreRebootVerification_Start_Complete(session.sessionId, rollbackId);
}
/**
@@ -1353,7 +1349,8 @@ public class StagingManager {
* validates signatures of apex files
*
*/
- private void handlePreRebootVerification_Apex(@NonNull PackageInstallerSession session) {
+ private void handlePreRebootVerification_Apex(
+ @NonNull PackageInstallerSession session, int rollbackId) {
final boolean hasApex = sessionContainsApex(session);
// APEX checks. For single-package sessions, check if they contain an APEX. For
@@ -1361,7 +1358,7 @@ public class StagingManager {
if (hasApex) {
final List apexPackages;
try {
- apexPackages = submitSessionToApexService(session);
+ apexPackages = submitSessionToApexService(session, rollbackId);
for (int i = 0, size = apexPackages.size(); i < size; i++) {
validateApexSignature(apexPackages.get(i));
}
From cba607a5aba529f56906fff7e0dd533794bc7fd3 Mon Sep 17 00:00:00 2001
From: JW Wang
Date: Tue, 8 Sep 2020 11:32:27 +0800
Subject: [PATCH 3/5] Let PreRebootVerificationHandler methods take a session
object (3/n)
So we don't need getStagedSession() to remap an id to the session
object.
Bug: 167996901
Test: atest StagedInstallTest StagedInstallInternalTest
Change-Id: Iaf7444d0fc924d9e2deda66a6ffbd54d8c32b279
---
.../server/pm/PackageInstallerSession.java | 2 +-
.../com/android/server/pm/StagingManager.java | 33 +++++++++++--------
2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 73a9e2cb52cde..938ff7dffa65a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1998,7 +1998,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (isStaged()) {
// TODO(b/136257624): Remove this once all verification logic has been transferred out
// of StagingManager.
- mStagingManager.notifyPreRebootVerification_Apk_Complete(sessionId);
+ mStagingManager.notifyPreRebootVerification_Apk_Complete(this);
// TODO(b/136257624): We also need to destroy internals for verified staged session,
// otherwise file descriptors are never closed for verified staged session until reboot
return;
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index b00094cb813aa..7cb4c46831339 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -1186,8 +1186,8 @@ public class StagingManager {
// TODO(b/136257624): Temporary API to let PMS communicate with StagingManager. When all
// verification logic is extracted out of StagingManager into PMS, we can remove
// this.
- void notifyPreRebootVerification_Apk_Complete(int sessionId) {
- mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(sessionId);
+ void notifyPreRebootVerification_Apk_Complete(PackageInstallerSession session) {
+ mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(session);
}
private final class PreRebootVerificationHandler extends Handler {
@@ -1222,7 +1222,7 @@ public class StagingManager {
public void handleMessage(Message msg) {
final int sessionId = msg.arg1;
final int rollbackId = msg.arg2;
- final PackageInstallerSession session = getStagedSession(sessionId);
+ final PackageInstallerSession session = (PackageInstallerSession) msg.obj;
if (session == null) {
Slog.wtf(TAG, "Session disappeared in the middle of pre-reboot verification: "
+ sessionId);
@@ -1274,7 +1274,8 @@ public class StagingManager {
if (session != null && session.notifyStagedStartPreRebootVerification()) {
Slog.d(TAG, "Starting preRebootVerification for session " + sessionId);
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, -1).sendToTarget();
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, -1, session)
+ .sendToTarget();
}
}
@@ -1296,16 +1297,20 @@ public class StagingManager {
session.notifyStagedEndPreRebootVerification();
}
- private void notifyPreRebootVerification_Start_Complete(int sessionId, int rollbackId) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, sessionId, rollbackId).sendToTarget();
+ private void notifyPreRebootVerification_Start_Complete(
+ PackageInstallerSession session, int rollbackId) {
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, session.sessionId, rollbackId, session)
+ .sendToTarget();
}
- private void notifyPreRebootVerification_Apex_Complete(int sessionId) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, sessionId, -1).sendToTarget();
+ private void notifyPreRebootVerification_Apex_Complete(PackageInstallerSession session) {
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, session.sessionId, -1, session)
+ .sendToTarget();
}
- private void notifyPreRebootVerification_Apk_Complete(int sessionId) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, sessionId, -1).sendToTarget();
+ private void notifyPreRebootVerification_Apk_Complete(PackageInstallerSession session) {
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, session.sessionId, -1, session)
+ .sendToTarget();
}
/**
@@ -1338,7 +1343,7 @@ public class StagingManager {
}
}
- notifyPreRebootVerification_Start_Complete(session.sessionId, rollbackId);
+ notifyPreRebootVerification_Start_Complete(session, rollbackId);
}
/**
@@ -1372,17 +1377,17 @@ public class StagingManager {
packageManagerInternal.pruneCachedApksInApex(apexPackages);
}
- notifyPreRebootVerification_Apex_Complete(session.sessionId);
+ notifyPreRebootVerification_Apex_Complete(session);
}
/**
* Pre-reboot verification state for apk files. Session is sent to
* {@link PackageManagerService} for verification and it notifies back the result via
- * {@link #notifyPreRebootVerification_Apk_Complete(int)}
+ * {@link #notifyPreRebootVerification_Apk_Complete}
*/
private void handlePreRebootVerification_Apk(@NonNull PackageInstallerSession session) {
if (!sessionContainsApk(session)) {
- notifyPreRebootVerification_Apk_Complete(session.sessionId);
+ notifyPreRebootVerification_Apk_Complete(session);
return;
}
session.verifyStagedSession();
From 921340c284e08f3f855ba397b888dcf32f889206 Mon Sep 17 00:00:00 2001
From: JW Wang
Date: Tue, 8 Sep 2020 14:21:06 +0800
Subject: [PATCH 4/5] Store pending sessions as objects instead of ids (4/n)
So we don't need getStagedSession() to remap an id to the session
object.
Bug: 167996901
Test: atest StagedInstallTest StagedInstallInternalTest
Change-Id: Ibcba41001b1a8853992bceb427179a9a9296cbce
---
.../com/android/server/pm/StagingManager.java | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 7cb4c46831339..527655129d28e 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -1191,8 +1191,8 @@ public class StagingManager {
}
private final class PreRebootVerificationHandler extends Handler {
- // Hold session ids before handler gets ready to do the verification.
- private IntArray mPendingSessionIds;
+ // Hold sessions before handler gets ready to do the verification.
+ private List mPendingSessions;
private boolean mIsReady;
PreRebootVerificationHandler(Looper looper) {
@@ -1252,27 +1252,27 @@ public class StagingManager {
// Notify the handler that system is ready, and reschedule the pre-reboot verifications.
private synchronized void readyToStart() {
mIsReady = true;
- if (mPendingSessionIds != null) {
- for (int i = 0; i < mPendingSessionIds.size(); i++) {
- PackageInstallerSession session = getStagedSession(mPendingSessionIds.get(i));
+ if (mPendingSessions != null) {
+ for (int i = 0; i < mPendingSessions.size(); i++) {
+ PackageInstallerSession session = mPendingSessions.get(i);
startPreRebootVerification(session);
}
- mPendingSessionIds = null;
+ mPendingSessions = null;
}
}
// Method for starting the pre-reboot verification
private synchronized void startPreRebootVerification(PackageInstallerSession session) {
- int sessionId = session.sessionId;
if (!mIsReady) {
- if (mPendingSessionIds == null) {
- mPendingSessionIds = new IntArray();
+ if (mPendingSessions == null) {
+ mPendingSessions = new ArrayList<>();
}
- mPendingSessionIds.add(sessionId);
+ mPendingSessions.add(session);
return;
}
if (session != null && session.notifyStagedStartPreRebootVerification()) {
+ int sessionId = session.sessionId;
Slog.d(TAG, "Starting preRebootVerification for session " + sessionId);
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, -1, session)
.sendToTarget();
From f8dd1956b4d32932d12f6582302176ed7a305cad Mon Sep 17 00:00:00 2001
From: JW Wang
Date: Tue, 8 Sep 2020 15:18:48 +0800
Subject: [PATCH 5/5] Remove null-checks (5/n)
1. Remove the check in handleMessage() since all callers of
obtainMessage() pass non-null sessions.
2. Remove the check in startPreRebootVerification() since
the passed-in session is non-null.
Bug: 167996901
Test: atest StagedInstallTest StagedInstallInternalTest
Change-Id: I6c5b5a1357130d3c9f4889b7e6297faf7f2c20a4
---
.../com/android/server/pm/StagingManager.java | 20 +++++++++----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 527655129d28e..6ce06e087c7c4 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -1186,7 +1186,7 @@ public class StagingManager {
// TODO(b/136257624): Temporary API to let PMS communicate with StagingManager. When all
// verification logic is extracted out of StagingManager into PMS, we can remove
// this.
- void notifyPreRebootVerification_Apk_Complete(PackageInstallerSession session) {
+ void notifyPreRebootVerification_Apk_Complete(@NonNull PackageInstallerSession session) {
mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(session);
}
@@ -1223,11 +1223,6 @@ public class StagingManager {
final int sessionId = msg.arg1;
final int rollbackId = msg.arg2;
final PackageInstallerSession session = (PackageInstallerSession) msg.obj;
- if (session == null) {
- Slog.wtf(TAG, "Session disappeared in the middle of pre-reboot verification: "
- + sessionId);
- return;
- }
if (session.isDestroyed() || session.isStagedSessionFailed()) {
// No point in running verification on a destroyed/failed session
onPreRebootVerificationComplete(session);
@@ -1262,7 +1257,8 @@ public class StagingManager {
}
// Method for starting the pre-reboot verification
- private synchronized void startPreRebootVerification(PackageInstallerSession session) {
+ private synchronized void startPreRebootVerification(
+ @NonNull PackageInstallerSession session) {
if (!mIsReady) {
if (mPendingSessions == null) {
mPendingSessions = new ArrayList<>();
@@ -1271,7 +1267,7 @@ public class StagingManager {
return;
}
- if (session != null && session.notifyStagedStartPreRebootVerification()) {
+ if (session.notifyStagedStartPreRebootVerification()) {
int sessionId = session.sessionId;
Slog.d(TAG, "Starting preRebootVerification for session " + sessionId);
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, -1, session)
@@ -1298,17 +1294,19 @@ public class StagingManager {
}
private void notifyPreRebootVerification_Start_Complete(
- PackageInstallerSession session, int rollbackId) {
+ @NonNull PackageInstallerSession session, int rollbackId) {
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, session.sessionId, rollbackId, session)
.sendToTarget();
}
- private void notifyPreRebootVerification_Apex_Complete(PackageInstallerSession session) {
+ private void notifyPreRebootVerification_Apex_Complete(
+ @NonNull PackageInstallerSession session) {
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, session.sessionId, -1, session)
.sendToTarget();
}
- private void notifyPreRebootVerification_Apk_Complete(PackageInstallerSession session) {
+ private void notifyPreRebootVerification_Apk_Complete(
+ @NonNull PackageInstallerSession session) {
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, session.sessionId, -1, session)
.sendToTarget();
}