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

Commit cfa66d9e authored by JW Wang's avatar JW Wang Committed by Android (Google) Code Review
Browse files

Merge changes I8f253e0f,I186a5f16

* changes:
  Rewrite #restoreSession (2/n)
  Add PackageInstallerSession#getChildSessions (1/n)
parents 7b10d42b ce3b19f0
Loading
Loading
Loading
Loading
+10 −3
Original line number Original line Diff line number Diff line
@@ -161,6 +161,7 @@ import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.Set;
@@ -1599,8 +1600,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    }
    }


    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private @Nullable List<PackageInstallerSession> getChildSessionsLocked() {
    private @NonNull List<PackageInstallerSession> getChildSessionsLocked() {
        List<PackageInstallerSession> childSessions = null;
        List<PackageInstallerSession> childSessions = Collections.EMPTY_LIST;
        if (isMultiPackage()) {
        if (isMultiPackage()) {
            int size = mChildSessions.size();
            int size = mChildSessions.size();
            childSessions = new ArrayList<>(size);
            childSessions = new ArrayList<>(size);
@@ -1611,6 +1612,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        return childSessions;
        return childSessions;
    }
    }


    @NonNull List<PackageInstallerSession> getChildSessions() {
        synchronized (mLock) {
            return getChildSessionsLocked();
        }
    }

    /**
    /**
     * Seal the session to prevent further modification.
     * Seal the session to prevent further modification.
     *
     *
@@ -3639,7 +3646,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    }
    }


    private void cleanStageDir(List<PackageInstallerSession> childSessions) {
    private void cleanStageDir(List<PackageInstallerSession> childSessions) {
        if (childSessions != null) {
        if (isMultiPackage()) {
            for (PackageInstallerSession childSession : childSessions) {
            for (PackageInstallerSession childSession : childSessions) {
                childSession.cleanStageDir();
                childSession.cleanStageDir();
            }
            }
+19 −76
Original line number Original line Diff line number Diff line
@@ -240,9 +240,9 @@ public class StagingManager {
            @NonNull PackageInstallerSession session) throws PackageManagerException {
            @NonNull PackageInstallerSession session) throws PackageManagerException {
        final IntArray childSessionIds = new IntArray();
        final IntArray childSessionIds = new IntArray();
        if (session.isMultiPackage()) {
        if (session.isMultiPackage()) {
            for (int id : session.getChildSessionIds()) {
            for (PackageInstallerSession s : session.getChildSessions()) {
                if (isApexSession(getStagedSession(id))) {
                if (isApexSession(s)) {
                    childSessionIds.add(id);
                    childSessionIds.add(s.sessionId);
                }
                }
            }
            }
        }
        }
@@ -356,19 +356,13 @@ public class StagingManager {
        if (!session.isMultiPackage()) {
        if (!session.isMultiPackage()) {
            return filter.test(session);
            return filter.test(session);
        }
        }
        synchronized (mStagedSessions) {
        for (PackageInstallerSession s : session.getChildSessions()) {
            final int[] childSessionIds = session.getChildSessionIds();
            for (int id : childSessionIds) {
                // Retrieve cached sessions matching ids.
                final PackageInstallerSession s = mStagedSessions.get(id);
                // Filter only the ones containing APEX.
            if (filter.test(s)) {
            if (filter.test(s)) {
                return true;
                return true;
            }
            }
        }
        }
        return false;
        return false;
    }
    }
    }


    private boolean sessionContainsApex(@NonNull PackageInstallerSession session) {
    private boolean sessionContainsApex(@NonNull PackageInstallerSession session) {
        return sessionContains(session, (s) -> isApexSession(s));
        return sessionContains(session, (s) -> isApexSession(s));
@@ -423,19 +417,9 @@ public class StagingManager {
    private List<PackageInstallerSession> extractApexSessions(PackageInstallerSession session) {
    private List<PackageInstallerSession> extractApexSessions(PackageInstallerSession session) {
        List<PackageInstallerSession> apexSessions = new ArrayList<>();
        List<PackageInstallerSession> apexSessions = new ArrayList<>();
        if (session.isMultiPackage()) {
        if (session.isMultiPackage()) {
            List<PackageInstallerSession> childrenSessions = new ArrayList<>();
            for (PackageInstallerSession s : session.getChildSessions()) {
            synchronized (mStagedSessions) {
                if (sessionContainsApex(s)) {
                for (int childSessionId : session.getChildSessionIds()) {
                    apexSessions.add(s);
                    PackageInstallerSession childSession = mStagedSessions.get(childSessionId);
                    if (childSession != null) {
                        childrenSessions.add(childSession);
                    }
                }
            }
            for (int i = 0, size = childrenSessions.size(); i < size; i++) {
                final PackageInstallerSession childSession = childrenSessions.get(i);
                if (sessionContainsApex(childSession)) {
                    apexSessions.add(childSession);
                }
                }
            }
            }
        } else {
        } else {
@@ -782,15 +766,11 @@ public class StagingManager {
            // carrying over all the session parameters and unmarking them as staged. On commit the
            // carrying over all the session parameters and unmarking them as staged. On commit the
            // sessions will be installed atomically.
            // sessions will be installed atomically.
            final List<PackageInstallerSession> childSessions = new ArrayList<>();
            final List<PackageInstallerSession> childSessions = new ArrayList<>();
            synchronized (mStagedSessions) {
            for (PackageInstallerSession s : session.getChildSessions()) {
                final int[] childSessionIds = session.getChildSessionIds();
                for (int id : childSessionIds) {
                    final PackageInstallerSession s = mStagedSessions.get(id);
                if (!isApexSession(s)) {
                if (!isApexSession(s)) {
                    childSessions.add(s);
                    childSessions.add(s);
                }
                }
            }
            }
            }
            if (childSessions.isEmpty()) {
            if (childSessions.isEmpty()) {
                // APEX-only multi-package staged session, nothing to do.
                // APEX-only multi-package staged session, nothing to do.
                return null;
                return null;
@@ -834,16 +814,12 @@ public class StagingManager {
        if (!session.isMultiPackage()) {
        if (!session.isMultiPackage()) {
            return;
            return;
        }
        }
        final int[] childSessionIds = session.getChildSessionIds();
        final Set<String> apkNames = new ArraySet<>();
        final Set<String> apkNames = new ArraySet<>();
        synchronized (mStagedSessions) {
        for (PackageInstallerSession s : session.getChildSessions()) {
            for (int id : childSessionIds) {
                final PackageInstallerSession s = mStagedSessions.get(id);
            if (!isApexSession(s)) {
            if (!isApexSession(s)) {
                apkNames.add(s.getPackageName());
                apkNames.add(s.getPackageName());
            }
            }
        }
        }
        }
        final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
        final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
        for (PackageInstallerSession apexSession : apexSessions) {
        for (PackageInstallerSession apexSession : apexSessions) {
            String packageName = apexSession.getPackageName();
            String packageName = apexSession.getPackageName();
@@ -1088,46 +1064,13 @@ public class StagingManager {
                || apexSessionInfo.isRevertFailed;
                || apexSessionInfo.isRevertFailed;
    }
    }


    @GuardedBy("mStagedSessions")
    private boolean isMultiPackageSessionComplete(@NonNull PackageInstallerSession session) {
        // This method assumes that the argument is either a parent session of a multi-package
        // i.e. isMultiPackage() returns true, or that it is a child session, i.e.
        // hasParentSessionId() returns true.
        if (session.isMultiPackage()) {
            // Parent session of a multi-package group. Check that we restored all the children.
            for (int childSession : session.getChildSessionIds()) {
                if (mStagedSessions.get(childSession) == null) {
                    return false;
                }
            }
            return true;
        }
        if (session.hasParentSessionId()) {
            PackageInstallerSession parent = mStagedSessions.get(session.getParentSessionId());
            if (parent == null) {
                return false;
            }
            return isMultiPackageSessionComplete(parent);
        }
        Slog.wtf(TAG, "Attempting to restore an invalid multi-package session.");
        return false;
    }

    void restoreSession(@NonNull PackageInstallerSession session, boolean isDeviceUpgrading) {
    void restoreSession(@NonNull PackageInstallerSession session, boolean isDeviceUpgrading) {
        PackageInstallerSession sessionToResume = session;
        PackageInstallerSession sessionToResume = session;
        synchronized (mStagedSessions) {
        synchronized (mStagedSessions) {
            mStagedSessions.append(session.sessionId, session);
            mStagedSessions.append(session.sessionId, session);
            // For multi-package sessions, we don't know in which order they will be restored. We
            // need to wait until we have restored all the session in a group before restoring them.
            if (session.isMultiPackage() || session.hasParentSessionId()) {
                if (!isMultiPackageSessionComplete(session)) {
                    // Still haven't recovered all sessions of the group, return.
                    return;
                }
                // Group recovered, find the parent if necessary and resume the installation.
            if (session.hasParentSessionId()) {
            if (session.hasParentSessionId()) {
                    sessionToResume = mStagedSessions.get(session.getParentSessionId());
                // Only parent sessions can be restored
                }
                return;
            }
            }
        }
        }
        // The preconditions used during pre-reboot verification might have changed when device
        // The preconditions used during pre-reboot verification might have changed when device