Storage API polishing.

Based on API council feedback, switch to using real UUID objects
instead of Strings.  Since UUID is a general-purpose utility class
that will be passed around quite a bit, add it to Parcel and Bundle.

Define well-known namespaced UUID values for "default" and "primary
physical" storage devices, which will let us annotate a bunch of
things with @NonNull.

Define new extras for MANAGE_STORAGE intent that apps can use to
signal where and how much space they'd like the user to free up.

Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.StorageHostTest
Bug: 37325923, 35812899, 35806020
Change-Id: I8421b126d680f69141a361c1e77223fe2bf4a325
diff --git a/api/current.txt b/api/current.txt
index 5697b39..2edbb9a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6994,12 +6994,12 @@
   }
 
   public class StorageStatsManager {
-    method public long getFreeBytes(java.lang.String);
-    method public long getTotalBytes(java.lang.String);
-    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
-    method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+    method public long getFreeBytes(java.util.UUID) throws java.io.IOException;
+    method public long getTotalBytes(java.util.UUID) throws java.io.IOException;
+    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -10217,12 +10217,12 @@
     field public java.lang.String[] splitNames;
     field public java.lang.String[] splitPublicSourceDirs;
     field public java.lang.String[] splitSourceDirs;
+    field public java.util.UUID storageUuid;
     field public int targetSdkVersion;
     field public java.lang.String taskAffinity;
     field public int theme;
     field public int uiOptions;
     field public int uid;
-    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -30801,6 +30801,7 @@
     method public android.util.SizeF getSizeF(java.lang.String);
     method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
+    method public java.util.UUID getUuid(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
     method public void putBinder(java.lang.String, android.os.IBinder);
@@ -30825,6 +30826,7 @@
     method public void putSizeF(java.lang.String, android.util.SizeF);
     method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>);
     method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>);
+    method public void putUuid(java.lang.String, java.util.UUID);
     method public void readFromParcel(android.os.Parcel);
     method public void setClassLoader(java.lang.ClassLoader);
     method public void writeToParcel(android.os.Parcel, int);
@@ -31354,6 +31356,7 @@
     method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
     method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
     method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final java.util.UUID readUuid();
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -31399,6 +31402,7 @@
     method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
     method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
     method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
+    method public final void writeUuid(java.util.UUID);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -32029,15 +32033,16 @@
   }
 
   public class StorageManager {
-    method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
-    method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes(java.io.File);
-    method public long getCacheSizeBytes(java.io.File);
+    method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException;
+    method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException;
+    method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException;
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
     method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
+    method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
     method public boolean isEncrypted(java.io.File);
@@ -32049,7 +32054,10 @@
     method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException;
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
     field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
+    field public static final java.lang.String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
+    field public static final java.lang.String EXTRA_UUID = "android.os.storage.extra.UUID";
     field public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1
+    field public static final java.util.UUID UUID_DEFAULT;
   }
 
   public final class StorageVolume implements android.os.Parcelable {
diff --git a/api/removed.txt b/api/removed.txt
index 82705fd..5b69be4 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -26,6 +26,20 @@
 
 }
 
+package android.app.usage {
+
+  public class StorageStatsManager {
+    method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated boolean isQuotaSupported(java.lang.String);
+    method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+  }
+
+}
+
 package android.content {
 
   public abstract class Context {
@@ -41,6 +55,10 @@
 
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String volumeUuid;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -184,10 +202,14 @@
 package android.os.storage {
 
   public class StorageManager {
-    method public deprecated long getCacheQuotaBytes();
-    method public deprecated long getCacheSizeBytes();
-    method public deprecated long getExternalCacheQuotaBytes();
-    method public deprecated long getExternalCacheSizeBytes();
+    method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException;
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
     method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 8b2ac55..da5ec3b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7457,12 +7457,12 @@
   }
 
   public class StorageStatsManager {
-    method public long getFreeBytes(java.lang.String);
-    method public long getTotalBytes(java.lang.String);
-    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
-    method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+    method public long getFreeBytes(java.util.UUID) throws java.io.IOException;
+    method public long getTotalBytes(java.util.UUID) throws java.io.IOException;
+    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -10790,12 +10790,12 @@
     field public java.lang.String[] splitNames;
     field public java.lang.String[] splitPublicSourceDirs;
     field public java.lang.String[] splitSourceDirs;
+    field public java.util.UUID storageUuid;
     field public int targetSdkVersion;
     field public java.lang.String taskAffinity;
     field public int theme;
     field public int uiOptions;
     field public int uid;
-    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -33557,6 +33557,7 @@
     method public android.util.SizeF getSizeF(java.lang.String);
     method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
+    method public java.util.UUID getUuid(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
     method public void putBinder(java.lang.String, android.os.IBinder);
@@ -33581,6 +33582,7 @@
     method public void putSizeF(java.lang.String, android.util.SizeF);
     method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>);
     method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>);
+    method public void putUuid(java.lang.String, java.util.UUID);
     method public void readFromParcel(android.os.Parcel);
     method public void setClassLoader(java.lang.ClassLoader);
     method public void writeToParcel(android.os.Parcel, int);
@@ -34140,6 +34142,7 @@
     method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
     method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
     method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final java.util.UUID readUuid();
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -34185,6 +34188,7 @@
     method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
     method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
     method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
+    method public final void writeUuid(java.util.UUID);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -34920,15 +34924,16 @@
   }
 
   public class StorageManager {
-    method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
-    method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes(java.io.File);
-    method public long getCacheSizeBytes(java.io.File);
+    method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException;
+    method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException;
+    method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException;
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
     method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
+    method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
     method public boolean isEncrypted(java.io.File);
@@ -34940,7 +34945,10 @@
     method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException;
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
     field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
+    field public static final java.lang.String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
+    field public static final java.lang.String EXTRA_UUID = "android.os.storage.extra.UUID";
     field public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1
+    field public static final java.util.UUID UUID_DEFAULT;
   }
 
   public final class StorageVolume implements android.os.Parcelable {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index bdcafae..9a35c0f 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -24,6 +24,20 @@
 
 }
 
+package android.app.usage {
+
+  public class StorageStatsManager {
+    method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated boolean isQuotaSupported(java.lang.String);
+    method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+  }
+
+}
+
 package android.content {
 
   public abstract class Context {
@@ -39,6 +53,10 @@
 
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String volumeUuid;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -178,10 +196,14 @@
 package android.os.storage {
 
   public class StorageManager {
-    method public deprecated long getCacheQuotaBytes();
-    method public deprecated long getCacheSizeBytes();
-    method public deprecated long getExternalCacheQuotaBytes();
-    method public deprecated long getExternalCacheSizeBytes();
+    method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException;
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
     method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException;
diff --git a/api/test-current.txt b/api/test-current.txt
index 86227a7..8d5adea 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -7024,13 +7024,13 @@
   }
 
   public class StorageStatsManager {
-    method public long getFreeBytes(java.lang.String);
-    method public long getTotalBytes(java.lang.String);
-    method public boolean isQuotaSupported(java.lang.String);
-    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
-    method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+    method public long getFreeBytes(java.util.UUID) throws java.io.IOException;
+    method public long getTotalBytes(java.util.UUID) throws java.io.IOException;
+    method public boolean isQuotaSupported(java.util.UUID);
+    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -10253,12 +10253,12 @@
     field public java.lang.String[] splitNames;
     field public java.lang.String[] splitPublicSourceDirs;
     field public java.lang.String[] splitSourceDirs;
+    field public java.util.UUID storageUuid;
     field public int targetSdkVersion;
     field public java.lang.String taskAffinity;
     field public int theme;
     field public int uiOptions;
     field public int uid;
-    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -30908,6 +30908,7 @@
     method public android.util.SizeF getSizeF(java.lang.String);
     method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
+    method public java.util.UUID getUuid(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
     method public void putBinder(java.lang.String, android.os.IBinder);
@@ -30932,6 +30933,7 @@
     method public void putSizeF(java.lang.String, android.util.SizeF);
     method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>);
     method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>);
+    method public void putUuid(java.lang.String, java.util.UUID);
     method public void readFromParcel(android.os.Parcel);
     method public void setClassLoader(java.lang.ClassLoader);
     method public void writeToParcel(android.os.Parcel, int);
@@ -31482,6 +31484,7 @@
     method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
     method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
     method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final java.util.UUID readUuid();
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -31527,6 +31530,7 @@
     method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
     method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
     method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
+    method public final void writeUuid(java.util.UUID);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -32161,15 +32165,16 @@
   }
 
   public class StorageManager {
-    method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
-    method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes(java.io.File);
-    method public long getCacheSizeBytes(java.io.File);
+    method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException;
+    method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException;
+    method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException;
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
     method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
+    method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
     method public boolean isEncrypted(java.io.File);
@@ -32181,7 +32186,10 @@
     method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException;
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
     field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
+    field public static final java.lang.String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
+    field public static final java.lang.String EXTRA_UUID = "android.os.storage.extra.UUID";
     field public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1
+    field public static final java.util.UUID UUID_DEFAULT;
   }
 
   public final class StorageVolume implements android.os.Parcelable {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 82705fd..5b69be4 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -26,6 +26,20 @@
 
 }
 
+package android.app.usage {
+
+  public class StorageStatsManager {
+    method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated boolean isQuotaSupported(java.lang.String);
+    method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+  }
+
+}
+
 package android.content {
 
   public abstract class Context {
@@ -41,6 +55,10 @@
 
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String volumeUuid;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -184,10 +202,14 @@
 package android.os.storage {
 
   public class StorageManager {
-    method public deprecated long getCacheQuotaBytes();
-    method public deprecated long getCacheSizeBytes();
-    method public deprecated long getExternalCacheQuotaBytes();
-    method public deprecated long getExternalCacheSizeBytes();
+    method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException;
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
     method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException;
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index 6fc4f5c..4b6479a 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -16,17 +16,25 @@
 
 package android.app.usage;
 
+import static android.os.storage.StorageManager.convert;
+
+import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.annotation.WorkerThread;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.ParcelableException;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 
 import com.android.internal.util.Preconditions;
 
 import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
 
 /**
  * Provides access to detailed storage statistics.
@@ -50,36 +58,49 @@
 
     /** {@hide} */
     @TestApi
-    public boolean isQuotaSupported(String volumeUuid) {
+    public boolean isQuotaSupported(@NonNull UUID storageUuid) {
         try {
-            return mService.isQuotaSupported(volumeUuid, mContext.getOpPackageName());
+            return mService.isQuotaSupported(convert(storageUuid), mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public boolean isQuotaSupported(String uuid) {
+        return isQuotaSupported(convert(uuid));
+    }
+
     /**
-     * Return the total space on the requested storage volume.
+     * Return the total size of the media hosting this storage volume.
      * <p>
-     * To reduce end user confusion, this value is the total storage size
+     * To reduce end user confusion, this value matches the total storage size
      * advertised in a retail environment, which is typically larger than the
-     * actual writable partition total size.
-     * <p>
-     * This method may take several seconds to calculate the requested values,
-     * so it should only be called from a worker thread.
+     * actual usable partition space.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
+     * @throws IOException when the storage device isn't present.
      */
     @WorkerThread
-    public long getTotalBytes(String volumeUuid) {
+    public long getTotalBytes(@NonNull UUID storageUuid) throws IOException {
         try {
-            return mService.getTotalBytes(volumeUuid, mContext.getOpPackageName());
+            return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public long getTotalBytes(String uuid) throws IOException {
+        return getTotalBytes(convert(uuid));
+    }
+
     /**
      * Return the free space on the requested storage volume.
      * <p>
@@ -90,18 +111,28 @@
      * This method may take several seconds to calculate the requested values,
      * so it should only be called from a worker thread.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
+     * @throws IOException when the storage device isn't present.
      */
     @WorkerThread
-    public long getFreeBytes(String volumeUuid) {
+    public long getFreeBytes(@NonNull UUID storageUuid) throws IOException {
         try {
-            return mService.getFreeBytes(volumeUuid, mContext.getOpPackageName());
+            return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public long getFreeBytes(String uuid) throws IOException {
+        return getFreeBytes(convert(uuid));
+    }
+
     /**
      * Return storage statistics for a specific package on the requested storage
      * volume.
@@ -112,27 +143,41 @@
      * Note: if the requested package uses the {@code android:sharedUserId}
      * manifest feature, this call will be forced into a slower manual
      * calculation path. If possible, consider always using
-     * {@link #queryStatsForUid(String, int)}, which is typically faster.
+     * {@link #queryStatsForUid(UUID, int)}, which is typically faster.
      * </p>
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
      * @param packageName the package name you're interested in.
      * @param user the user you're interested in.
-     * @see ApplicationInfo#volumeUuid
+     * @throws PackageManager.NameNotFoundException when the requested package
+     *             name isn't installed for the requested user.
+     * @throws IOException when the storage device isn't present.
+     * @see ApplicationInfo#storageUuid
      * @see PackageInfo#packageName
      */
     @WorkerThread
-    public StorageStats queryStatsForPackage(String volumeUuid, String packageName,
-            UserHandle user) {
+    public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, String packageName,
+            UserHandle user) throws PackageManager.NameNotFoundException, IOException {
         try {
-            return mService.queryStatsForPackage(volumeUuid, packageName, user.getIdentifier(),
-                    mContext.getOpPackageName());
+            return mService.queryStatsForPackage(convert(storageUuid), packageName,
+                    user.getIdentifier(), mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(PackageManager.NameNotFoundException.class);
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public StorageStats queryStatsForPackage(String uuid, String packageName,
+            UserHandle user) throws PackageManager.NameNotFoundException, IOException {
+        return queryStatsForPackage(convert(uuid), packageName, user);
+    }
+
     /**
      * Return storage statistics for a specific UID on the requested storage
      * volume.
@@ -140,21 +185,32 @@
      * This method may take several seconds to calculate the requested values,
      * so it should only be called from a worker thread.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
      * @param uid the UID you're interested in.
-     * @see ApplicationInfo#volumeUuid
+     * @throws IOException when the storage device isn't present.
+     * @see ApplicationInfo#storageUuid
      * @see ApplicationInfo#uid
      */
     @WorkerThread
-    public StorageStats queryStatsForUid(String volumeUuid, int uid) {
+    public StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) throws IOException {
         try {
-            return mService.queryStatsForUid(volumeUuid, uid, mContext.getOpPackageName());
+            return mService.queryStatsForUid(convert(storageUuid), uid,
+                    mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public StorageStats queryStatsForUid(String uuid, int uid) throws IOException {
+        return queryStatsForUid(convert(uuid), uid);
+    }
+
     /**
      * Return storage statistics for a specific {@link UserHandle} on the
      * requested storage volume.
@@ -162,21 +218,32 @@
      * This method may take several seconds to calculate the requested values,
      * so it should only be called from a worker thread.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
      * @param user the user you're interested in.
+     * @throws IOException when the storage device isn't present.
      * @see android.os.Process#myUserHandle()
      */
     @WorkerThread
-    public StorageStats queryStatsForUser(String volumeUuid, UserHandle user) {
+    public StorageStats queryStatsForUser(@NonNull UUID storageUuid, UserHandle user)
+            throws IOException {
         try {
-            return mService.queryStatsForUser(volumeUuid, user.getIdentifier(),
+            return mService.queryStatsForUser(convert(storageUuid), user.getIdentifier(),
                     mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public StorageStats queryStatsForUser(String uuid, UserHandle user) throws IOException {
+        return queryStatsForUser(convert(uuid), user);
+    }
+
     /**
      * Return shared/external storage statistics for a specific
      * {@link UserHandle} on the requested storage volume.
@@ -184,20 +251,32 @@
      * This method may take several seconds to calculate the requested values,
      * so it should only be called from a worker thread.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
+     * @throws IOException when the storage device isn't present.
      * @see android.os.Process#myUserHandle()
      */
     @WorkerThread
-    public ExternalStorageStats queryExternalStatsForUser(String volumeUuid, UserHandle user) {
+    public ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid,
+            UserHandle user) throws IOException {
         try {
-            return mService.queryExternalStatsForUser(volumeUuid, user.getIdentifier(),
+            return mService.queryExternalStatsForUser(convert(storageUuid), user.getIdentifier(),
                     mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public ExternalStorageStats queryExternalStatsForUser(String uuid, UserHandle user)
+            throws IOException {
+        return queryExternalStatsForUser(convert(uuid), user);
+    }
+
     /** {@hide} */
     public long getCacheQuotaBytes(String volumeUuid, int uid) {
         try {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 5f53e27..8b2809a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -29,6 +29,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.Printer;
 import android.util.SparseArray;
@@ -41,6 +42,7 @@
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Objects;
+import java.util.UUID;
 
 /**
  * Information you can retrieve about a particular application.  This
@@ -621,12 +623,17 @@
      */
     public float maxAspectRatio;
 
+    /** @removed */
+    @Deprecated
+    public String volumeUuid;
+
     /**
      * UUID of the storage volume on which this application is being hosted. For
      * apps hosted on the default internal storage at
-     * {@link Environment#getDataDirectory()}, the UUID value is {@code null}.
+     * {@link Environment#getDataDirectory()}, the UUID value is
+     * {@link StorageManager#UUID_DEFAULT}.
      */
-    public String volumeUuid;
+    public UUID storageUuid;
 
     /** {@hide} */
     public String scanSourceDir;
@@ -1134,6 +1141,7 @@
         compatibleWidthLimitDp = orig.compatibleWidthLimitDp;
         largestWidthLimitDp = orig.largestWidthLimitDp;
         volumeUuid = orig.volumeUuid;
+        storageUuid = orig.storageUuid;
         scanSourceDir = orig.scanSourceDir;
         scanPublicSourceDir = orig.scanPublicSourceDir;
         sourceDir = orig.sourceDir;
@@ -1195,7 +1203,7 @@
         dest.writeInt(requiresSmallestWidthDp);
         dest.writeInt(compatibleWidthLimitDp);
         dest.writeInt(largestWidthLimitDp);
-        dest.writeString(volumeUuid);
+        dest.writeUuid(storageUuid);
         dest.writeString(scanSourceDir);
         dest.writeString(scanPublicSourceDir);
         dest.writeString(sourceDir);
@@ -1257,7 +1265,8 @@
         requiresSmallestWidthDp = source.readInt();
         compatibleWidthLimitDp = source.readInt();
         largestWidthLimitDp = source.readInt();
-        volumeUuid = source.readString();
+        storageUuid = source.readUuid();
+        volumeUuid = StorageManager.convert(storageUuid);
         scanSourceDir = source.readString();
         scanPublicSourceDir = source.readString();
         sourceDir = source.readString();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 430d8b1..66b4718 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -66,6 +66,7 @@
 import android.os.PatternMatcher;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.system.ErrnoException;
 import android.system.OsConstants;
 import android.system.StructStat;
@@ -116,6 +117,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.ZipEntry;
 
@@ -5741,11 +5743,14 @@
         }
 
         public void setApplicationVolumeUuid(String volumeUuid) {
+            final UUID storageUuid = StorageManager.convert(volumeUuid);
             this.applicationInfo.volumeUuid = volumeUuid;
+            this.applicationInfo.storageUuid = storageUuid;
             if (childPackages != null) {
                 final int packageCount = childPackages.size();
                 for (int i = 0; i < packageCount; i++) {
                     childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
+                    childPackages.get(i).applicationInfo.storageUuid = storageUuid;
                 }
             }
         }
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 9b5ff29..167c46d 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -25,6 +25,7 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.UUID;
 
 /**
  * A mapping from String keys to various {@link Parcelable} values.
@@ -476,6 +477,18 @@
     }
 
     /**
+     * Inserts a UUID value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a UUID object, or null
+     */
+    public void putUuid(@Nullable String key, @Nullable UUID value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
      * Inserts an array of Parcelable values into the mapping of this Bundle,
      * replacing any existing value for the given key.  Either key or value may
      * be null.
@@ -858,6 +871,26 @@
      * value is explicitly associated with the key.
      *
      * @param key a String, or null
+     * @return a UUID value, or null
+     */
+    @Nullable
+    public UUID getUuid(@Nullable String key) {
+        unparcel();
+        final Object o = mMap.get(key);
+        try {
+            return (UUID) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "UUID", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
      * @return a Bundle value, or null
      */
     @Nullable
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index c3836a3..c1647c7 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -16,8 +16,6 @@
 
 package android.os;
 
-import android.annotation.IntegerRes;
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -29,6 +27,9 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
+import dalvik.annotation.optimization.FastNative;
+import dalvik.system.VMRuntime;
+
 import libcore.util.SneakyThrow;
 
 import java.io.ByteArrayInputStream;
@@ -49,9 +50,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
-import dalvik.annotation.optimization.FastNative;
-import dalvik.system.VMRuntime;
+import java.util.UUID;
 
 /**
  * Container for a message (data and object references) that can
@@ -243,6 +242,7 @@
     private static final int VAL_SIZE = 26;
     private static final int VAL_SIZEF = 27;
     private static final int VAL_DOUBLEARRAY = 28;
+    private static final int VAL_UUID = 29;
 
     // The initial int32 in a Binder call's reply Parcel header:
     // Keep these in sync with libbinder's binder/Status.h.
@@ -831,6 +831,15 @@
     }
 
     /**
+     * Flatten a UUID into the parcel at the current dataPosition(),
+     * growing dataCapacity() if needed.
+     */
+    public final void writeUuid(UUID val) {
+        writeLong(val.getMostSignificantBits());
+        writeLong(val.getLeastSignificantBits());
+    }
+
+    /**
      * Flatten a List into the parcel at the current dataPosition(), growing
      * dataCapacity() if needed.  The List values are written using
      * {@link #writeValue} and must follow the specification there.
@@ -1678,6 +1687,9 @@
         } else if (v instanceof double[]) {
             writeInt(VAL_DOUBLEARRAY);
             writeDoubleArray((double[]) v);
+        } else if (v instanceof UUID) {
+            writeInt(VAL_UUID);
+            writeUuid((UUID) v);
         } else {
             Class<?> clazz = v.getClass();
             if (clazz.isArray() && clazz.getComponentType() == Object.class) {
@@ -2182,6 +2194,13 @@
     }
 
     /**
+     * Read a UUID from the parcel at the current dataPosition().
+     */
+    public final UUID readUuid() {
+        return new UUID(readLong(), readLong());
+    }
+
+    /**
      * Read and return a byte[] object from the parcel.
      */
     public final byte[] createByteArray() {
@@ -2731,6 +2750,9 @@
         case VAL_DOUBLEARRAY:
             return createDoubleArray();
 
+        case VAL_UUID:
+            return readUuid();
+
         default:
             int off = dataPosition() - 4;
             throw new RuntimeException(
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index b5af766..3942531 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -66,6 +66,7 @@
 
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -77,6 +78,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
+import java.util.UUID;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -117,19 +119,66 @@
     public static final String UUID_PRIVATE_INTERNAL = null;
     /** {@hide} */
     public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
+    /** {@hide} */
+    public static final String UUID_SYSTEM = "system";
 
+    // NOTE: UUID constants below are namespaced
+    // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad default
+    // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad primary_physical
+    // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad system
 
     /**
-     * Activity Action: Allows the user to manage their storage. This activity provides the ability
-     * to free up space on the device by deleting data such as apps.
+     * UUID representing the default internal storage of this device which
+     * provides {@link Environment#getDataDirectory()}.
      * <p>
-     * Input: Nothing.
+     * This value is constant across all devices and it will never change, and
+     * thus it cannot be used to uniquely identify a particular physical device.
+     *
+     * @see #getUuidForPath(File)
+     */
+    public static final UUID UUID_DEFAULT = UUID
+            .fromString("41217664-9172-527a-b3d5-edabb50a7d69");
+
+    /** {@hide} */
+    public static final UUID UUID_PRIMARY_PHYSICAL_ = UUID
+            .fromString("0f95a519-dae7-5abf-9519-fbd6209e05fd");
+
+    /** {@hide} */
+    public static final UUID UUID_SYSTEM_ = UUID
+            .fromString("5d258386-e60d-59e3-826d-0089cdd42cc0");
+
+    /**
+     * Activity Action: Allows the user to manage their storage. This activity
+     * provides the ability to free up space on the device by deleting data such
+     * as apps.
      * <p>
-     * Output: Nothing.
+     * If the sending application has a specific storage device or allocation
+     * size in mind, they can optionally define {@link #EXTRA_UUID} or
+     * {@link #EXTRA_REQUESTED_BYTES}, respectively.
      */
     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_MANAGE_STORAGE
-            = "android.os.storage.action.MANAGE_STORAGE";
+    public static final String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
+
+    /**
+     * Extra {@link UUID} used to indicate the storage volume where an
+     * application is interested in allocating or managing disk space.
+     *
+     * @see #ACTION_MANAGE_STORAGE
+     * @see #UUID_DEFAULT
+     * @see #getUuidForPath(File)
+     */
+    public static final String EXTRA_UUID = "android.os.storage.extra.UUID";
+
+    /**
+     * Extra used to indicate the total size (in bytes) that an application is
+     * interested in allocating.
+     * <p>
+     * When defined, the management UI will help guide the user to free up
+     * enough disk space to reach this requested value.
+     *
+     * @see #ACTION_MANAGE_STORAGE
+     */
+    public static final String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
 
     /** {@hide} */
     public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
@@ -668,34 +717,44 @@
         }
     }
 
-    /** {@hide} */
-    public @Nullable String findUuidForPath(File path) {
+    /**
+     * Return a UUID identifying the storage volume that hosts the given
+     * filesystem path.
+     * <p>
+     * If this path is hosted by the default internal storage of the device at
+     * {@link Environment#getDataDirectory()}, the returned value will be
+     * {@link #UUID_DEFAULT}.
+     *
+     * @throws IOException when the storage device at the given path isn't
+     *             present, or when it doesn't have a valid UUID.
+     */
+    public @NonNull UUID getUuidForPath(@NonNull File path) throws IOException {
         Preconditions.checkNotNull(path);
         final String pathString = path.getAbsolutePath();
         if (FileUtils.contains(Environment.getDataDirectory().getAbsolutePath(), pathString)) {
-            return StorageManager.UUID_PRIVATE_INTERNAL;
+            return UUID_DEFAULT;
         }
         try {
             for (VolumeInfo vol : mStorageManager.getVolumes(0)) {
                 if (vol.path != null && FileUtils.contains(vol.path, pathString)) {
                     // TODO: verify that emulated adopted devices have UUID of
                     // underlying volume
-                    return vol.fsUuid;
+                    return convert(vol.fsUuid);
                 }
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-        throw new IllegalStateException("Failed to find a storage device for " + path);
+        throw new FileNotFoundException("Failed to find a storage device for " + path);
     }
 
     /** {@hide} */
-    public @Nullable File findPathForUuid(String volumeUuid) {
+    public @NonNull File findPathForUuid(String volumeUuid) throws FileNotFoundException {
         final VolumeInfo vol = findVolumeByQualifiedUuid(volumeUuid);
         if (vol != null) {
             return vol.getPath();
         }
-        throw new IllegalStateException("Failed to find a storage device for " + volumeUuid);
+        throw new FileNotFoundException("Failed to find a storage device for " + volumeUuid);
     }
 
     /** {@hide} */
@@ -1451,7 +1510,7 @@
 
     /**
      * Return quota size in bytes for all cached data belonging to the calling
-     * app on the filesystem that hosts the given path.
+     * app on the given storage volume.
      * <p>
      * If your app goes above this quota, your cached files will be some of the
      * first to be deleted when additional disk space is needed. Conversely, if
@@ -1466,21 +1525,34 @@
      * as a single unit.
      * </p>
      *
-     * @see #getCacheSizeBytes(File)
+     * @param storageUuid the UUID of the storage volume that you're interested
+     *            in. The UUID for a specific path can be obtained using
+     *            {@link #getUuidForPath(File)}.
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support cache quotas.
+     * @see #getCacheSizeBytes(UUID)
      */
-    public long getCacheQuotaBytes(File path) {
+    public long getCacheQuotaBytes(@NonNull UUID storageUuid) throws IOException {
         try {
-            final String volumeUuid = findUuidForPath(path);
             final ApplicationInfo app = mContext.getApplicationInfo();
-            return mStorageManager.getCacheQuotaBytes(volumeUuid, app.uid);
+            return mStorageManager.getCacheQuotaBytes(convert(storageUuid), app.uid);
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public long getCacheQuotaBytes(@NonNull File path) throws IOException {
+        return getCacheQuotaBytes(getUuidForPath(path));
+    }
+
     /**
      * Return total size in bytes of all cached data belonging to the calling
-     * app on the filesystem that hosts the given path.
+     * app on the given storage volume.
      * <p>
      * Cached data tracked by this method always includes
      * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and
@@ -1493,13 +1565,20 @@
      * as a single unit.
      * </p>
      *
-     * @see #getCacheQuotaBytes()
+     * @param storageUuid the UUID of the storage volume that you're interested
+     *            in. The UUID for a specific path can be obtained using
+     *            {@link #getUuidForPath(File)}.
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support cache quotas.
+     * @see #getCacheQuotaBytes(UUID)
      */
-    public long getCacheSizeBytes(File path) {
+    public long getCacheSizeBytes(@NonNull UUID storageUuid) throws IOException {
         try {
-            final String volumeUuid = findUuidForPath(path);
             final ApplicationInfo app = mContext.getApplicationInfo();
-            return mStorageManager.getCacheSizeBytes(volumeUuid, app.uid);
+            return mStorageManager.getCacheSizeBytes(convert(storageUuid), app.uid);
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1507,25 +1586,31 @@
 
     /** @removed */
     @Deprecated
-    public long getCacheQuotaBytes() {
+    public long getCacheSizeBytes(@NonNull File path) throws IOException {
+        return getCacheSizeBytes(getUuidForPath(path));
+    }
+
+    /** @removed */
+    @Deprecated
+    public long getCacheQuotaBytes() throws IOException {
         return getCacheQuotaBytes(mContext.getCacheDir());
     }
 
     /** @removed */
     @Deprecated
-    public long getCacheSizeBytes() {
+    public long getCacheSizeBytes() throws IOException {
         return getCacheSizeBytes(mContext.getCacheDir());
     }
 
     /** @removed */
     @Deprecated
-    public long getExternalCacheQuotaBytes() {
+    public long getExternalCacheQuotaBytes() throws IOException {
         return getCacheQuotaBytes(mContext.getExternalCacheDir());
     }
 
     /** @removed */
     @Deprecated
-    public long getExternalCacheSizeBytes() {
+    public long getExternalCacheSizeBytes() throws IOException {
         return getCacheSizeBytes(mContext.getExternalCacheDir());
     }
 
@@ -1542,8 +1627,8 @@
      * this flag to take effect.
      * </p>
      *
-     * @see #getAllocatableBytes(File, int)
-     * @see #allocateBytes(File, long, int)
+     * @see #getAllocatableBytes(UUID, int)
+     * @see #allocateBytes(UUID, long, int)
      * @see #allocateBytes(FileDescriptor, long, int)
      */
     @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
@@ -1558,32 +1643,43 @@
 
     /**
      * Return the maximum number of new bytes that your app can allocate for
-     * itself using {@link #allocateBytes(File, long, int)} at the given path.
-     * This value is typically larger than {@link File#getUsableSpace()}, since
-     * the system may be willing to delete cached files to satisfy an allocation
-     * request.
+     * itself on the given storage volume. This value is typically larger than
+     * {@link File#getUsableSpace()}, since the system may be willing to delete
+     * cached files to satisfy an allocation request. You can then allocate
+     * space for yourself using {@link #allocateBytes(UUID, long, int)} or
+     * {@link #allocateBytes(FileDescriptor, long, int)}.
      * <p>
      * This method is best used as a pre-flight check, such as deciding if there
      * is enough space to store an entire music album before you allocate space
      * for each audio file in the album. Attempts to allocate disk space beyond
      * the returned value will fail.
+     * <p>
+     * If the returned value is not large enough for the data you'd like to
+     * store, you can launch {@link #ACTION_MANAGE_STORAGE} with the
+     * {@link #EXTRA_UUID} and {@link #EXTRA_REQUESTED_BYTES} options to help
+     * involve the user in freeing up disk space.
      * <p class="note">
      * Note: if your app uses the {@code android:sharedUserId} manifest feature,
      * then allocatable space for all packages in your shared UID is tracked
      * together as a single unit.
      * </p>
      *
-     * @param path the path where you're considering allocating disk space,
-     *            since allocatable space can vary widely depending on the
-     *            underlying storage device.
+     * @param storageUuid the UUID of the storage volume where you're
+     *            considering allocating disk space, since allocatable space can
+     *            vary widely depending on the underlying storage device. The
+     *            UUID for a specific path can be obtained using
+     *            {@link #getUuidForPath(File)}.
      * @param flags to apply to the request.
      * @return the maximum number of new bytes that the calling app can allocate
-     *         using {@link #allocateBytes(File, long, int)}.
+     *         using {@link #allocateBytes(UUID, long, int)} or
+     *         {@link #allocateBytes(FileDescriptor, long, int)}.
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support allocating space.
      */
-    public long getAllocatableBytes(File path, @AllocateFlags int flags) throws IOException {
+    public long getAllocatableBytes(@NonNull UUID storageUuid, @AllocateFlags int flags)
+            throws IOException {
         try {
-            final String volumeUuid = findUuidForPath(path);
-            return mStorageManager.getAllocatableBytes(volumeUuid, flags);
+            return mStorageManager.getAllocatableBytes(convert(storageUuid), flags);
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
             throw new RuntimeException(e);
@@ -1592,28 +1688,40 @@
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public long getAllocatableBytes(@NonNull File path, @AllocateFlags int flags)
+            throws IOException {
+        return getAllocatableBytes(getUuidForPath(path), flags);
+    }
+
     /**
-     * Allocate the requested number of bytes for your application to use at the
-     * given path. This will cause the system to delete any cached files
-     * necessary to satisfy your request.
+     * Allocate the requested number of bytes for your application to use on the
+     * given storage volume. This will cause the system to delete any cached
+     * files necessary to satisfy your request.
      * <p>
      * Attempts to allocate disk space beyond the value returned by
-     * {@link #getAllocatableBytes(File, int)} will fail.
+     * {@link #getAllocatableBytes(UUID, int)} will fail.
      * <p>
      * Since multiple apps can be running simultaneously, this method may be
      * subject to race conditions. If possible, consider using
      * {@link #allocateBytes(FileDescriptor, long, int)} which will guarantee
      * that bytes are allocated to an opened file.
      *
-     * @param path the path where you'd like to allocate disk space.
+     * @param storageUuid the UUID of the storage volume where you'd like to
+     *            allocate disk space. The UUID for a specific path can be
+     *            obtained using {@link #getUuidForPath(File)}.
      * @param bytes the number of bytes to allocate.
      * @param flags to apply to the request.
-     * @see #getAllocatableBytes(File, int)
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support allocating space, or if the device had
+     *             trouble allocating the requested space.
+     * @see #getAllocatableBytes(UUID, int)
      */
-    public void allocateBytes(File path, long bytes, @AllocateFlags int flags) throws IOException {
+    public void allocateBytes(@NonNull UUID storageUuid, long bytes, @AllocateFlags int flags)
+            throws IOException {
         try {
-            final String volumeUuid = findUuidForPath(path);
-            mStorageManager.allocateBytes(volumeUuid, bytes, flags);
+            mStorageManager.allocateBytes(convert(storageUuid), bytes, flags);
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
         } catch (RemoteException e) {
@@ -1621,13 +1729,20 @@
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public void allocateBytes(@NonNull File path, long bytes, @AllocateFlags int flags)
+            throws IOException {
+        allocateBytes(getUuidForPath(path), bytes, flags);
+    }
+
     /**
      * Allocate the requested number of bytes for your application to use in the
      * given open file. This will cause the system to delete any cached files
      * necessary to satisfy your request.
      * <p>
      * Attempts to allocate disk space beyond the value returned by
-     * {@link #getAllocatableBytes(File, int)} will fail.
+     * {@link #getAllocatableBytes(UUID, int)} will fail.
      * <p>
      * This method guarantees that bytes have been allocated to the opened file,
      * otherwise it will throw if fast allocation is not possible. Fast
@@ -1636,9 +1751,15 @@
      *
      * @param fd the open file that you'd like to allocate disk space for.
      * @param bytes the number of bytes to allocate. This is the desired final
-     *            size of the open file.
+     *            size of the open file. If the open file is smaller than this
+     *            requested size, it will be extended without modifying any
+     *            existing contents. If the open file is larger than this
+     *            requested size, it will be truncated.
      * @param flags to apply to the request.
-     * @see #getAllocatableBytes(File, int)
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support allocating space, or if the device had
+     *             trouble allocating the requested space.
+     * @see #getAllocatableBytes(UUID, int)
      * @see Environment#isExternalStorageEmulated(File)
      */
     public void allocateBytes(FileDescriptor fd, long bytes, @AllocateFlags int flags)
@@ -1777,6 +1898,32 @@
         return isCacheBehavior(path, XATTR_CACHE_TOMBSTONE);
     }
 
+    /** {@hide} */
+    public static UUID convert(String uuid) {
+        if (Objects.equals(uuid, UUID_PRIVATE_INTERNAL)) {
+            return UUID_DEFAULT;
+        } else if (Objects.equals(uuid, UUID_PRIMARY_PHYSICAL)) {
+            return UUID_PRIMARY_PHYSICAL_;
+        } else if (Objects.equals(uuid, UUID_SYSTEM)) {
+            return UUID_SYSTEM_;
+        } else {
+            return UUID.fromString(uuid);
+        }
+    }
+
+    /** {@hide} */
+    public static String convert(UUID storageUuid) {
+        if (UUID_DEFAULT.equals(storageUuid)) {
+            return UUID_PRIVATE_INTERNAL;
+        } else if (UUID_PRIMARY_PHYSICAL_.equals(storageUuid)) {
+            return UUID_PRIMARY_PHYSICAL;
+        } else if (UUID_SYSTEM_.equals(storageUuid)) {
+            return UUID_SYSTEM;
+        } else {
+            return storageUuid.toString();
+        }
+    }
+
     private final Object mFuseAppLoopLock = new Object();
 
     @GuardedBy("mFuseAppLoopLock")
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 8a86c13..10f3b63 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -29,6 +29,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageStats;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
@@ -52,6 +53,7 @@
 import com.android.settingslib.R;
 
 import java.io.File;
+import java.io.IOException;
 import java.text.Collator;
 import java.text.Normalizer;
 import java.text.Normalizer.Form;
@@ -61,6 +63,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Objects;
+import java.util.UUID;
 import java.util.regex.Pattern;
 
 /**
@@ -114,7 +117,7 @@
     final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
     List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();
     long mCurId = 1;
-    String mCurComputingSizeUuid;
+    UUID mCurComputingSizeUuid;
     String mCurComputingSizePkg;
     int mCurComputingSizeUserId;
     boolean mSessionsChanged;
@@ -334,15 +337,23 @@
             AppEntry entry = mEntriesMap.get(userId).get(packageName);
             if (entry != null && (entry.info.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
                 mBackgroundHandler.post(() -> {
-                    final StorageStats stats = mStats.queryStatsForPackage(entry.info.volumeUuid,
-                            packageName, UserHandle.of(userId));
-                    final PackageStats legacyStats = new PackageStats(packageName, userId);
-                    legacyStats.codeSize = stats.getCodeBytes();
-                    legacyStats.dataSize = stats.getDataBytes();
-                    legacyStats.cacheSize = stats.getCacheBytes();
                     try {
-                        mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacyStats, true);
-                    } catch (RemoteException ignored) {
+                        final StorageStats stats = mStats.queryStatsForPackage(
+                                entry.info.storageUuid, packageName, UserHandle.of(userId));
+                        final PackageStats legacy = new PackageStats(packageName, userId);
+                        legacy.codeSize = stats.getCodeBytes();
+                        legacy.dataSize = stats.getDataBytes();
+                        legacy.cacheSize = stats.getCacheBytes();
+                        try {
+                            mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacy, true);
+                        } catch (RemoteException ignored) {
+                        }
+                    } catch (NameNotFoundException | IOException e) {
+                        Log.w(TAG, "Failed to query stats: " + e);
+                        try {
+                            mBackgroundHandler.mStatsObserver.onGetStatsCompleted(null, false);
+                        } catch (RemoteException ignored) {
+                        }
                     }
                 });
             }
@@ -979,7 +990,7 @@
                                         mMainHandler.sendMessage(m);
                                     }
                                     entry.sizeLoadStart = now;
-                                    mCurComputingSizeUuid = entry.info.volumeUuid;
+                                    mCurComputingSizeUuid = entry.info.storageUuid;
                                     mCurComputingSizePkg = entry.info.packageName;
                                     mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
 
@@ -988,17 +999,17 @@
                                             final StorageStats stats = mStats.queryStatsForPackage(
                                                     mCurComputingSizeUuid, mCurComputingSizePkg,
                                                     UserHandle.of(mCurComputingSizeUserId));
-                                            final PackageStats legacyStats = new PackageStats(
+                                            final PackageStats legacy = new PackageStats(
                                                     mCurComputingSizePkg, mCurComputingSizeUserId);
-                                            legacyStats.codeSize = stats.getCodeBytes();
-                                            legacyStats.dataSize = stats.getDataBytes();
-                                            legacyStats.cacheSize = stats.getCacheBytes();
+                                            legacy.codeSize = stats.getCodeBytes();
+                                            legacy.dataSize = stats.getDataBytes();
+                                            legacy.cacheSize = stats.getCacheBytes();
                                             try {
-                                                mStatsObserver.onGetStatsCompleted(legacyStats, true);
+                                                mStatsObserver.onGetStatsCompleted(legacy, true);
                                             } catch (RemoteException ignored) {
                                             }
-                                        } catch (IllegalStateException e) {
-                                            Log.e(TAG,"An exception occurred while fetching app size", e);
+                                        } catch (NameNotFoundException | IOException e) {
+                                            Log.w(TAG, "Failed to query stats: " + e);
                                             try {
                                                 mStatsObserver.onGetStatsCompleted(null, false);
                                             } catch (RemoteException ignored) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
index 2183573..34fdc9d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
@@ -19,9 +19,12 @@
 import android.app.usage.StorageStats;
 import android.app.usage.StorageStatsManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.support.annotation.VisibleForTesting;
 
+import java.io.IOException;
+
 /**
  * StorageStatsSource wraps the StorageStatsManager for testability purposes.
  */
@@ -32,17 +35,21 @@
         mStorageStatsManager = context.getSystemService(StorageStatsManager.class);
     }
 
-    public StorageStatsSource.ExternalStorageStats getExternalStorageStats(String volumeUuid, UserHandle user) {
+    public StorageStatsSource.ExternalStorageStats getExternalStorageStats(String volumeUuid,
+            UserHandle user) throws IOException {
         return new StorageStatsSource.ExternalStorageStats(
                 mStorageStatsManager.queryExternalStatsForUser(volumeUuid, user));
     }
 
-    public StorageStatsSource.AppStorageStats getStatsForUid(String volumeUuid, int uid) {
-        return new StorageStatsSource.AppStorageStatsImpl(mStorageStatsManager.queryStatsForUid(volumeUuid, uid));
+    public StorageStatsSource.AppStorageStats getStatsForUid(String volumeUuid, int uid)
+            throws IOException {
+        return new StorageStatsSource.AppStorageStatsImpl(
+                mStorageStatsManager.queryStatsForUid(volumeUuid, uid));
     }
 
     public StorageStatsSource.AppStorageStats getStatsForPackage(
-            String volumeUuid, String packageName, UserHandle user) {
+            String volumeUuid, String packageName, UserHandle user)
+            throws PackageManager.NameNotFoundException, IOException {
         return new StorageStatsSource.AppStorageStatsImpl(
                 mStorageStatsManager.queryStatsForPackage(volumeUuid, packageName, user));
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
index 88f133c..ccf7a0b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -20,11 +20,16 @@
 import android.app.usage.StorageStatsManager;
 import android.content.Context;
 import android.os.storage.VolumeInfo;
+import android.util.Log;
+
+import java.io.IOException;
 
 /**
  * PrivateStorageInfo provides information about the total and free storage on the device.
  */
 public class PrivateStorageInfo {
+    private static final String TAG = "PrivateStorageInfo";
+
     public final long freeBytes;
     public final long totalBytes;
 
@@ -41,8 +46,12 @@
         long privateTotalBytes = 0;
         for (VolumeInfo info : sm.getVolumes()) {
             if (info.getType() == VolumeInfo.TYPE_PRIVATE && info.isMountedReadable()) {
-                privateTotalBytes += sm.getTotalBytes(stats, info);
-                privateFreeBytes += sm.getFreeBytes(stats, info);
+                try {
+                    privateTotalBytes += sm.getTotalBytes(stats, info);
+                    privateFreeBytes += sm.getFreeBytes(stats, info);
+                } catch (IOException e) {
+                    Log.w(TAG, e);
+                }
             }
         }
         return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
@@ -51,6 +60,11 @@
     public static long getTotalSize(VolumeInfo info, long totalInternalStorage) {
         final Context context = AppGlobals.getInitialApplication();
         final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
-        return stats.getTotalBytes(info.getFsUuid());
+        try {
+            return stats.getTotalBytes(info.getFsUuid());
+        } catch (IOException e) {
+            Log.w(TAG, e);
+            return 0;
+        }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
index 11060e6..b57b6cc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
@@ -20,6 +20,7 @@
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -49,12 +50,12 @@
     }
 
     @Override
-    public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) {
+    public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException {
         return stats.getTotalBytes(volume.getFsUuid());
     }
 
     @Override
-    public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) {
+    public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException {
         return stats.getFreeBytes(volume.getFsUuid());
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 60e10a1..ea28fe6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -32,6 +32,7 @@
 import android.util.SparseArray;
 import android.util.SparseLongArray;
 
+import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import java.util.List;
@@ -154,7 +155,7 @@
         try {
             details.totalSize = mStats.getTotalBytes(mVolume.fsUuid);
             details.availSize = mStats.getFreeBytes(mVolume.fsUuid);
-        } catch (IllegalStateException e) {
+        } catch (IOException e) {
             // The storage volume became null while we were measuring it.
             Log.w(TAG, e);
             return details;
@@ -169,8 +170,14 @@
                 final HashMap<String, Long> mediaMap = new HashMap<>();
                 details.mediaSize.put(user.id, mediaMap);
 
-                final ExternalStorageStats stats = mStats
-                        .queryExternalStatsForUser(mSharedVolume.fsUuid, UserHandle.of(user.id));
+                final ExternalStorageStats stats;
+                try {
+                    stats = mStats.queryExternalStatsForUser(mSharedVolume.fsUuid,
+                            UserHandle.of(user.id));
+                } catch (IOException e) {
+                    Log.w(TAG, e);
+                    continue;
+                }
 
                 addValue(details.usersSize, user.id, stats.getTotalBytes());
 
@@ -190,8 +197,13 @@
 
         if ((mVolume.getType() == VolumeInfo.TYPE_PRIVATE) && mVolume.isMountedReadable()) {
             for (UserInfo user : users) {
-                final StorageStats stats = mStats.queryStatsForUser(mVolume.fsUuid,
-                        UserHandle.of(user.id));
+                final StorageStats stats;
+                try {
+                    stats = mStats.queryStatsForUser(mVolume.fsUuid, UserHandle.of(user.id));
+                } catch (IOException e) {
+                    Log.w(TAG, e);
+                    continue;
+                }
 
                 // Only count code once against current user
                 if (user.id == UserHandle.myUserId()) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
index e5d85d1..4c45413 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
@@ -19,6 +19,7 @@
 import android.app.usage.StorageStatsManager;
 import android.os.storage.VolumeInfo;
 
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -46,12 +47,12 @@
      *
      * @pre The volume is a private volume and is readable.
      */
-    long getTotalBytes(StorageStatsManager stats, VolumeInfo volume);
+    long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException;
 
     /**
      * Returns the free bytes for a given storage volume.
      *
      * @pre The volume is a private volume and is readable.
      */
-    long getFreeBytes(StorageStatsManager stats, VolumeInfo volume);
+    long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException;
 }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d796098..452fe1d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3272,6 +3272,8 @@
         try {
             return mContext.getSystemService(StorageStatsManager.class)
                     .queryStatsForUid(volumeUuid, uid).getCacheBytes();
+        } catch (IOException e) {
+            throw new ParcelableException(e);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -3312,6 +3314,8 @@
                     return Math.max(0, path.getUsableSpace() - storage.getStorageLowBytes(path));
                 }
             }
+        } catch (IOException e) {
+            throw new ParcelableException(e);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -3329,13 +3333,13 @@
                     + " because only " + allocatableBytes + " allocatable"));
         }
 
-        // Free up enough disk space to satisfy both the requested allocation
-        // and our low disk warning space.
-        final File path = storage.findPathForUuid(volumeUuid);
-        bytes += storage.getStorageLowBytes(path);
-
         final long token = Binder.clearCallingIdentity();
         try {
+            // Free up enough disk space to satisfy both the requested allocation
+            // and our low disk warning space.
+            final File path = storage.findPathForUuid(volumeUuid);
+            bytes += storage.getStorageLowBytes(path);
+
             mPms.freeStorage(volumeUuid, bytes, flags);
         } catch (IOException e) {
             throw new ParcelableException(e);
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index a77d33f..03b754f 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -21,22 +21,21 @@
 import android.app.usage.StorageStatsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageStatsObserver;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageStats;
 import android.content.pm.UserInfo;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
 import android.os.UserManager;
 import android.os.storage.VolumeInfo;
 import android.util.Log;
+
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.Preconditions;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -44,7 +43,6 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * AppCollector asynchronously collects package sizes.
@@ -132,7 +130,7 @@
 
                             try {
                                 StorageStats storageStats =
-                                        mStorageStatsManager.queryStatsForPackage(app.volumeUuid,
+                                        mStorageStatsManager.queryStatsForPackage(app.storageUuid,
                                                 app.packageName, user.getUserHandle());
                                 PackageStats packageStats = new PackageStats(app.packageName,
                                         user.id);
@@ -140,7 +138,7 @@
                                 packageStats.codeSize = storageStats.getCodeBytes();
                                 packageStats.dataSize = storageStats.getDataBytes();
                                 stats.add(packageStats);
-                            } catch (IllegalStateException e) {
+                            } catch (NameNotFoundException | IOException e) {
                                 Log.e(TAG, "An exception occurred while fetching app size", e);
                             }
                         }
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 5ad7f80..094c7bd 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -35,6 +35,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelableException;
 import android.os.StatFs;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -150,7 +151,7 @@
         try {
             return mInstaller.isQuotaSupported(volumeUuid);
         } catch (InstallerException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(new IOException(e.getMessage()));
         }
     }
 
@@ -163,7 +164,8 @@
         } else {
             final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
             if (vol == null) {
-                throw new IllegalStateException("Volume was unexpected null");
+                throw new ParcelableException(
+                        new IOException("Failed to find storage device for UUID " + volumeUuid));
             }
             return FileUtils.roundStorageSize(vol.disk.size);
         }
@@ -189,7 +191,8 @@
         } else {
             final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
             if (vol == null) {
-                throw new IllegalStateException("Volume was unexpected null");
+                throw new ParcelableException(
+                        new IOException("Failed to find storage device for UUID " + volumeUuid));
             }
             return vol.getPath().getUsableSpace() + cacheBytes;
         }
@@ -221,7 +224,7 @@
             appInfo = mPackage.getApplicationInfoAsUser(packageName,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
         } catch (NameNotFoundException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(e);
         }
 
         if (mPackage.getPackagesForUid(appInfo.uid).length == 1) {
@@ -239,7 +242,7 @@
                 mInstaller.getAppSize(volumeUuid, packageNames, userId, 0,
                         appId, ceDataInodes, codePaths, stats);
             } catch (InstallerException e) {
-                throw new IllegalStateException(e);
+                throw new ParcelableException(new IOException(e.getMessage()));
             }
             return translate(stats);
         }
@@ -265,7 +268,7 @@
                 codePaths[i] = mPackage.getApplicationInfoAsUser(packageNames[i],
                         PackageManager.MATCH_UNINSTALLED_PACKAGES, userId).getCodePath();
             } catch (NameNotFoundException e) {
-                throw new IllegalStateException(e);
+                throw new ParcelableException(e);
             }
         }
 
@@ -281,7 +284,7 @@
                 checkEquals("UID " + uid, manualStats, stats);
             }
         } catch (InstallerException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(new IOException(e.getMessage()));
         }
         return translate(stats);
     }
@@ -313,7 +316,7 @@
                 checkEquals("User " + userId, manualStats, stats);
             }
         } catch (InstallerException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(new IOException(e.getMessage()));
         }
         return translate(stats);
     }
@@ -336,7 +339,7 @@
                 checkEquals("External " + userId, manualStats, stats);
             }
         } catch (InstallerException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(new IOException(e.getMessage()));
         }
 
         final ExternalStorageStats res = new ExternalStorageStats();