Provider-level changes for implementing direct eject of a root in Files app.
Several changes at different levels:
1. Introduction of ejectRoot(String) for DocumentsProvider
2. Introduction of ejectRoot(ContentResolver, Uri, String) for
DocumentsContract
4. Additional permission for MOUNT_UNMOUNT for ExternalStorageProvider
5. Implementation of ejectRoot(String) for External StorageProvider
Bug: 29584653
Change-Id: I28557af63259548784cf24d5b051eb06ad5193ca
(cherry picked from commit 2ccc18357d6741dde56edc4d5a2608f15f4b9078)
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 1158776..b0ea99c 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -593,6 +593,9 @@
* @hide
*/
public static final int FLAG_REMOVABLE_USB = 1 << 20;
+
+ /** {@hide} */
+ public static final int FLAG_SUPPORTS_EJECT = 1 << 21;
}
/**
@@ -643,6 +646,8 @@
public static final String METHOD_IS_CHILD_DOCUMENT = "android:isChildDocument";
/** {@hide} */
public static final String METHOD_REMOVE_DOCUMENT = "android:removeDocument";
+ /** {@hide} */
+ public static final String METHOD_EJECT_ROOT = "android:ejectRoot";
/** {@hide} */
public static final String EXTRA_PARENT_URI = "parentUri";
@@ -1274,6 +1279,37 @@
client.call(METHOD_REMOVE_DOCUMENT, null, in);
}
+ /** {@hide} */
+ public static boolean ejectRoot(ContentResolver resolver, Uri rootUri) {
+ final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
+ rootUri.getAuthority());
+ try {
+ return ejectRoot(client, rootUri);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to eject root", e);
+ return false;
+ } finally {
+ ContentProviderClient.releaseQuietly(client);
+ }
+ }
+
+ /** {@hide} */
+ public static boolean ejectRoot(ContentProviderClient client, Uri rootUri)
+ throws RemoteException {
+ final Bundle in = new Bundle();
+ in.putParcelable(DocumentsContract.EXTRA_URI, rootUri);
+
+ final Bundle out = client.call(METHOD_EJECT_ROOT, null, in);
+
+ if (out == null) {
+ throw new RemoteException("Failed to get a reponse from ejectRoot.");
+ }
+ if (!out.containsKey(DocumentsContract.EXTRA_RESULT)) {
+ throw new RemoteException("Response did not include result field..");
+ }
+ return out.getBoolean(DocumentsContract.EXTRA_RESULT);
+ }
+
/**
* Open the given image for thumbnail purposes, using any embedded EXIF
* thumbnail if available, and providing orientation hints from the parent