Merge "Periodically clear cache under high storage threshold"
This commit is contained in:
committed by
Android (Google) Code Review
commit
075254e1db
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user