Revert "Revert "[pm] remove old stage dirs on low storage""
This reverts commitb45ebca772. Reason for revert: adding the fix for system to abandon sessions BUG: 67862680 Test: manual Change-Id: I91170ba399b3a596320b3bd9c8188912e5c4f1be (cherry picked from commitce2c9032b9) Merged-In: I91170ba399b3a596320b3bd9c8188912e5c4f1be
This commit is contained in:
@@ -135,6 +135,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
private static final long MAX_ACTIVE_SESSIONS_NO_PERMISSION = 50;
|
||||
/** Upper bound on number of historical sessions for a UID */
|
||||
private static final long MAX_HISTORICAL_SESSIONS = 1048576;
|
||||
/** Destroy sessions older than this on storage free request */
|
||||
private static final long MAX_SESSION_AGE_ON_LOW_STORAGE_MILLIS = 8 * DateUtils.HOUR_IN_MILLIS;
|
||||
|
||||
/**
|
||||
* Allow verification-skipping if it's a development app installed through ADB with
|
||||
@@ -334,22 +336,28 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
|
||||
@GuardedBy("mSessions")
|
||||
private void reconcileStagesLocked(String volumeUuid) {
|
||||
final File stagingDir = getTmpSessionDir(volumeUuid);
|
||||
final ArraySet<File> unclaimedStages = newArraySet(
|
||||
stagingDir.listFiles(sStageFilter));
|
||||
|
||||
// We also need to clean up orphaned staging directory for staged sessions
|
||||
final File stagedSessionStagingDir = Environment.getDataStagingDirectory(volumeUuid);
|
||||
unclaimedStages.addAll(newArraySet(stagedSessionStagingDir.listFiles()));
|
||||
|
||||
final ArraySet<File> unclaimedStages = getStagingDirsOnVolume(volumeUuid);
|
||||
// Ignore stages claimed by active sessions
|
||||
for (int i = 0; i < mSessions.size(); i++) {
|
||||
final PackageInstallerSession session = mSessions.valueAt(i);
|
||||
unclaimedStages.remove(session.stageDir);
|
||||
}
|
||||
removeStagingDirs(unclaimedStages);
|
||||
}
|
||||
|
||||
private ArraySet<File> getStagingDirsOnVolume(String volumeUuid) {
|
||||
final File stagingDir = getTmpSessionDir(volumeUuid);
|
||||
final ArraySet<File> stagingDirs = newArraySet(stagingDir.listFiles(sStageFilter));
|
||||
|
||||
// We also need to clean up orphaned staging directory for staged sessions
|
||||
final File stagedSessionStagingDir = Environment.getDataStagingDirectory(volumeUuid);
|
||||
stagingDirs.addAll(newArraySet(stagedSessionStagingDir.listFiles()));
|
||||
return stagingDirs;
|
||||
}
|
||||
|
||||
private void removeStagingDirs(ArraySet<File> stagingDirsToRemove) {
|
||||
// Clean up orphaned staging directories
|
||||
for (File stage : unclaimedStages) {
|
||||
for (File stage : stagingDirsToRemove) {
|
||||
Slog.w(TAG, "Deleting orphan stage " + stage);
|
||||
synchronized (mPm.mInstallLock) {
|
||||
mPm.removeCodePathLI(stage);
|
||||
@@ -363,6 +371,33 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to free up some storage space from obsolete installation files
|
||||
*/
|
||||
public void freeStageDirs(String volumeUuid) {
|
||||
final ArraySet<File> unclaimedStagingDirsOnVolume = getStagingDirsOnVolume(volumeUuid);
|
||||
final long currentTimeMillis = System.currentTimeMillis();
|
||||
synchronized (mSessions) {
|
||||
for (int i = 0; i < mSessions.size(); i++) {
|
||||
final PackageInstallerSession session = mSessions.valueAt(i);
|
||||
if (!unclaimedStagingDirsOnVolume.contains(session.stageDir)) {
|
||||
// Only handles sessions stored on the target volume
|
||||
continue;
|
||||
}
|
||||
final long age = currentTimeMillis - session.createdMillis;
|
||||
if (age >= MAX_SESSION_AGE_ON_LOW_STORAGE_MILLIS) {
|
||||
// Aggressively close old sessions because we are running low on storage
|
||||
// Their staging dirs will be removed too
|
||||
session.abandon();
|
||||
} else {
|
||||
// Session is new enough, so it deserves to be kept even on low storage
|
||||
unclaimedStagingDirsOnVolume.remove(session.stageDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
removeStagingDirs(unclaimedStagingDirsOnVolume);
|
||||
}
|
||||
|
||||
public static boolean isStageName(String name) {
|
||||
final boolean isFile = name.startsWith("vmdl") && name.endsWith(".tmp");
|
||||
final boolean isContainer = name.startsWith("smdl") && name.endsWith(".tmp");
|
||||
|
||||
@@ -673,7 +673,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
final Runnable r;
|
||||
synchronized (mLock) {
|
||||
assertNotChildLocked("StagedSession#abandon");
|
||||
assertCallerIsOwnerOrRoot();
|
||||
assertCallerIsOwnerOrRootOrSystem();
|
||||
if (isInTerminalState()) {
|
||||
// We keep the session in the database if it's in a finalized state. It will be
|
||||
// removed by PackageInstallerService when the last update time is old enough.
|
||||
@@ -3704,7 +3704,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
private void abandonNonStaged() {
|
||||
synchronized (mLock) {
|
||||
assertNotChildLocked("abandonNonStaged");
|
||||
assertCallerIsOwnerOrRoot();
|
||||
assertCallerIsOwnerOrRootOrSystem();
|
||||
if (mRelinquished) {
|
||||
if (LOGD) Slog.d(TAG, "Ignoring abandon after commit relinquished control");
|
||||
return;
|
||||
|
||||
@@ -8962,6 +8962,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
if (freeBytesRequired > 0) {
|
||||
smInternal.freeCache(volumeUuid, freeBytesRequired);
|
||||
}
|
||||
|
||||
// 12. Clear temp install session files
|
||||
mInstallerService.freeStageDirs(volumeUuid);
|
||||
|
||||
if (file.getUsableSpace() >= bytes) return;
|
||||
} else {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user