Merge "Handles child failure on session validate" into rvc-dev am: eb29d9ac77

Change-Id: I7f41b4d16a423c100fdc3d184d79f188ffdd09bc
This commit is contained in:
Patrick Baumann
2020-04-30 19:53:23 +00:00
committed by Automerger Merge Worker

View File

@@ -1122,21 +1122,52 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
} }
private void handleStreamValidateAndCommit() { private void handleStreamValidateAndCommit() {
boolean success = streamValidateAndCommit(); PackageManagerException unrecoverableFailure = null;
// This will track whether the session and any children were validated and are ready to
// progress to the next phase of install
boolean allSessionsReady = false;
try {
allSessionsReady = streamValidateAndCommit();
} catch (PackageManagerException e) {
unrecoverableFailure = e;
}
if (isMultiPackage()) { if (isMultiPackage()) {
for (int i = mChildSessionIds.size() - 1; i >= 0; --i) { int childCount = mChildSessionIds.size();
// This will contain all child sessions that do not encounter an unrecoverable failure
ArrayList<PackageInstallerSession> nonFailingSessions = new ArrayList<>(childCount);
for (int i = childCount - 1; i >= 0; --i) {
final int childSessionId = mChildSessionIds.keyAt(i); final int childSessionId = mChildSessionIds.keyAt(i);
// commit all children, regardless if any of them fail; we'll throw/return // commit all children, regardless if any of them fail; we'll throw/return
// as appropriate once all children have been processed // as appropriate once all children have been processed
if (!mSessionProvider.getSession(childSessionId) try {
.streamValidateAndCommit()) { PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
success = false; if (!session.streamValidateAndCommit()) {
allSessionsReady = false;
}
nonFailingSessions.add(session);
} catch (PackageManagerException e) {
allSessionsReady = false;
if (unrecoverableFailure == null) {
unrecoverableFailure = e;
}
}
}
// If we encountered any unrecoverable failures, destroy all
// other impacted sessions besides the parent; that will be cleaned up by the
// ChildStatusIntentReceiver.
if (unrecoverableFailure != null) {
// fail other child sessions that did not already fail
for (int i = nonFailingSessions.size() - 1; i >= 0; --i) {
PackageInstallerSession session = nonFailingSessions.get(i);
session.onSessionVerificationFailure(unrecoverableFailure);
} }
} }
} }
if (!success) { if (!allSessionsReady) {
return; return;
} }
@@ -1216,14 +1247,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mStatusReceiver.sendIntent(mContext, 0, intent, null, null); mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
} catch (IntentSender.SendIntentException ignore) { } catch (IntentSender.SendIntentException ignore) {
} }
} else { } else { // failure, let's forward and clean up this session.
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, intent.putExtra(PackageInstaller.EXTRA_SESSION_ID,
PackageInstallerSession.this.sessionId); PackageInstallerSession.this.sessionId);
mChildSessionsRemaining.clear(); // we're done. Don't send any more. mChildSessionsRemaining.clear(); // we're done. Don't send any more.
try { onSessionVerificationFailure(status,
mStatusReceiver.sendIntent(mContext, 0, intent, null, null); intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
} catch (IntentSender.SendIntentException ignore) {
}
} }
}); });
} }
@@ -1329,7 +1358,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return true; return true;
} }
private boolean streamValidateAndCommit() { /**
* Returns true if the session is successfully validated and committed. Returns false if the
* dataloader could not be prepared. This can be called multiple times so long as no
* exception is thrown.
* @throws PackageManagerException on an unrecoverable error.
*/
private boolean streamValidateAndCommit() throws PackageManagerException {
synchronized (mLock) { synchronized (mLock) {
if (mCommitted) { if (mCommitted) {
return true; return true;
@@ -1349,7 +1384,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mCommitted = true; mCommitted = true;
} }
return true; return true;
} }
@@ -1449,10 +1483,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
* Prepare DataLoader and stream content for DataLoader sessions. * Prepare DataLoader and stream content for DataLoader sessions.
* Validate the contents of all session. * Validate the contents of all session.
* *
* @return false if validation failed. * @return false if the data loader could not be prepared.
* @throws PackageManagerException when an unrecoverable exception is encountered
*/ */
@GuardedBy("mLock") @GuardedBy("mLock")
private boolean streamAndValidateLocked() { private boolean streamAndValidateLocked() throws PackageManagerException {
try { try {
// Read transfers from the original owner stay open, but as the session's data cannot // Read transfers from the original owner stay open, but as the session's data cannot
// be modified anymore, there is no leak of information. For staged sessions, further // be modified anymore, there is no leak of information. For staged sessions, further
@@ -1472,16 +1507,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (params.isStaged) { if (params.isStaged) {
mStagingManager.checkNonOverlappingWithStagedSessions(this); mStagingManager.checkNonOverlappingWithStagedSessions(this);
} }
return true; return true;
} catch (PackageManagerException e) { } catch (PackageManagerException e) {
onSessionVerificationFailure(e); throw onSessionVerificationFailure(e);
} catch (Throwable e) { } catch (Throwable e) {
// Convert all exceptions into package manager exceptions as only those are handled // Convert all exceptions into package manager exceptions as only those are handled
// in the code above. // in the code above.
onSessionVerificationFailure(new PackageManagerException(e)); throw onSessionVerificationFailure(new PackageManagerException(e));
} }
return false;
} }
private PackageManagerException onSessionVerificationFailure(PackageManagerException e) { private PackageManagerException onSessionVerificationFailure(PackageManagerException e) {