diff options
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageInstallerService.java | 19 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageInstallerSession.java | 24 |
2 files changed, 38 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 181b7a2af8b0..ad17549d7448 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -123,6 +123,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements /** Automatically destroy sessions older than this */ private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS; + /** Automatically destroy staged sessions that have not changed state in this time */ + private static final long MAX_TIME_SINCE_UPDATE_MILLIS = 7 * DateUtils.DAY_IN_MILLIS; /** Upper bound on number of active sessions for a UID */ private static final long MAX_ACTIVE_SESSIONS = 1024; /** Upper bound on number of historical sessions for a UID */ @@ -357,11 +359,19 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } final long age = System.currentTimeMillis() - session.createdMillis; - + final long timeSinceUpdate = + System.currentTimeMillis() - session.updatedMillis; final boolean valid; - if (age >= MAX_AGE_MILLIS) { - Slog.w(TAG, "Abandoning old session first created at " - + session.createdMillis); + if (session.isStaged()) { + if (timeSinceUpdate >= MAX_TIME_SINCE_UPDATE_MILLIS + && session.isStagedAndInTerminalState()) { + valid = false; + } else { + valid = true; + } + } else if (age >= MAX_AGE_MILLIS) { + Slog.w(TAG, "Abandoning old session created at " + + session.createdMillis); valid = false; } else { valid = true; @@ -1196,6 +1206,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } public void onStagedSessionChanged(PackageInstallerSession session) { + session.markUpdated(); writeSessionsAsync(); if (mOkToSendBroadcasts) { mPm.sendSessionUpdatedBroadcast(session.generateInfo(false), diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 6451b5653fe3..66b530f19ed8 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -144,6 +144,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName"; private static final String ATTR_INSTALLER_UID = "installerUid"; private static final String ATTR_CREATED_MILLIS = "createdMillis"; + private static final String ATTR_UPDATED_MILLIS = "updatedMillis"; private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir"; private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid"; private static final String ATTR_PREPARED = "prepared"; @@ -199,6 +200,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private final Object mLock = new Object(); + /** Timestamp of the last time this session changed state */ + @GuardedBy("mLock") + long updatedMillis; + /** Uid of the creator of this session. */ private final int mOriginalInstallerUid; @@ -422,6 +427,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mInstallerUid = installerUid; this.params = params; this.createdMillis = createdMillis; + this.updatedMillis = createdMillis; this.stageDir = stageDir; this.stageCid = stageCid; if (childSessionIds != null) { @@ -521,6 +527,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + /** Returns true if a staged session has reached a final state and can be forgotten about */ + public boolean isStagedAndInTerminalState() { + synchronized (mLock) { + return params.isStaged && (mStagedSessionApplied || mStagedSessionFailed); + } + } + @GuardedBy("mLock") private void assertPreparedAndNotSealedLocked(String cookie) { assertPreparedAndNotCommittedOrDestroyedLocked(cookie); @@ -1034,6 +1047,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + /** Update the timestamp of when the staged session last changed state */ + public void markUpdated() { + synchronized (mLock) { + this.updatedMillis = System.currentTimeMillis(); + } + } + @Override public void transfer(String packageName) { Preconditions.checkNotNull(packageName); @@ -2114,7 +2134,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private void destroyInternal() { synchronized (mLock) { mSealed = true; - if (!params.isStaged) { + if (!params.isStaged || isStagedAndInTerminalState()) { mDestroyed = true; } // Force shut down all bridges @@ -2224,6 +2244,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mInstallerPackageName); writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid); writeLongAttribute(out, ATTR_CREATED_MILLIS, createdMillis); + writeLongAttribute(out, ATTR_UPDATED_MILLIS, updatedMillis); if (stageDir != null) { writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, stageDir.getAbsolutePath()); @@ -2326,6 +2347,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID, pm.getPackageUid( installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId)); final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS); + long updatedMillis = readLongAttribute(in, ATTR_UPDATED_MILLIS); final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR); final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null; final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID); |