Consistent "low storage" behavior.

When answering the question "how much space is free", use the same
logic for Settings UI and StorageManager.getAllocatableBytes().  That
is, the reported free space is usable bytes plus any cached data the
system is willing to delete automatically.

This does *not* include any reserved cache space, since we don't want
abusive apps to penalize other well-behaved apps that are storing
their data in cache locations.  Callers freeing cached data need to
now explicitly request defiance of the reserved cache space.  (Most
callers are already doing this by using FLAG_ALLOCATE_AGGRESSIVE.)

Rewrite the core logic of DeviceStorageMonitorService to understand
this new "reserved" cache space, and to be easier to understand.  It
also now handles cached data on adopted storage volumes, which had
been ignored until now.  Also fix bug where we had skipped "low"
broadcasts when the device skipped directly from/to "full" state.

Bug: 38008706
Test: cts-tradefed run commandAndExit cts-dev -m CtsJobSchedulerTestCases -t android.jobscheduler.cts.StorageConstraintTest
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.StorageHostTest
Change-Id: Icbdcf3b52775f7ada1ceaeff2f96094c8d8052f9
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 525b151..e5c42087 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2108,7 +2108,7 @@
     public void freeStorageAndNotify(String volumeUuid, long idealStorageSize,
             IPackageDataObserver observer) {
         try {
-            mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, observer);
+            mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, 0, observer);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2117,7 +2117,7 @@
     @Override
     public void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {
         try {
-            mPM.freeStorage(volumeUuid, freeStorageSize, pi);
+            mPM.freeStorage(volumeUuid, freeStorageSize, 0, pi);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/usage/IStorageStatsManager.aidl b/core/java/android/app/usage/IStorageStatsManager.aidl
index 5d1550f..15e5ea5 100644
--- a/core/java/android/app/usage/IStorageStatsManager.aidl
+++ b/core/java/android/app/usage/IStorageStatsManager.aidl
@@ -24,6 +24,7 @@
     boolean isQuotaSupported(String volumeUuid, String callingPackage);
     long getTotalBytes(String volumeUuid, String callingPackage);
     long getFreeBytes(String volumeUuid, String callingPackage);
+    long getCacheBytes(String volumeUuid, String callingPackage);
     long getCacheQuotaBytes(String volumeUuid, int uid, String callingPackage);
     StorageStats queryStatsForPackage(String volumeUuid, String packageName, int userId, String callingPackage);
     StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage);
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index d9d958c..0b2b190 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -142,6 +142,24 @@
         return getFreeBytes(convert(uuid));
     }
 
+    /** {@hide} */
+    public @BytesLong long getCacheBytes(@NonNull UUID storageUuid) throws IOException {
+        try {
+            return mService.getCacheBytes(convert(storageUuid), mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** {@hide} */
+    @Deprecated
+    public long getCacheBytes(String uuid) throws IOException {
+        return getCacheBytes(convert(uuid));
+    }
+
     /**
      * Return storage statistics for a specific package on the requested storage
      * volume.
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 7aaf453..2ebfa8f 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -360,7 +360,7 @@
      * the operation is completed
      */
      void freeStorageAndNotify(in String volumeUuid, in long freeStorageSize,
-             IPackageDataObserver observer);
+             int storageFlags, IPackageDataObserver observer);
 
     /**
      * Free storage by deleting LRU sorted list of cache files across
@@ -384,7 +384,7 @@
      * to indicate that no call back is desired.
      */
      void freeStorage(in String volumeUuid, in long freeStorageSize,
-             in IntentSender pi);
+             int storageFlags, in IntentSender pi);
 
     /**
      * Delete all the cache files in an applications cache directory
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index f361c54..d81ee4e 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1642,11 +1642,20 @@
      */
     @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
     @SystemApi
-    public static final int FLAG_ALLOCATE_AGGRESSIVE = 1;
+    public static final int FLAG_ALLOCATE_AGGRESSIVE = 1 << 0;
+
+    /**
+     * Flag indicating that a disk space allocation request should defy any
+     * reserved disk space.
+     *
+     * @hide
+     */
+    public static final int FLAG_ALLOCATE_DEFY_RESERVED = 1 << 1;
 
     /** @hide */
     @IntDef(flag = true, value = {
             FLAG_ALLOCATE_AGGRESSIVE,
+            FLAG_ALLOCATE_DEFY_RESERVED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AllocateFlags {}
diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
index 15dbddf..59aa50a 100644
--- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
@@ -492,7 +492,7 @@
             PackageDataObserver observer = new PackageDataObserver();
             //wait on observer
             synchronized(observer) {
-                getPm().freeStorageAndNotify(null, idealStorageSize, observer);
+                getPm().freeStorageAndNotify(null, idealStorageSize, 0, observer);
                 long waitTime = 0;
                 while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) {
                     observer.wait(WAIT_TIME_INCR);
@@ -517,7 +517,7 @@
         try {
             // Spin lock waiting for call back
             synchronized(r) {
-                getPm().freeStorage(null, idealStorageSize, pi.getIntentSender());
+                getPm().freeStorage(null, idealStorageSize, 0, pi.getIntentSender());
                 long waitTime = 0;
                 while(!r.isDone() && (waitTime < MAX_WAIT_TIME)) {
                     r.wait(WAIT_TIME_INCR);