Merge "Revert "Revert "[pm] remove old stage dirs on low storage""" into rvc-dev am: abe4e3849b
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16057568 Change-Id: Ia158c2f41134cde4d114b040503c961655ac98f2
This commit is contained in:
@@ -134,6 +134,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
/** Upper bound on number of historical sessions for a UID */
|
/** Upper bound on number of historical sessions for a UID */
|
||||||
private static final long MAX_HISTORICAL_SESSIONS = 1048576;
|
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
|
* Allow verification-skipping if it's a development app installed through ADB with
|
||||||
* disable verification flag specified.
|
* disable verification flag specified.
|
||||||
@@ -295,22 +298,29 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
|
|
||||||
@GuardedBy("mSessions")
|
@GuardedBy("mSessions")
|
||||||
private void reconcileStagesLocked(String volumeUuid) {
|
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
|
// Ignore stages claimed by active sessions
|
||||||
for (int i = 0; i < mSessions.size(); i++) {
|
for (int i = 0; i < mSessions.size(); i++) {
|
||||||
final PackageInstallerSession session = mSessions.valueAt(i);
|
final PackageInstallerSession session = mSessions.valueAt(i);
|
||||||
unclaimedStages.remove(session.stageDir);
|
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
|
// Clean up orphaned staging directories
|
||||||
for (File stage : unclaimedStages) {
|
for (File stage : stagingDirsToRemove) {
|
||||||
Slog.w(TAG, "Deleting orphan stage " + stage);
|
Slog.w(TAG, "Deleting orphan stage " + stage);
|
||||||
synchronized (mPm.mInstallLock) {
|
synchronized (mPm.mInstallLock) {
|
||||||
mPm.removeCodePathLI(stage);
|
mPm.removeCodePathLI(stage);
|
||||||
@@ -318,6 +328,34 @@ 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 void onPrivateVolumeMounted(String volumeUuid) {
|
public void onPrivateVolumeMounted(String volumeUuid) {
|
||||||
synchronized (mSessions) {
|
synchronized (mSessions) {
|
||||||
reconcileStagesLocked(volumeUuid);
|
reconcileStagesLocked(volumeUuid);
|
||||||
|
|||||||
@@ -2610,14 +2610,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
|
|
||||||
List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
|
List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (params.isStaged && mDestroyed) {
|
|
||||||
// If a user abandons staged session in an unsafe state, then system will try to
|
|
||||||
// abandon the destroyed staged session when it is safe on behalf of the user.
|
|
||||||
assertCallerIsOwnerOrRootOrSystemLocked();
|
|
||||||
} else {
|
|
||||||
assertCallerIsOwnerOrRootLocked();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assertCallerIsOwnerOrRootOrSystemLocked();
|
||||||
if (isStagedAndInTerminalState()) {
|
if (isStagedAndInTerminalState()) {
|
||||||
// We keep the session in the database if it's in a finalized state. It will be
|
// 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.
|
// removed by PackageInstallerService when the last update time is old enough.
|
||||||
|
|||||||
@@ -5133,6 +5133,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
InstantAppRegistry.DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
|
InstantAppRegistry.DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 12. Clear temp install session files
|
||||||
|
mInstallerService.freeStageDirs(volumeUuid);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
mInstaller.freeCache(volumeUuid, bytes, 0, 0);
|
mInstaller.freeCache(volumeUuid, bytes, 0, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user