summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/storage/StorageManager.java20
-rw-r--r--core/java/com/android/internal/content/PackageHelper.java17
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java47
3 files changed, 62 insertions, 22 deletions
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 69c1295df4f9..5b9205d16898 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1987,11 +1987,31 @@ public class StorageManager {
*/
public static final int FLAG_ALLOCATE_DEFY_HALF_RESERVED = 1 << 2;
+ /**
+ * Flag indicating that a disk space check should not take into account
+ * freeable cached space when determining allocatable space.
+ *
+ * Intended for use with {@link #getAllocatableBytes()}.
+ * @hide
+ */
+ public static final int FLAG_ALLOCATE_NON_CACHE_ONLY = 1 << 3;
+
+ /**
+ * Flag indicating that a disk space check should only return freeable
+ * cached space when determining allocatable space.
+ *
+ * Intended for use with {@link #getAllocatableBytes()}.
+ * @hide
+ */
+ public static final int FLAG_ALLOCATE_CACHE_ONLY = 1 << 4;
+
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_ALLOCATE_" }, value = {
FLAG_ALLOCATE_AGGRESSIVE,
FLAG_ALLOCATE_DEFY_ALL_RESERVED,
FLAG_ALLOCATE_DEFY_HALF_RESERVED,
+ FLAG_ALLOCATE_NON_CACHE_ONLY,
+ FLAG_ALLOCATE_CACHE_ONLY,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AllocateFlags {}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index ad1ff902b7d8..1d81c59a8f89 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -261,8 +261,21 @@ public class PackageHelper {
public static boolean fitsOnInternal(Context context, SessionParams params) throws IOException {
final StorageManager storage = context.getSystemService(StorageManager.class);
final UUID target = storage.getUuidForPath(Environment.getDataDirectory());
- return (params.sizeBytes <= storage.getAllocatableBytes(target,
- translateAllocateFlags(params.installFlags)));
+ final int flags = translateAllocateFlags(params.installFlags);
+
+ final long allocateableBytes = storage.getAllocatableBytes(target,
+ flags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY);
+
+ // If we fit on internal storage without including freeable cache space, don't bother
+ // checking to determine how much space is taken up by the cache.
+ if (params.sizeBytes <= allocateableBytes) {
+ return true;
+ }
+
+ final long cacheClearable = storage.getAllocatableBytes(target,
+ flags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY);
+
+ return params.sizeBytes <= allocateableBytes + cacheClearable;
}
public static boolean fitsOnExternal(Context context, SessionParams params) {
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index deff7ef7d39a..ddde7fef8962 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3208,28 +3208,28 @@ class StorageManagerService extends IStorageManager.Stub
// should be kept in sync with getFreeBytes().
final File path = storage.findPathForUuid(volumeUuid);
- final long usable = path.getUsableSpace();
- final long lowReserved = storage.getStorageLowBytes(path);
- final long fullReserved = storage.getStorageFullBytes(path);
+ long usable = 0;
+ long lowReserved = 0;
+ long fullReserved = 0;
+ long cacheClearable = 0;
- if (stats.isQuotaSupported(volumeUuid)) {
+ if ((flags & StorageManager.FLAG_ALLOCATE_CACHE_ONLY) == 0) {
+ usable = path.getUsableSpace();
+ lowReserved = storage.getStorageLowBytes(path);
+ fullReserved = storage.getStorageFullBytes(path);
+ }
+
+ if ((flags & StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY) == 0
+ && stats.isQuotaSupported(volumeUuid)) {
final long cacheTotal = stats.getCacheBytes(volumeUuid);
final long cacheReserved = storage.getStorageCacheBytes(path, flags);
- final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
+ cacheClearable = Math.max(0, cacheTotal - cacheReserved);
+ }
- if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
- return Math.max(0, (usable + cacheClearable) - fullReserved);
- } else {
- return Math.max(0, (usable + cacheClearable) - lowReserved);
- }
+ if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
+ return Math.max(0, (usable + cacheClearable) - fullReserved);
} else {
- // When we don't have fast quota information, we ignore cached
- // data and only consider unused bytes.
- if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
- return Math.max(0, usable - fullReserved);
- } else {
- return Math.max(0, usable - lowReserved);
- }
+ return Math.max(0, (usable + cacheClearable) - lowReserved);
}
} catch (IOException e) {
throw new ParcelableException(e);
@@ -3242,10 +3242,17 @@ class StorageManagerService extends IStorageManager.Stub
public void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) {
flags = adjustAllocateFlags(flags, Binder.getCallingUid(), callingPackage);
- final long allocatableBytes = getAllocatableBytes(volumeUuid, flags, callingPackage);
+ final long allocatableBytes = getAllocatableBytes(volumeUuid,
+ flags | StorageManager.FLAG_ALLOCATE_NON_CACHE_ONLY, callingPackage);
if (bytes > allocatableBytes) {
- throw new ParcelableException(new IOException("Failed to allocate " + bytes
- + " because only " + allocatableBytes + " allocatable"));
+ // If we don't have room without taking cache into account, check to see if we'd have
+ // room if we included freeable cache space.
+ final long cacheClearable = getAllocatableBytes(volumeUuid,
+ flags | StorageManager.FLAG_ALLOCATE_CACHE_ONLY, callingPackage);
+ if (bytes > allocatableBytes + cacheClearable) {
+ throw new ParcelableException(new IOException("Failed to allocate " + bytes
+ + " because only " + (allocatableBytes + cacheClearable) + " allocatable"));
+ }
}
final StorageManager storage = mContext.getSystemService(StorageManager.class);