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

Commit 2b9930d0 authored by Dario Freni's avatar Dario Freni Committed by Android (Google) Code Review
Browse files

Merge "Write staged sessions to /data/staging."

parents fd605701 a8f4b131
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -381,6 +381,11 @@ public class Environment {
        return new File(getDataDirectory(volumeUuid), "app");
    }

    /** {@hide} */
    public static File getDataStagingDirectory(String volumeUuid) {
        return new File(getDataDirectory(volumeUuid), "staging");
    }

    /** {@hide} */
    public static File getDataUserCeDirectory(String volumeUuid) {
        return new File(getDataDirectory(volumeUuid), "user");
+20 −15
Original line number Diff line number Diff line
@@ -209,8 +209,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
        synchronized (mSessions) {
            readSessionsLocked();

            reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL, false /*isInstant*/);
            reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL, true /*isInstant*/);
            reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL);

            final ArraySet<File> unclaimedIcons = newArraySet(
                    mSessionsDir.listFiles());
@@ -230,8 +229,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
    }

    @GuardedBy("mSessions")
    private void reconcileStagesLocked(String volumeUuid, boolean isEphemeral) {
        final File stagingDir = buildStagingDir(volumeUuid, isEphemeral);
    private void reconcileStagesLocked(String volumeUuid) {
        final File stagingDir = getTmpSessionDir(volumeUuid);
        final ArraySet<File> unclaimedStages = newArraySet(
                stagingDir.listFiles(sStageFilter));

@@ -252,7 +251,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements

    public void onPrivateVolumeMounted(String volumeUuid) {
        synchronized (mSessions) {
            reconcileStagesLocked(volumeUuid, false /*isInstant*/);
            reconcileStagesLocked(volumeUuid);
        }
    }

@@ -269,9 +268,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
            try {
                final int sessionId = allocateSessionIdLocked();
                mLegacySessions.put(sessionId, true);
                final File stageDir = buildStageDir(volumeUuid, sessionId, isEphemeral);
                prepareStageDir(stageDir);
                return stageDir;
                final File sessionStageDir = buildTmpSessionDir(sessionId, volumeUuid);
                prepareStageDir(sessionStageDir);
                return sessionStageDir;
            } catch (IllegalStateException e) {
                throw new IOException(e);
            }
@@ -526,9 +525,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
        String stageCid = null;
        if (!params.isMultiPackage) {
            if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
                final boolean isInstant =
                        (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
                stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
                stageDir = buildSessionDir(sessionId, params);
            } else {
                stageCid = buildExternalStageCid(sessionId);
            }
@@ -634,13 +631,21 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
        throw new IllegalStateException("Failed to allocate session ID");
    }

    private File buildStagingDir(String volumeUuid, boolean isEphemeral) {
    private File getTmpSessionDir(String volumeUuid) {
        return Environment.getDataAppDirectory(volumeUuid);
    }

    private File buildStageDir(String volumeUuid, int sessionId, boolean isEphemeral) {
        final File stagingDir = buildStagingDir(volumeUuid, isEphemeral);
        return new File(stagingDir, "vmdl" + sessionId + ".tmp");
    private File buildTmpSessionDir(int sessionId, String volumeUuid) {
        final File sessionStagingDir = getTmpSessionDir(volumeUuid);
        return new File(sessionStagingDir, "vmdl" + sessionId + ".tmp");
    }

    private File buildSessionDir(int sessionId, SessionParams params) {
        if (params.isStaged) {
            final File sessionStagingDir = Environment.getDataStagingDirectory(params.volumeUuid);
            return new File(sessionStagingDir, "session_" + sessionId);
        }
        return buildTmpSessionDir(sessionId, params.volumeUuid);
    }

    static void prepareStageDir(File stageDir) throws IOException {
+15 −10
Original line number Diff line number Diff line
@@ -978,18 +978,18 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

        // Read transfers from the original owner stay open, but as the session's data
        // cannot be modified anymore, there is no leak of information.
        if (!params.isMultiPackage) {
        // For staged sessions, the validation is performed by StagingManager.
        if (!params.isMultiPackage && !params.isStaged) {
            final PackageInfo pkgInfo = mPm.getPackageInfo(
                    params.appPackageName, PackageManager.GET_SIGNATURES
                            | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);

            resolveStageDirLocked();

            // Verify that stage looks sane with respect to existing application.
            // This currently only ensures packageName, versionCode, and certificate
            // consistency.
            try {
                if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
                    // TODO(b/118865310): Remove this when APEX validation is done via
                    //                    StagingManager.
                    validateApexInstallLocked(pkgInfo);
                } else {
                    // Verify that stage looks sane with respect to existing application.
@@ -1062,16 +1062,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    @GuardedBy("mLock")
    private void commitLocked()
            throws PackageManagerException {
        if (params.isStaged) {
            mStagingManager.commitSession(this);
            destroyInternal();
            dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
            return;
        }
        final PackageManagerService.ActiveInstallSession committingSession =
                makeSessionActiveLocked();
        if (committingSession == null) {
            return;
        }
        if (isStaged()) {
            mStagingManager.commitSession(this);
            dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
            return;
        }
        if (isMultiPackage()) {
            final int[] childSessionIds = getChildSessionIds();
            List<PackageManagerService.ActiveInstallSession> childSessions =
@@ -1984,7 +1985,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                bridge.forceClose();
            }
        }
        if (stageDir != null) {
        // For staged sessions, we don't delete the directory where the packages have been copied,
        // since these packages are supposed to be read on reboot. StagingManager is in charge of
        // deleting these dirs when the staged session has reached a final state.
        // TODO(b/118865310): Implement packageDir deletion in StagingManager.
        if (stageDir != null && !params.isStaged) {
            try {
                mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
            } catch (InstallerException ignored) {
+4 −1
Original line number Diff line number Diff line
@@ -2293,6 +2293,9 @@ class PackageManagerShellCommand extends ShellCommand {
                    break;
                case "--apex":
                    sessionParams.installFlags |= PackageManager.INSTALL_APEX;
                    // TODO(b/118865310): APEX packages should always imply
                    //                    sessionParams.isStaged(). Enforce this when the staged
                    //                    install workflow is complete.
                    break;
                case "--multi-package":
                    sessionParams.setMultiPackage();
@@ -2588,7 +2591,7 @@ class PackageManagerShellCommand extends ShellCommand {
        try {
            session = new PackageInstaller.Session(
                    mInterface.getPackageInstaller().openSession(sessionId));
            if (!session.isMultiPackage()) {
            if (!session.isMultiPackage() && !session.isStaged()) {
                // Sanity check that all .dm files match an apk.
                // (The installer does not support standalone .dm files and will not process them.)
                try {