summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Sharkey <jsharkey@android.com> 2017-04-27 11:21:41 -0600
committer Jeff Sharkey <jsharkey@android.com> 2017-04-27 11:33:39 -0600
commita4d34d971c9566a162a53e6b027ba2bc341ae5b4 (patch)
tree69112edf49564387b09dadb878e6f01edcfbb9aa
parentdd91a5636bec399be1f9e6af298bc667e0c25b09 (diff)
Respond to API council feedback.
Move aggressive allocation to @SystemApi, which means we can hide the "flags" API variants. Remove UUID APIs, since we should use existing Serializable APIs. Relax permission checks to allow apps to ask for their own stats. Improve docs. Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.StorageHostTest Bug: 37534687, 37534941, 37718184, 37738770 Change-Id: I6a763fb3ab3169c8d3329765bb31e1ee08d9ced7
-rw-r--r--api/current.txt14
-rw-r--r--api/removed.txt4
-rw-r--r--api/system-current.txt9
-rw-r--r--api/system-removed.txt4
-rw-r--r--api/test-current.txt14
-rw-r--r--api/test-removed.txt4
-rw-r--r--core/java/android/app/usage/ExternalStorageStats.java11
-rw-r--r--core/java/android/app/usage/StorageStats.java17
-rw-r--r--core/java/android/app/usage/StorageStatsManager.java106
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java5
-rw-r--r--core/java/android/os/Bundle.java33
-rw-r--r--core/java/android/os/Parcel.java24
-rw-r--r--core/java/android/os/storage/StorageManager.java45
-rw-r--r--core/res/AndroidManifest.xml3
-rw-r--r--services/usage/java/com/android/server/usage/StorageStatsService.java36
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 {