Merge "Periodically clear cache under high storage threshold"

This commit is contained in:
Neharika Jali
2021-12-27 11:17:45 +00:00
committed by Android (Google) Code Review
3 changed files with 81 additions and 21 deletions

View File

@@ -100,6 +100,8 @@ public class Installer extends SystemService {
public static final int FLAG_FREE_CACHE_V2 = IInstalld.FLAG_FREE_CACHE_V2;
public static final int FLAG_FREE_CACHE_V2_DEFY_QUOTA = IInstalld.FLAG_FREE_CACHE_V2_DEFY_QUOTA;
public static final int FLAG_FREE_CACHE_NOOP = IInstalld.FLAG_FREE_CACHE_NOOP;
public static final int FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES =
IInstalld.FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES;
public static final int FLAG_USE_QUOTA = IInstalld.FLAG_USE_QUOTA;
public static final int FLAG_FORCE = IInstalld.FLAG_FORCE;

View File

@@ -2779,6 +2779,23 @@ public class PackageManagerService extends IPackageManager.Stub
});
}
/**
* Blocking call to clear all cached app data above quota.
*/
public void freeAllAppCacheAboveQuota(String volumeUuid) throws IOException {
synchronized (mInstallLock) {
// To avoid refactoring Installer.freeCache() and InstalldNativeService.freeCache(),
// Long.MAX_VALUE is passed as an argument which is used in neither of two methods
// when FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES is set
try {
mInstaller.freeCache(volumeUuid, Long.MAX_VALUE, Installer.FLAG_FREE_CACHE_V2
| Installer.FLAG_FREE_CACHE_DEFY_TARGET_FREE_BYTES);
} catch (InstallerException ignored) {
}
}
return;
}
/**
* Blocking call to clear various types of cached data across the system
* until the requested bytes are available.

View File

@@ -75,10 +75,12 @@ public class DeviceStorageMonitorService extends SystemService {
*/
public static final String EXTRA_SEQUENCE = "seq";
private static final int MSG_CHECK = 1;
private static final int MSG_CHECK_LOW = 1;
private static final int MSG_CHECK_HIGH = 2;
private static final long DEFAULT_LOG_DELTA_BYTES = DataUnit.MEBIBYTES.toBytes(64);
private static final long DEFAULT_CHECK_INTERVAL = DateUtils.MINUTE_IN_MILLIS;
private static final long LOW_CHECK_INTERVAL = DateUtils.MINUTE_IN_MILLIS;
private static final long HIGH_CHECK_INTERVAL = 10 * DateUtils.HOUR_IN_MILLIS;
// com.android.internal.R.string.low_internal_storage_view_text_no_boot
// hard codes 250MB in the message as the storage space required for the
@@ -165,12 +167,12 @@ public class DeviceStorageMonitorService extends SystemService {
}
/**
* Core logic that checks the storage state of every mounted private volume.
* Since this can do heavy I/O, callers should invoke indirectly using
* {@link #MSG_CHECK}.
* Core logic that checks the storage state of every mounted private volume and clears cache
* under low storage state. Since this can do heavy I/O, callers should invoke indirectly using
* {@link #MSG_CHECK_LOW}.
*/
@WorkerThread
private void check() {
private void checkLow() {
final StorageManager storage = getContext().getSystemService(StorageManager.class);
final int seq = mSeq.get();
@@ -234,9 +236,45 @@ public class DeviceStorageMonitorService extends SystemService {
// Loop around to check again in future; we don't remove messages since
// there might be an immediate request pending.
if (!mHandler.hasMessages(MSG_CHECK)) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK),
DEFAULT_CHECK_INTERVAL);
if (!mHandler.hasMessages(MSG_CHECK_LOW)) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_LOW),
LOW_CHECK_INTERVAL);
}
if (!mHandler.hasMessages(MSG_CHECK_HIGH)) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_HIGH),
HIGH_CHECK_INTERVAL);
}
}
/**
* Core logic that checks the storage state of every mounted private volume and clears cache if
* free space is under 20% of total space. Since this can do heavy I/O, callers should invoke
* indirectly using {@link #MSG_CHECK_HIGH}.
*/
@WorkerThread
private void checkHigh() {
final StorageManager storage = getContext().getSystemService(StorageManager.class);
// Check every mounted private volume to see if they're under the high storage threshold
// which is StorageManager.STORAGE_THRESHOLD_PERCENT_HIGH of total space
for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
final File file = vol.getPath();
if (file.getUsableSpace() < file.getTotalSpace()
* StorageManager.STORAGE_THRESHOLD_PERCENT_HIGH / 100) {
final PackageManagerService pms = (PackageManagerService) ServiceManager
.getService("package");
try {
pms.freeAllAppCacheAboveQuota(vol.getFsUuid());
} catch (IOException e) {
Slog.w(TAG, e);
}
}
}
// Loop around to check again in future; we don't remove messages since
// there might be an immediate request pending
if (!mHandler.hasMessages(MSG_CHECK_HIGH)) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_HIGH),
HIGH_CHECK_INTERVAL);
}
}
@@ -250,8 +288,11 @@ public class DeviceStorageMonitorService extends SystemService {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_CHECK:
check();
case MSG_CHECK_LOW:
checkLow();
return;
case MSG_CHECK_HIGH:
checkHigh();
return;
}
}
@@ -282,16 +323,16 @@ public class DeviceStorageMonitorService extends SystemService {
publishLocalService(DeviceStorageMonitorInternal.class, mLocalService);
// Kick off pass to examine storage state
mHandler.removeMessages(MSG_CHECK);
mHandler.obtainMessage(MSG_CHECK).sendToTarget();
mHandler.removeMessages(MSG_CHECK_LOW);
mHandler.obtainMessage(MSG_CHECK_LOW).sendToTarget();
}
private final DeviceStorageMonitorInternal mLocalService = new DeviceStorageMonitorInternal() {
@Override
public void checkMemory() {
// Kick off pass to examine storage state
mHandler.removeMessages(MSG_CHECK);
mHandler.obtainMessage(MSG_CHECK).sendToTarget();
mHandler.removeMessages(MSG_CHECK_LOW);
mHandler.obtainMessage(MSG_CHECK_LOW).sendToTarget();
}
@Override
@@ -360,8 +401,8 @@ public class DeviceStorageMonitorService extends SystemService {
mForceLevel = State.LEVEL_LOW;
int seq = mSeq.incrementAndGet();
if ((opts & OPTION_FORCE_UPDATE) != 0) {
mHandler.removeMessages(MSG_CHECK);
mHandler.obtainMessage(MSG_CHECK).sendToTarget();
mHandler.removeMessages(MSG_CHECK_LOW);
mHandler.obtainMessage(MSG_CHECK_LOW).sendToTarget();
pw.println(seq);
}
} break;
@@ -372,8 +413,8 @@ public class DeviceStorageMonitorService extends SystemService {
mForceLevel = State.LEVEL_NORMAL;
int seq = mSeq.incrementAndGet();
if ((opts & OPTION_FORCE_UPDATE) != 0) {
mHandler.removeMessages(MSG_CHECK);
mHandler.obtainMessage(MSG_CHECK).sendToTarget();
mHandler.removeMessages(MSG_CHECK_LOW);
mHandler.obtainMessage(MSG_CHECK_LOW).sendToTarget();
pw.println(seq);
}
} break;
@@ -384,8 +425,8 @@ public class DeviceStorageMonitorService extends SystemService {
mForceLevel = State.LEVEL_UNKNOWN;
int seq = mSeq.incrementAndGet();
if ((opts & OPTION_FORCE_UPDATE) != 0) {
mHandler.removeMessages(MSG_CHECK);
mHandler.obtainMessage(MSG_CHECK).sendToTarget();
mHandler.removeMessages(MSG_CHECK_LOW);
mHandler.obtainMessage(MSG_CHECK_LOW).sendToTarget();
pw.println(seq);
}
} break;