Merge "Initial implementation of StorageManager.getVolumesList()." into nyc-dev

am: 3c3770d8fe

* commit '3c3770d8fe9f64fc92de02f3e52901748e1f30de':
  Initial implementation of StorageManager.getVolumesList().
This commit is contained in:
Felipe Leme
2016-02-17 23:47:27 +00:00
committed by android-build-merger
11 changed files with 220 additions and 19 deletions

View File

@@ -8534,7 +8534,6 @@ package android.content {
field public static final java.lang.String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
field public static final java.lang.String ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
field public static final java.lang.String ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";
field public static final java.lang.String ACTION_OPEN_EXTERNAL_DIRECTORY = "android.intent.action.OPEN_EXTERNAL_DIRECTORY";
field public static final java.lang.String ACTION_PACKAGES_SUSPENDED = "android.intent.action.PACKAGES_SUSPENDED";
field public static final java.lang.String ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED";
field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
@@ -29365,11 +29364,27 @@ package android.os.storage {
public class StorageManager {
method public java.lang.String getMountedObbPath(java.lang.String);
method public android.os.storage.StorageVolume getPrimaryVolume();
method public android.os.storage.StorageVolume[] getVolumeList();
method public boolean isObbMounted(java.lang.String);
method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
}
public class StorageVolume implements android.os.Parcelable {
method public android.content.Intent createAccessIntent(java.lang.String);
method public int describeContents();
method public java.lang.String getDescription(android.content.Context);
method public java.lang.String getState();
method public java.lang.String getUuid();
method public boolean isEmulated();
method public boolean isPrimary();
method public boolean isRemovable();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.os.storage.StorageVolume> CREATOR;
field public static final java.lang.String EXTRA_STORAGE_VOLUME = "android.os.storage.extra.STORAGE_VOLUME";
}
}
package android.preference {

View File

@@ -15,6 +15,14 @@ package android.app.admin {
}
package android.content {
public class Intent implements java.lang.Cloneable android.os.Parcelable {
field public static final java.lang.String ACTION_OPEN_EXTERNAL_DIRECTORY = "android.intent.action.OPEN_EXTERNAL_DIRECTORY";
}
}
package android.content.pm {
public class PackageInfo implements android.os.Parcelable {

View File

@@ -8840,7 +8840,6 @@ package android.content {
field public static final java.lang.String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
field public static final java.lang.String ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
field public static final java.lang.String ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";
field public static final java.lang.String ACTION_OPEN_EXTERNAL_DIRECTORY = "android.intent.action.OPEN_EXTERNAL_DIRECTORY";
field public static final java.lang.String ACTION_PACKAGES_SUSPENDED = "android.intent.action.PACKAGES_SUSPENDED";
field public static final java.lang.String ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED";
field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
@@ -31719,11 +31718,27 @@ package android.os.storage {
public class StorageManager {
method public java.lang.String getMountedObbPath(java.lang.String);
method public android.os.storage.StorageVolume getPrimaryVolume();
method public android.os.storage.StorageVolume[] getVolumeList();
method public boolean isObbMounted(java.lang.String);
method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
}
public class StorageVolume implements android.os.Parcelable {
method public android.content.Intent createAccessIntent(java.lang.String);
method public int describeContents();
method public java.lang.String getDescription(android.content.Context);
method public java.lang.String getState();
method public java.lang.String getUuid();
method public boolean isEmulated();
method public boolean isPrimary();
method public boolean isRemovable();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.os.storage.StorageVolume> CREATOR;
field public static final java.lang.String EXTRA_STORAGE_VOLUME = "android.os.storage.extra.STORAGE_VOLUME";
}
}
package android.preference {

View File

@@ -6,6 +6,14 @@ package android.app {
}
package android.content {
public class Intent implements java.lang.Cloneable android.os.Parcelable {
field public static final java.lang.String ACTION_OPEN_EXTERNAL_DIRECTORY = "android.intent.action.OPEN_EXTERNAL_DIRECTORY";
}
}
package android.content.pm {
public class PackageInfo implements android.os.Parcelable {

View File

@@ -8539,7 +8539,6 @@ package android.content {
field public static final java.lang.String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
field public static final java.lang.String ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
field public static final java.lang.String ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";
field public static final java.lang.String ACTION_OPEN_EXTERNAL_DIRECTORY = "android.intent.action.OPEN_EXTERNAL_DIRECTORY";
field public static final java.lang.String ACTION_PACKAGES_SUSPENDED = "android.intent.action.PACKAGES_SUSPENDED";
field public static final java.lang.String ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED";
field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
@@ -29375,11 +29374,27 @@ package android.os.storage {
public class StorageManager {
method public java.lang.String getMountedObbPath(java.lang.String);
method public android.os.storage.StorageVolume getPrimaryVolume();
method public android.os.storage.StorageVolume[] getVolumeList();
method public boolean isObbMounted(java.lang.String);
method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
}
public class StorageVolume implements android.os.Parcelable {
method public android.content.Intent createAccessIntent(java.lang.String);
method public int describeContents();
method public java.lang.String getDescription(android.content.Context);
method public java.lang.String getState();
method public java.lang.String getUuid();
method public boolean isEmulated();
method public boolean isPrimary();
method public boolean isRemovable();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.os.storage.StorageVolume> CREATOR;
field public static final java.lang.String EXTRA_STORAGE_VOLUME = "android.os.storage.extra.STORAGE_VOLUME";
}
}
package android.preference {

View File

@@ -15,6 +15,14 @@ package android.app.admin {
}
package android.content {
public class Intent implements java.lang.Cloneable android.os.Parcelable {
field public static final java.lang.String ACTION_OPEN_EXTERNAL_DIRECTORY = "android.intent.action.OPEN_EXTERNAL_DIRECTORY";
}
}
package android.content.pm {
public class PackageInfo implements android.os.Parcelable {

View File

@@ -3213,6 +3213,12 @@ public class Intent implements Parcelable, Cloneable {
* Output: The URI representing the requested directory tree.
*
* @see DocumentsContract
*
* {@removed}
*
* Will be removed / hidden before N is published; apps should use
* {@link android.os.storage.StorageManager#getVolumeList()} and
* {@link android.os.storage.StorageVolume#createAccessIntent(String)} instead.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String

View File

@@ -339,7 +339,7 @@ public class Environment {
* <p>
* Writing to this path requires the
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission,
* and starting in read access requires the
* and starting in {@link android.os.Build.VERSION_CODES#KITKAT}, read access requires the
* {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission,
* which is automatically granted if you hold the write permission.
* <p>

View File

@@ -865,7 +865,12 @@ public class StorageManager {
}
}
/** {@hide} */
/**
* Gets the list of shared/external storage volumes available to the current user.
*
* <p>It always contains the primary storage volume, plus any additional external volume(s)
* available in the device, such as SD cards or attached USB drives.
*/
public @NonNull StorageVolume[] getVolumeList() {
return getVolumeList(mContext.getUserId(), 0);
}
@@ -914,7 +919,9 @@ public class StorageManager {
return paths;
}
/** {@hide} */
/**
* Gets the primary shared/external storage volume available to the current user.
*/
public @NonNull StorageVolume getPrimaryVolume() {
return getPrimaryVolume(getVolumeList());
}

View File

@@ -16,11 +16,17 @@
package android.os.storage;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.net.TrafficStats;
import android.net.Uri;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.provider.DocumentsContract;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -29,14 +35,46 @@ import java.io.CharArrayWriter;
import java.io.File;
/**
* Information about a storage volume that may be mounted. This is a legacy
* specialization of {@link VolumeInfo} which describes the volume for a
* specific user.
* <p>
* This class may be deprecated in the future.
* Information about a shared/external storage volume for a specific user.
*
* @hide
* <p>
* A device always has one (and one only) primary storage volume, but it could have extra volumes,
* like SD cards and USB drives. This object represents the logical view of a storage
* volume for a specific user: different users might have different views for the same physical
* volume (for example, if the volume is a built-in emulated storage).
*
* <p>
* The storage volume is not necessarily mounted, applications should use {@link #getState()} to
* verify its state.
*
* <p>
* Applications willing to read or write to this storage volume needs to get a permission from the
* user first, which can be achieved in the following ways:
*
* <ul>
* <li>To get access to standard directories (like the {@link Environment#DIRECTORY_PICTURES}), they
* can use the {@link #createAccessIntent(String)}. This is the recommend way, since it provides a
* simpler API and narrows the access to the given directory (and its descendants).
* <li>To get access to any directory (and its descendants), they can use the Storage Area Framework
* APIs (such as {@link Intent#ACTION_OPEN_DOCUMENT} and {@link Intent#ACTION_OPEN_DOCUMENT_TREE},
* although these APIs do not guarantee the user will select this specific volume.
* <li>To get read and write access to the primary storage volume, applications can declare the
* {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} and
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permissions respectively, with the
* latter including the former. This approach is discouraged, since users may be hesitant to grant
* broad access to all files contained on a storage device.
* </ul>
*
* <p>It can be obtained through {@link StorageManager#getVolumeList()} and
* {@link StorageManager#getPrimaryVolume()} and also as an extra in some broadcasts
* (see {@link #EXTRA_STORAGE_VOLUME}).
*
* <p>
* See {@link Environment#getExternalStorageDirectory()} for more info about shared/external
* storage semantics.
*/
// NOTE: This is a legacy specialization of VolumeInfo which describes the volume for a specific
// user, but is now part of the public API.
public class StorageVolume implements Parcelable {
private final String mId;
@@ -53,14 +91,23 @@ public class StorageVolume implements Parcelable {
private final String mFsUuid;
private final String mState;
// StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
// ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
// ACTION_MEDIA_BAD_REMOVAL, ACTION_MEDIA_UNMOUNTABLE and ACTION_MEDIA_EJECT broadcasts.
public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
/**
* Name of the {@link Parcelable} extra in the {@link Intent#ACTION_MEDIA_REMOVED},
* {@link Intent#ACTION_MEDIA_UNMOUNTED}, {@link Intent#ACTION_MEDIA_CHECKING},
* {@link Intent#ACTION_MEDIA_NOFS}, {@link Intent#ACTION_MEDIA_MOUNTED},
* {@link Intent#ACTION_MEDIA_SHARED}, {@link Intent#ACTION_MEDIA_BAD_REMOVAL},
* {@link Intent#ACTION_MEDIA_UNMOUNTABLE}, and {@link Intent#ACTION_MEDIA_EJECT} broadcast that
* contains a {@link StorageVolume}.
*/
// Also sent on ACTION_MEDIA_UNSHARED, which is @hide
public static final String EXTRA_STORAGE_VOLUME = "android.os.storage.extra.STORAGE_VOLUME";
/** {@hide} */
public static final int STORAGE_ID_INVALID = 0x00000000;
/** {@hide} */
public static final int STORAGE_ID_PRIMARY = 0x00010001;
/** {@hide} */
public StorageVolume(String id, int storageId, File path, String description, boolean primary,
boolean removable, boolean emulated, long mtpReserveSize, boolean allowMassStorage,
long maxFileSize, UserHandle owner, String fsUuid, String state) {
@@ -95,6 +142,7 @@ public class StorageVolume implements Parcelable {
mState = in.readString();
}
/** {@hide} */
public String getId() {
return mId;
}
@@ -103,17 +151,19 @@ public class StorageVolume implements Parcelable {
* Returns the mount path for the volume.
*
* @return the mount path
* @hide
*/
public String getPath() {
return mPath.toString();
}
/** {@hide} */
public File getPathFile() {
return mPath;
}
/**
* Returns a user visible description of the volume.
* Returns a user-visible description of the volume.
*
* @return the volume description
*/
@@ -121,6 +171,10 @@ public class StorageVolume implements Parcelable {
return mDescription;
}
/**
* Returns true if the volume is the primary shared/external storage, which is the volume
* backed by {@link Environment#getExternalStorageDirectory()}.
*/
public boolean isPrimary() {
return mPrimary;
}
@@ -148,6 +202,7 @@ public class StorageVolume implements Parcelable {
* this is also used for the storage_id column in the media provider.
*
* @return MTP storage ID
* @hide
*/
public int getStorageId() {
return mStorageId;
@@ -164,6 +219,7 @@ public class StorageVolume implements Parcelable {
* too close to full.
*
* @return MTP reserve space
* @hide
*/
public int getMtpReserveSpace() {
return (int) (mMtpReserveSize / TrafficStats.MB_IN_BYTES);
@@ -173,6 +229,7 @@ public class StorageVolume implements Parcelable {
* Returns true if this volume can be shared via USB mass storage.
*
* @return whether mass storage is allowed
* @hide
*/
public boolean allowMassStorage() {
return mAllowMassStorage;
@@ -182,22 +239,28 @@ public class StorageVolume implements Parcelable {
* Returns maximum file size for the volume, or zero if it is unbounded.
*
* @return maximum file size
* @hide
*/
public long getMaxFileSize() {
return mMaxFileSize;
}
/** {@hide} */
public UserHandle getOwner() {
return mOwner;
}
public String getUuid() {
/**
* Gets the volume UUID, if any.
*/
public @Nullable String getUuid() {
return mFsUuid;
}
/**
* Parse and return volume UUID as FAT volume ID, or return -1 if unable to
* parse or UUID is unknown.
* @hide
*/
public int getFatVolumeId() {
if (mFsUuid == null || mFsUuid.length() != 9) {
@@ -210,14 +273,56 @@ public class StorageVolume implements Parcelable {
}
}
/** {@hide} */
public String getUserLabel() {
return mDescription;
}
/**
* Returns the current state of the volume.
*
* @return one of {@link Environment#MEDIA_UNKNOWN}, {@link Environment#MEDIA_REMOVED},
* {@link Environment#MEDIA_UNMOUNTED}, {@link Environment#MEDIA_CHECKING},
* {@link Environment#MEDIA_NOFS}, {@link Environment#MEDIA_MOUNTED},
* {@link Environment#MEDIA_MOUNTED_READ_ONLY}, {@link Environment#MEDIA_SHARED},
* {@link Environment#MEDIA_BAD_REMOVAL}, or {@link Environment#MEDIA_UNMOUNTABLE}.
*/
public String getState() {
return mState;
}
/**
* Builds an intent to give access to a standard storage directory after obtaining the user's
* approval.
* <p>
* When invoked, the system will ask the user to grant access to the requested directory (and
* its descendants). The result of the request will be returned to the activity through the
* {@code onActivityResult} method.
* <p>
* To gain access to descendants (child, grandchild, etc) documents, use
* {@link DocumentsContract#buildDocumentUriUsingTree(Uri, String)}, or
* {@link DocumentsContract#buildChildDocumentsUriUsingTree(Uri, String)} with the returned URI.
*
* <b>If your application only needs to store internal data, consider using
* {@link Context#getExternalFilesDirs(String) Context.getExternalFilesDirs},
* {@link Context#getExternalCacheDirs()}, or
* {@link Context#getExternalMediaDirs()}, which require no permissions to read or write.
*
* @param directoryName must be one of
* {@link Environment#DIRECTORY_MUSIC}, {@link Environment#DIRECTORY_PODCASTS},
* {@link Environment#DIRECTORY_RINGTONES}, {@link Environment#DIRECTORY_ALARMS},
* {@link Environment#DIRECTORY_NOTIFICATIONS}, {@link Environment#DIRECTORY_PICTURES},
* {@link Environment#DIRECTORY_MOVIES}, {@link Environment#DIRECTORY_DOWNLOADS},
* {@link Environment#DIRECTORY_DCIM}, or {@link Environment#DIRECTORY_DOCUMENTS}
*
* @see DocumentsContract
*/
public Intent createAccessIntent(@NonNull String directoryName) {
final Intent intent = new Intent(Intent.ACTION_OPEN_EXTERNAL_DIRECTORY);
intent.setData(Uri.fromFile(new File(mPath, directoryName)));
return intent;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof StorageVolume && mPath != null) {
@@ -234,11 +339,23 @@ public class StorageVolume implements Parcelable {
@Override
public String toString() {
final StringBuilder buffer = new StringBuilder("StorageVolume: ").append(mDescription);
if (mFsUuid != null) {
buffer.append(" (").append(mFsUuid).append(")");
}
return buffer.toString();
}
/** {@hide} */
// TODO(b/26742218): find out where toString() is called internally and replace these calls by
// dump().
public String dump() {
final CharArrayWriter writer = new CharArrayWriter();
dump(new IndentingPrintWriter(writer, " ", 80));
return writer.toString();
}
/** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.println("StorageVolume:");
pw.increaseIndent();

View File

@@ -39,6 +39,7 @@ import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.OnCloseListener;
import android.os.RemoteException;
import android.os.storage.StorageVolume;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
@@ -62,7 +63,8 @@ import java.util.List;
* All client apps must hold a valid URI permission grant to access documents,
* typically issued when a user makes a selection through
* {@link Intent#ACTION_OPEN_DOCUMENT}, {@link Intent#ACTION_CREATE_DOCUMENT},
* {@link Intent#ACTION_OPEN_DOCUMENT_TREE}, or {@link Intent#ACTION_OPEN_EXTERNAL_DIRECTORY}.
* {@link Intent#ACTION_OPEN_DOCUMENT_TREE}, or
* {@link StorageVolume#createAccessIntent(String) StorageVolume.createAccessIntent}.
*
* @see DocumentsProvider
*/