diff options
| -rw-r--r-- | api/current.txt | 14 | ||||
| -rw-r--r-- | api/removed.txt | 4 | ||||
| -rw-r--r-- | api/system-current.txt | 9 | ||||
| -rw-r--r-- | api/system-removed.txt | 4 | ||||
| -rw-r--r-- | api/test-current.txt | 14 | ||||
| -rw-r--r-- | api/test-removed.txt | 4 | ||||
| -rw-r--r-- | core/java/android/app/usage/ExternalStorageStats.java | 11 | ||||
| -rw-r--r-- | core/java/android/app/usage/StorageStats.java | 17 | ||||
| -rw-r--r-- | core/java/android/app/usage/StorageStatsManager.java | 106 | ||||
| -rw-r--r-- | core/java/android/content/pm/ApplicationInfo.java | 5 | ||||
| -rw-r--r-- | core/java/android/os/Bundle.java | 33 | ||||
| -rw-r--r-- | core/java/android/os/Parcel.java | 24 | ||||
| -rw-r--r-- | core/java/android/os/storage/StorageManager.java | 45 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 3 | ||||
| -rw-r--r-- | services/usage/java/com/android/server/usage/StorageStatsService.java | 36 |
15 files changed, 177 insertions, 152 deletions
diff --git a/api/current.txt b/api/current.txt index 58d617a00e7c..46b3abc6472a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15,7 +15,6 @@ package android { field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE"; field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER"; field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL"; - field public static final java.lang.String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE"; field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS"; field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS"; field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE"; @@ -6991,8 +6990,8 @@ package android.app.usage { public final class StorageStats implements android.os.Parcelable { method public int describeContents(); + method public long getAppBytes(); method public long getCacheBytes(); - method public long getCodeBytes(); method public long getDataBytes(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; @@ -30748,7 +30747,6 @@ package android.os { 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); @@ -30773,7 +30771,6 @@ package android.os { 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); @@ -31303,7 +31300,6 @@ package android.os { 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); @@ -31349,7 +31345,6 @@ package android.os { 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; } @@ -31980,9 +31975,9 @@ package android.os.storage { } public class StorageManager { - 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.util.UUID, int) throws java.io.IOException; + method public void allocateBytes(java.util.UUID, long) throws java.io.IOException; + method public void allocateBytes(java.io.FileDescriptor, long) throws java.io.IOException; + method public long getAllocatableBytes(java.util.UUID) 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); @@ -32003,7 +31998,6 @@ package android.os.storage { 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; } diff --git a/api/removed.txt b/api/removed.txt index c132385f1631..ee2e84e44b93 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -23,6 +23,10 @@ package android.app.admin { package android.app.usage { + public final class StorageStats implements android.os.Parcelable { + method public deprecated long getCodeBytes(); + } + 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; diff --git a/api/system-current.txt b/api/system-current.txt index 3723e7ea286a..5fc51f821683 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7457,8 +7457,8 @@ package android.app.usage { public final class StorageStats implements android.os.Parcelable { method public int describeContents(); + method public long getAppBytes(); method public long getCacheBytes(); - method public long getCodeBytes(); method public long getDataBytes(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; @@ -33508,7 +33508,6 @@ package android.os { 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); @@ -33533,7 +33532,6 @@ package android.os { 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); @@ -34095,7 +34093,6 @@ package android.os { 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); @@ -34141,7 +34138,6 @@ package android.os { 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; } @@ -34878,8 +34874,11 @@ package android.os.storage { } public class StorageManager { + method public void allocateBytes(java.util.UUID, long) 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) throws java.io.IOException; method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException; + method public long getAllocatableBytes(java.util.UUID) throws java.io.IOException; 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; diff --git a/api/system-removed.txt b/api/system-removed.txt index 039cd74e982d..89bc6bd095a6 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -21,6 +21,10 @@ package android.app.admin { package android.app.usage { + public final class StorageStats implements android.os.Parcelable { + method public deprecated long getCodeBytes(); + } + 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; diff --git a/api/test-current.txt b/api/test-current.txt index 9f7441c9124e..0f40c78d5648 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -15,7 +15,6 @@ package android { field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE"; field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER"; field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL"; - field public static final java.lang.String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE"; field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS"; field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS"; field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE"; @@ -7021,8 +7020,8 @@ package android.app.usage { public final class StorageStats implements android.os.Parcelable { method public int describeContents(); + method public long getAppBytes(); method public long getCacheBytes(); - method public long getCodeBytes(); method public long getDataBytes(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; @@ -30856,7 +30855,6 @@ package android.os { 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); @@ -30881,7 +30879,6 @@ package android.os { 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); @@ -31432,7 +31429,6 @@ package android.os { 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); @@ -31478,7 +31474,6 @@ package android.os { 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; } @@ -32113,9 +32108,9 @@ package android.os.storage { } public class StorageManager { - 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.util.UUID, int) throws java.io.IOException; + method public void allocateBytes(java.util.UUID, long) throws java.io.IOException; + method public void allocateBytes(java.io.FileDescriptor, long) throws java.io.IOException; + method public long getAllocatableBytes(java.util.UUID) 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); @@ -32136,7 +32131,6 @@ package android.os.storage { 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; } diff --git a/api/test-removed.txt b/api/test-removed.txt index c132385f1631..ee2e84e44b93 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -23,6 +23,10 @@ package android.app.admin { package android.app.usage { + public final class StorageStats implements android.os.Parcelable { + method public deprecated long getCodeBytes(); + } + 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; diff --git a/core/java/android/app/usage/ExternalStorageStats.java b/core/java/android/app/usage/ExternalStorageStats.java index 10c9b5ff5a50..83ac779ee7db 100644 --- a/core/java/android/app/usage/ExternalStorageStats.java +++ b/core/java/android/app/usage/ExternalStorageStats.java @@ -16,6 +16,7 @@ package android.app.usage; +import android.annotation.BytesLong; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; @@ -37,7 +38,7 @@ public final class ExternalStorageStats implements Parcelable { * Return the total bytes used by all files in the shared/external storage * hosted on this volume. */ - public long getTotalBytes() { + public @BytesLong long getTotalBytes() { return totalBytes; } @@ -45,7 +46,7 @@ public final class ExternalStorageStats implements Parcelable { * Return the total bytes used by audio files in the shared/external storage * hosted on this volume. */ - public long getAudioBytes() { + public @BytesLong long getAudioBytes() { return audioBytes; } @@ -53,7 +54,7 @@ public final class ExternalStorageStats implements Parcelable { * Return the total bytes used by video files in the shared/external storage * hosted on this volume. */ - public long getVideoBytes() { + public @BytesLong long getVideoBytes() { return videoBytes; } @@ -61,7 +62,7 @@ public final class ExternalStorageStats implements Parcelable { * Return the total bytes used by image files in the shared/external storage * hosted on this volume. */ - public long getImageBytes() { + public @BytesLong long getImageBytes() { return imageBytes; } @@ -72,7 +73,7 @@ public final class ExternalStorageStats implements Parcelable { * This data is already accounted against individual apps as returned * through {@link StorageStats}. */ - public long getAppBytes() { + public @BytesLong long getAppBytes() { return appBytes; } diff --git a/core/java/android/app/usage/StorageStats.java b/core/java/android/app/usage/StorageStats.java index 26c702c0eb4e..3a277518977d 100644 --- a/core/java/android/app/usage/StorageStats.java +++ b/core/java/android/app/usage/StorageStats.java @@ -16,6 +16,7 @@ package android.app.usage; +import android.annotation.BytesLong; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; @@ -33,18 +34,24 @@ public final class StorageStats implements Parcelable { /** {@hide} */ public long cacheBytes; /** - * Return the size of all code. This includes {@code APK} files and - * optimized compiler output. + * Return the size of app. This includes {@code APK} files, optimized + * compiler output, and unpacked native libraries. * <p> * If the primary external/shared storage is hosted on this storage device, * then this includes files stored under {@link Context#getObbDir()}. * <p> * Code is shared between all users on a multiuser device. */ - public long getCodeBytes() { + public @BytesLong long getAppBytes() { return codeBytes; } + /** @removed */ + @Deprecated + public long getCodeBytes() { + return getAppBytes(); + } + /** * Return the size of all data. This includes files stored under * {@link Context#getDataDir()}, {@link Context#getCacheDir()}, @@ -58,7 +65,7 @@ public final class StorageStats implements Parcelable { * <p> * Data is isolated for each user on a multiuser device. */ - public long getDataBytes() { + public @BytesLong long getDataBytes() { return dataBytes; } @@ -72,7 +79,7 @@ public final class StorageStats implements Parcelable { * <p> * Cached data is isolated for each user on a multiuser device. */ - public long getCacheBytes() { + public @BytesLong long getCacheBytes() { return cacheBytes; } diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java index 5497d57ba264..d9d958c0653c 100644 --- a/core/java/android/app/usage/StorageStatsManager.java +++ b/core/java/android/app/usage/StorageStatsManager.java @@ -18,6 +18,7 @@ package android.app.usage; import static android.os.storage.StorageManager.convert; +import android.annotation.BytesLong; import android.annotation.NonNull; import android.annotation.TestApi; import android.annotation.WorkerThread; @@ -37,13 +38,16 @@ import java.io.IOException; import java.util.UUID; /** - * Provides access to detailed storage statistics. + * Access to detailed storage statistics. This provides a summary of how apps, + * users, and external/shared storage is utilizing disk space. * <p class="note"> - * Note: this API requires the permission - * {@code android.permission.PACKAGE_USAGE_STATS}, which is a system-level - * permission that will not be granted to normal apps. However, declaring the - * permission expresses your intention to use this API and an end user can then - * choose to grant this permission through the Settings application. + * Note: no permissions are required when calling these APIs for your own + * package or UID. However, requesting details for any other package requires + * the {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an end + * user can then choose to grant this permission through the Settings + * application. * </p> */ public class StorageStatsManager { @@ -73,19 +77,22 @@ public class StorageStatsManager { } /** - * Return the total size of the underlying media that is hosting this - * storage volume. + * Return the total size of the underlying physical media that is hosting + * this storage volume. * <p> - * To reduce end user confusion, this value matches the total storage size - * advertised in a retail environment, which is typically larger than the - * actual usable partition space. + * This value is best suited for visual display to end users, since it's + * designed to reflect the total storage size advertised in a retail + * environment. + * <p> + * Apps making logical decisions about disk space should always use + * {@link File#getTotalSpace()} instead of this value. * * @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(@NonNull UUID storageUuid) throws IOException { + public @BytesLong long getTotalBytes(@NonNull UUID storageUuid) throws IOException { try { return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName()); } catch (ParcelableException e) { @@ -105,19 +112,20 @@ public class StorageStatsManager { /** * Return the free space on the requested storage volume. * <p> - * The free space is equivalent to {@link File#getUsableSpace()} plus the - * size of any cached data that can be automatically deleted by the system - * as additional space is needed. + * This value is best suited for visual display to end users, since it's + * designed to reflect both unused space <em>and</em> and cached space that + * could be reclaimed by the system. * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * Apps making logical decisions about disk space should always use + * {@link StorageManager#getAllocatableBytes(UUID, int)} instead of this + * value. * * @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(@NonNull UUID storageUuid) throws IOException { + public @BytesLong long getFreeBytes(@NonNull UUID storageUuid) throws IOException { try { return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName()); } catch (ParcelableException e) { @@ -137,9 +145,15 @@ public class StorageStatsManager { /** * Return storage statistics for a specific package on the requested storage * volume. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * <p class="note"> + * Note: no permissions are required when calling this API for your own + * package. However, requesting details for any other package requires the + * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an + * end user can then choose to grant this permission through the Settings + * application. + * </p> * <p class="note"> * Note: if the requested package uses the {@code android:sharedUserId} * manifest feature, this call will be forced into a slower manual @@ -158,8 +172,9 @@ public class StorageStatsManager { * @see PackageInfo#packageName */ @WorkerThread - public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, String packageName, - UserHandle user) throws PackageManager.NameNotFoundException, IOException { + public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, + @NonNull String packageName, @NonNull UserHandle user) + throws PackageManager.NameNotFoundException, IOException { try { return mService.queryStatsForPackage(convert(storageUuid), packageName, user.getIdentifier(), mContext.getOpPackageName()); @@ -182,9 +197,15 @@ public class StorageStatsManager { /** * Return storage statistics for a specific UID on the requested storage * volume. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * <p class="note"> + * Note: no permissions are required when calling this API for your own UID. + * However, requesting details for any other UID requires the + * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an + * end user can then choose to grant this permission through the Settings + * application. + * </p> * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. @@ -194,7 +215,8 @@ public class StorageStatsManager { * @see ApplicationInfo#uid */ @WorkerThread - public StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) throws IOException { + public @NonNull StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) + throws IOException { try { return mService.queryStatsForUid(convert(storageUuid), uid, mContext.getOpPackageName()); @@ -215,9 +237,14 @@ public class StorageStatsManager { /** * Return storage statistics for a specific {@link UserHandle} on the * requested storage volume. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * <p class="note"> + * Note: this API requires the + * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an + * end user can then choose to grant this permission through the Settings + * application. + * </p> * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. @@ -226,8 +253,8 @@ public class StorageStatsManager { * @see android.os.Process#myUserHandle() */ @WorkerThread - public StorageStats queryStatsForUser(@NonNull UUID storageUuid, UserHandle user) - throws IOException { + public @NonNull StorageStats queryStatsForUser(@NonNull UUID storageUuid, + @NonNull UserHandle user) throws IOException { try { return mService.queryStatsForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); @@ -248,9 +275,14 @@ public class StorageStatsManager { /** * Return shared/external storage statistics for a specific * {@link UserHandle} on the requested storage volume. - * <p> - * This method may take several seconds to calculate the requested values, - * so it should only be called from a worker thread. + * <p class="note"> + * Note: this API requires the + * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which + * is a system-level permission that will not be granted to normal apps. + * Declaring that permission expresses your intention to use this API and an + * end user can then choose to grant this permission through the Settings + * application. + * </p> * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. @@ -258,8 +290,8 @@ public class StorageStatsManager { * @see android.os.Process#myUserHandle() */ @WorkerThread - public ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid, - UserHandle user) throws IOException { + public @NonNull ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid, + @NonNull UserHandle user) throws IOException { try { return mService.queryExternalStatsForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 6c5d26a9706f..06f7916be4b6 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1205,7 +1205,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeInt(largestWidthLimitDp); if (storageUuid != null) { dest.writeInt(1); - dest.writeUuid(storageUuid); + dest.writeLong(storageUuid.getMostSignificantBits()); + dest.writeLong(storageUuid.getLeastSignificantBits()); } else { dest.writeInt(0); } @@ -1271,7 +1272,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { compatibleWidthLimitDp = source.readInt(); largestWidthLimitDp = source.readInt(); if (source.readInt() != 0) { - storageUuid = source.readUuid(); + storageUuid = new UUID(source.readLong(), source.readLong()); volumeUuid = StorageManager.convert(storageUuid); } scanSourceDir = source.readString(); diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index 167c46d6ded0..9b5ff29d592e 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -25,7 +25,6 @@ import android.util.SparseArray; 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. @@ -477,18 +476,6 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { } /** - * 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. @@ -871,26 +858,6 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { * 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 c1647c74f363..28bdacfaea9c 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -50,7 +50,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.UUID; /** * Container for a message (data and object references) that can @@ -242,7 +241,6 @@ public final class Parcel { 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,15 +829,6 @@ public final class Parcel { } /** - * 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. @@ -1687,9 +1676,6 @@ public final class Parcel { } 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) { @@ -2194,13 +2180,6 @@ public final class Parcel { } /** - * 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() { @@ -2750,9 +2729,6 @@ public final class Parcel { 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 baa29b078dd8..4b4cabf7a5d5 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -19,14 +19,18 @@ package android.os.storage; import static android.net.TrafficStats.GB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; +import android.annotation.BytesLong; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; +import android.annotation.SystemApi; +import android.annotation.WorkerThread; import android.app.ActivityThread; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; @@ -135,6 +139,7 @@ public class StorageManager { * thus it cannot be used to uniquely identify a particular physical device. * * @see #getUuidForPath(File) + * @see ApplicationInfo#storageUuid */ public static final UUID UUID_DEFAULT = UUID .fromString("41217664-9172-527a-b3d5-edabb50a7d69"); @@ -166,6 +171,7 @@ public class StorageManager { * @see #ACTION_MANAGE_STORAGE * @see #UUID_DEFAULT * @see #getUuidForPath(File) + * @see Intent#putExtra(String, java.io.Serializable) */ public static final String EXTRA_UUID = "android.os.storage.extra.UUID"; @@ -1533,7 +1539,8 @@ public class StorageManager { * doesn't support cache quotas. * @see #getCacheSizeBytes(UUID) */ - public long getCacheQuotaBytes(@NonNull UUID storageUuid) throws IOException { + @WorkerThread + public @BytesLong long getCacheQuotaBytes(@NonNull UUID storageUuid) throws IOException { try { final ApplicationInfo app = mContext.getApplicationInfo(); return mStorageManager.getCacheQuotaBytes(convert(storageUuid), app.uid); @@ -1573,7 +1580,8 @@ public class StorageManager { * doesn't support cache quotas. * @see #getCacheQuotaBytes(UUID) */ - public long getCacheSizeBytes(@NonNull UUID storageUuid) throws IOException { + @WorkerThread + public @BytesLong long getCacheSizeBytes(@NonNull UUID storageUuid) throws IOException { try { final ApplicationInfo app = mContext.getApplicationInfo(); return mStorageManager.getCacheSizeBytes(convert(storageUuid), app.uid); @@ -1631,8 +1639,10 @@ public class StorageManager { * @see #getAllocatableBytes(UUID, int) * @see #allocateBytes(UUID, long, int) * @see #allocateBytes(FileDescriptor, long, int) + * @hide */ @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) + @SystemApi public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; /** @hide */ @@ -1656,7 +1666,7 @@ public class StorageManager { * 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 + * persist, 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"> @@ -1670,13 +1680,19 @@ public class StorageManager { * 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(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 @BytesLong long getAllocatableBytes(@NonNull UUID storageUuid) + throws IOException { + return getAllocatableBytes(storageUuid, 0); + } + + /** @hide */ + @SystemApi public long getAllocatableBytes(@NonNull UUID storageUuid, @AllocateFlags int flags) throws IOException { try { @@ -1713,14 +1729,20 @@ public class StorageManager { * 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. * @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(@NonNull UUID storageUuid, long bytes, @AllocateFlags int flags) + public void allocateBytes(@NonNull UUID storageUuid, @BytesLong long bytes) throws IOException { + allocateBytes(storageUuid, bytes, 0); + } + + /** @hide */ + @SystemApi + public void allocateBytes(@NonNull UUID storageUuid, @BytesLong long bytes, + @AllocateFlags int flags) throws IOException { try { mStorageManager.allocateBytes(convert(storageUuid), bytes, flags); } catch (ParcelableException e) { @@ -1732,7 +1754,7 @@ public class StorageManager { /** @removed */ @Deprecated - public void allocateBytes(@NonNull File path, long bytes, @AllocateFlags int flags) + public void allocateBytes(@NonNull File path, @BytesLong long bytes, @AllocateFlags int flags) throws IOException { allocateBytes(getUuidForPath(path), bytes, flags); } @@ -1756,14 +1778,19 @@ public class StorageManager { * 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. * @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) + public void allocateBytes(FileDescriptor fd, @BytesLong long bytes) throws IOException { + allocateBytes(fd, bytes, 0); + } + + /** @hide */ + @SystemApi + public void allocateBytes(FileDescriptor fd, @BytesLong long bytes, @AllocateFlags int flags) throws IOException { final File file = ParcelFileDescriptor.getFile(fd); for (int i = 0; i < 3; i++) { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 313130221ff6..7c7daf74d0d1 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1697,7 +1697,8 @@ <permission android:name="android.permission.CACHE_CONTENT" android:protectionLevel="signature" /> - <!-- Allows an application to aggressively allocate disk space. + <!-- @SystemApi @hide + Allows an application to aggressively allocate disk space. <p>Not for use by third-party applications. --> <permission android:name="android.permission.ALLOCATE_AGGRESSIVE" diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java index 2ebf5fc1c533..e13665bed275 100644 --- a/services/usage/java/com/android/server/usage/StorageStatsService.java +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -157,7 +157,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public long getTotalBytes(String volumeUuid, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); + // NOTE: No permissions required if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) { return FileUtils.roundStorageSize(mStorage.getPrimaryStorageSize()); @@ -173,7 +173,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public long getFreeBytes(String volumeUuid, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); + // NOTE: No permissions required long cacheBytes = 0; final long token = Binder.clearCallingIdentity(); @@ -187,14 +187,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub { } if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) { - return Environment.getDataDirectory().getUsableSpace() + cacheBytes; + return Environment.getDataDirectory().getFreeSpace() + cacheBytes; } else { final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid); if (vol == null) { throw new ParcelableException( new IOException("Failed to find storage device for UUID " + volumeUuid)); } - return vol.getPath().getUsableSpace() + cacheBytes; + return vol.getPath().getFreeSpace() + cacheBytes; } } @@ -213,7 +213,6 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public StorageStats queryStatsForPackage(String volumeUuid, String packageName, int userId, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); @@ -227,6 +226,12 @@ public class StorageStatsService extends IStorageStatsManager.Stub { throw new ParcelableException(e); } + if (Binder.getCallingUid() == appInfo.uid) { + // No permissions required when asking about themselves + } else { + enforcePermission(Binder.getCallingUid(), callingPackage); + } + if (mPackage.getPackagesForUid(appInfo.uid).length == 1) { // Only one package inside UID means we can fast-path return queryStatsForUid(volumeUuid, appInfo.uid, callingPackage); @@ -257,14 +262,19 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); - if (UserHandle.getUserId(uid) != UserHandle.getCallingUserId()) { + final int userId = UserHandle.getUserId(uid); + final int appId = UserHandle.getAppId(uid); + + if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); } - final int userId = UserHandle.getUserId(uid); - final int appId = UserHandle.getAppId(uid); + if (Binder.getCallingUid() == uid) { + // No permissions required when asking about themselves + } else { + enforcePermission(Binder.getCallingUid(), callingPackage); + } final String[] packageNames = mPackage.getPackagesForUid(uid); final long[] ceDataInodes = new long[packageNames.length]; @@ -304,12 +314,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public StorageStats queryStatsForUser(String volumeUuid, int userId, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); } + // Always require permission to see user-level stats + enforcePermission(Binder.getCallingUid(), callingPackage); + final int[] appIds = getAppIds(userId); final PackageStats stats = new PackageStats(TAG); try { @@ -329,12 +341,14 @@ public class StorageStatsService extends IStorageStatsManager.Stub { @Override public ExternalStorageStats queryExternalStatsForUser(String volumeUuid, int userId, String callingPackage) { - enforcePermission(Binder.getCallingUid(), callingPackage); if (userId != UserHandle.getCallingUserId()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, TAG); } + // Always require permission to see user-level stats + enforcePermission(Binder.getCallingUid(), callingPackage); + final int[] appIds = getAppIds(userId); final long[] stats; try { |