Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef83e031 authored by Patrick Baumann's avatar Patrick Baumann Committed by Automerger Merge Worker
Browse files

Merge "Handles child failure on session validate" into rvc-dev am: eb29d9ac am: 42a0c683

Change-Id: I7ecc00ff5e885bccad70666391894beeb54a6aeb
parents 4e6762bb 42a0c683
Loading
Loading
Loading
Loading
+52 −19
Original line number Original line Diff line number Diff line
@@ -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) {