Loading services/core/java/com/android/server/pm/PackageInstallerSession.java +52 −19 Original line number Original line Diff line number Diff line Loading @@ -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; } } Loading Loading @@ -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) { } } } }); }); } } Loading Loading @@ -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; Loading @@ -1349,7 +1384,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mCommitted = true; mCommitted = true; } } return true; return true; } } Loading Loading @@ -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 Loading @@ -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) { Loading Loading
services/core/java/com/android/server/pm/PackageInstallerSession.java +52 −19 Original line number Original line Diff line number Diff line Loading @@ -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; } } Loading Loading @@ -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) { } } } }); }); } } Loading Loading @@ -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; Loading @@ -1349,7 +1384,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mCommitted = true; mCommitted = true; } } return true; return true; } } Loading Loading @@ -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 Loading @@ -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) { Loading