summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java19
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java24
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);