Add support for multi-parents to DocumentsProvider::moveDocument.

Bug: 26481380
Change-Id: I96290268fd49072a334bde9c04c5313de8540f56
This commit is contained in:
Tomasz Mikolajewski
2016-01-25 14:26:54 +09:00
parent e76958297a
commit d46ecbcc53
4 changed files with 25 additions and 13 deletions

View File

@@ -342,8 +342,8 @@ public final class DocumentsContract {
* within the same document provider.
*
* @see #COLUMN_FLAGS
* @see DocumentsContract#moveDocument(ContentProviderClient, Uri, Uri)
* @see DocumentsProvider#moveDocument(String, String)
* @see DocumentsContract#moveDocument(ContentProviderClient, Uri, Uri, Uri)
* @see DocumentsProvider#moveDocument(String, String, String)
*/
public static final int FLAG_SUPPORTS_MOVE = 1 << 8;
@@ -613,6 +613,8 @@ public final class DocumentsContract {
/** {@hide} */
public static final String METHOD_IS_CHILD_DOCUMENT = "android:isChildDocument";
/** {@hide} */
public static final String EXTRA_PARENT_URI = "parentUri";
/** {@hide} */
public static final String EXTRA_URI = "uri";
@@ -1170,17 +1172,19 @@ public final class DocumentsContract {
* Moves the given document under a new parent.
*
* @param sourceDocumentUri document with {@link Document#FLAG_SUPPORTS_MOVE}
* @param sourceParentDocumentUri parent document of the document to move.
* @param targetParentDocumentUri document which will become a new parent of the source
* document.
* @return the moved document, or {@code null} if failed.
* @hide
*/
public static Uri moveDocument(ContentResolver resolver, Uri sourceDocumentUri,
Uri targetParentDocumentUri) {
Uri sourceParentDocumentUri, Uri targetParentDocumentUri) {
final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
sourceDocumentUri.getAuthority());
try {
return moveDocument(client, sourceDocumentUri, targetParentDocumentUri);
return moveDocument(client, sourceParentDocumentUri, sourceDocumentUri,
targetParentDocumentUri);
} catch (Exception e) {
Log.w(TAG, "Failed to move document", e);
return null;
@@ -1191,9 +1195,10 @@ public final class DocumentsContract {
/** {@hide} */
public static Uri moveDocument(ContentProviderClient client, Uri sourceDocumentUri,
Uri targetParentDocumentUri) throws RemoteException {
Uri sourceParentDocumentUri, Uri targetParentDocumentUri) throws RemoteException {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri);
in.putParcelable(DocumentsContract.EXTRA_PARENT_URI, sourceParentDocumentUri);
in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, targetParentDocumentUri);
final Bundle out = client.call(METHOD_MOVE_DOCUMENT, null, in);

View File

@@ -289,12 +289,14 @@ public abstract class DocumentsProvider extends ContentProvider {
* be returned.
*
* @param sourceDocumentId the document to move.
* @param sourceParentDocumentId the parent of the document to move.
* @param targetParentDocumentId the target document to be a new parent of the
* source document.
* @hide
*/
@SuppressWarnings("unused")
public String moveDocument(String sourceDocumentId, String targetParentDocumentId)
public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
String targetParentDocumentId)
throws FileNotFoundException {
throw new UnsupportedOperationException("Move not supported");
}
@@ -759,7 +761,7 @@ public abstract class DocumentsProvider extends ContentProvider {
out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
// Original document no longer exists, clean up any grants
// Original document no longer exists, clean up any grants.
revokeDocumentPermission(documentId);
}
@@ -767,7 +769,7 @@ public abstract class DocumentsProvider extends ContentProvider {
enforceWritePermissionInner(documentUri, getCallingPackage(), null);
deleteDocument(documentId);
// Document no longer exists, clean up any grants
// Document no longer exists, clean up any grants.
revokeDocumentPermission(documentId);
} else if (METHOD_COPY_DOCUMENT.equals(method)) {
@@ -793,13 +795,16 @@ public abstract class DocumentsProvider extends ContentProvider {
}
} else if (METHOD_MOVE_DOCUMENT.equals(method)) {
final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI);
final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
final String targetId = DocumentsContract.getDocumentId(targetUri);
enforceReadPermissionInner(documentUri, getCallingPackage(), null);
enforceWritePermissionInner(documentUri, getCallingPackage(), null);
enforceReadPermissionInner(parentSourceUri, getCallingPackage(), null);
enforceWritePermissionInner(targetUri, getCallingPackage(), null);
final String newDocumentId = moveDocument(documentId, targetId);
final String newDocumentId = moveDocument(documentId, parentSourceId, targetId);
if (newDocumentId != null) {
final Uri newDocumentUri = buildDocumentUriMaybeUsingTree(documentUri,
@@ -814,7 +819,7 @@ public abstract class DocumentsProvider extends ContentProvider {
out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
}
// Original document no longer exists, clean up any grants
// Original document no longer exists, clean up any grants.
revokeDocumentPermission(documentId);
} else {

View File

@@ -21,6 +21,7 @@ import static com.android.documentsui.services.FileOperationService.OPERATION_MO
import android.app.Notification;
import android.app.Notification.Builder;
import android.content.Context;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
@@ -85,7 +86,7 @@ final class MoveJob extends CopyJob {
if (src.authority.equals(dest.authority)) {
if ((src.flags & Document.FLAG_SUPPORTS_MOVE) != 0) {
if (DocumentsContract.moveDocument(getClient(src), src.derivedUri,
dest.derivedUri) == null) {
Uri.EMPTY /* Not used yet */, dest.derivedUri) == null) {
onFileFailed(src);
return false;
}

View File

@@ -463,7 +463,8 @@ public class ExternalStorageProvider extends DocumentsProvider {
}
@Override
public String moveDocument(String sourceDocumentId, String targetParentDocumentId)
public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
String targetParentDocumentId)
throws FileNotFoundException {
final File before = getFileForDocId(sourceDocumentId);
final File after = new File(getFileForDocId(targetParentDocumentId), before.getName());