Loading core/java/android/os/Environment.java +5 −0 Original line number Diff line number Diff line Loading @@ -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"); Loading services/core/java/com/android/server/pm/PackageInstallerService.java +20 −15 Original line number Diff line number Diff line Loading @@ -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()); Loading @@ -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)); Loading @@ -252,7 +251,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements public void onPrivateVolumeMounted(String volumeUuid) { synchronized (mSessions) { reconcileStagesLocked(volumeUuid, false /*isInstant*/); reconcileStagesLocked(volumeUuid); } } Loading @@ -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); } Loading Loading @@ -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); } Loading Loading @@ -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 { Loading services/core/java/com/android/server/pm/PackageInstallerSession.java +15 −10 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 = Loading Loading @@ -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) { Loading services/core/java/com/android/server/pm/PackageManagerShellCommand.java +4 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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 { Loading Loading
core/java/android/os/Environment.java +5 −0 Original line number Diff line number Diff line Loading @@ -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"); Loading
services/core/java/com/android/server/pm/PackageInstallerService.java +20 −15 Original line number Diff line number Diff line Loading @@ -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()); Loading @@ -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)); Loading @@ -252,7 +251,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements public void onPrivateVolumeMounted(String volumeUuid) { synchronized (mSessions) { reconcileStagesLocked(volumeUuid, false /*isInstant*/); reconcileStagesLocked(volumeUuid); } } Loading @@ -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); } Loading Loading @@ -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); } Loading Loading @@ -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 { Loading
services/core/java/com/android/server/pm/PackageInstallerSession.java +15 −10 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 = Loading Loading @@ -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) { Loading
services/core/java/com/android/server/pm/PackageManagerShellCommand.java +4 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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 { Loading