Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8436af1 authored by Tomasz Mikolajewski's avatar Tomasz Mikolajewski
Browse files

Wire multi-parents support for moving to DocumentsUI.

Bug: 26481380

Change-Id: Ief7db8f8abeca94e47832995fd0e2a6f31bfbc93
parent 165e2849
Loading
Loading
Loading
Loading
+16 −14
Original line number Diff line number Diff line
@@ -385,6 +385,7 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi
        FileOperations.start(
                getActivity(),
                getDisplayState().selectedDocumentsForCopy,
                getDisplayState().stack.peek(),
                (DocumentStack) data.getParcelableExtra(Shared.EXTRA_STACK),
                operationType);
    }
@@ -783,6 +784,7 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi
    private void deleteDocuments(final Selection selected) {

        checkArgument(!selected.isEmpty());
        final DocumentInfo srcParent = getDisplayState().stack.peek();
        new GetDocumentsTask() {
            @Override
            void onDocumentsReady(List<DocumentInfo> docs) {
@@ -791,7 +793,7 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi

                checkState(DELETE_JOB_DELAY > DELETE_UNDO_TIMEOUT);
                String operationId = FileOperations.delete(
                            getActivity(), docs, getDisplayState().stack,
                        getActivity(), docs, srcParent, getDisplayState().stack,
                        DELETE_JOB_DELAY);
                showDeleteSnackbar(hidden, operationId);
            }
+8 −4
Original line number Diff line number Diff line
@@ -199,7 +199,7 @@ class CopyJob extends Job {
                    "Copying " + srcInfo.displayName + " (" + srcInfo.derivedUri + ")"
                    + " to " + dstInfo.displayName + " (" + dstInfo.derivedUri + ")");

            processDocument(srcInfo, dstInfo);
            processDocument(srcInfo, null, dstInfo);
        }
    }

@@ -220,11 +220,15 @@ class CopyJob extends Job {
     * Copies a the given document to the given location.
     *
     * @param src DocumentInfos for the documents to copy.
     * @param srcParent DocumentInfo for the parent of the document to process.
     * @param dstDirInfo The destination directory.
     * @return True on success, false on failure.
     * @throws RemoteException
     *
     * TODO: Stop passing srcParent, as it's not used for copy, but for move only.
     */
    boolean processDocument(DocumentInfo src, DocumentInfo dstDirInfo) throws RemoteException {
    boolean processDocument(DocumentInfo src, DocumentInfo srcParent,
            DocumentInfo dstDirInfo) throws RemoteException {

        // TODO: When optimized copy kicks in, we'll not making any progress updates.
        // For now. Local storage isn't using optimized copy.
@@ -332,7 +336,7 @@ class CopyJob extends Job {
            cursor = getClient(srcDir).query(queryUri, queryColumns, null, null, null);
            while (cursor.moveToNext() && !isCanceled()) {
                DocumentInfo src = DocumentInfo.fromCursor(cursor, srcDir.authority);
                success &= processDocument(src, destDir);
                success &= processDocument(src, srcDir, destDir);
            }
        } finally {
            IoUtils.closeQuietly(cursor);
@@ -509,7 +513,7 @@ class CopyJob extends Job {
                .append("CopyJob")
                .append("{")
                .append("id=" + id)
                .append("srcs=" + mSrcs)
                .append(", srcs=" + mSrcs)
                .append(", destination=" + stack)
                .append("}")
                .toString();
+9 −3
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ final class DeleteJob extends Job {

    private static final String TAG = "DeleteJob";
    private List<DocumentInfo> mSrcs;
    final DocumentInfo mSrcParent;

    /**
     * Moves files to a destination identified by {@code destination}.
@@ -43,12 +44,14 @@ final class DeleteJob extends Job {
     *
     * @see @link {@link Job} constructor for most param descriptions.
     *
     * @param srcs List of files to delete
     * @param srcs List of files to delete.
     * @param srcParent Parent of all source files.
     */
    DeleteJob(Context service, Context appContext, Listener listener,
            String id, DocumentStack stack, List<DocumentInfo> srcs) {
            String id, DocumentStack stack, List<DocumentInfo> srcs, DocumentInfo srcParent) {
        super(service, appContext, listener, OPERATION_DELETE, id, stack);
        this.mSrcs = srcs;
        this.mSrcParent = srcParent;
    }

    @Override
@@ -75,6 +78,8 @@ final class DeleteJob extends Job {
    void start() throws RemoteException {
        for (DocumentInfo doc : mSrcs) {
            if (DEBUG) Log.d(TAG, "Deleting document @ " + doc.derivedUri);
            // TODO: Start using mSrcParent as soon as DocumentsProvider::removeDocument() is
            // implemented.
            if (!deleteDocument(doc)) {
                Log.w(TAG, "Failed to delete document @ " + doc.derivedUri);
                onFileFailed(doc);
@@ -88,7 +93,8 @@ final class DeleteJob extends Job {
                .append("DeleteJob")
                .append("{")
                .append("id=" + id)
                .append("srcs=" + mSrcs)
                .append(", srcs=" + mSrcs)
                .append(", srcParent=" + mSrcParent)
                .append(", location=" + stack)
                .append("}")
                .toString();
+14 −6
Original line number Diff line number Diff line
@@ -65,6 +65,11 @@ public class FileOperationService extends Service implements Job.Listener {
    public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST";
    public static final String EXTRA_FAILURE = "com.android.documentsui.FAILURE";

    // This extra is used only for moving and deleting. Currently it's not the case,
    // but in the future those files may be from multiple different parents. In
    // such case, this needs to be replaced with pairs of parent and child.
    public static final String EXTRA_SRC_PARENT = "com.android.documentsui.SRC_PARENT";

    public static final int OPERATION_UNKNOWN = -1;
    public static final int OPERATION_COPY = 1;
    public static final int OPERATION_MOVE = 2;
@@ -152,14 +157,14 @@ public class FileOperationService extends Service implements Job.Listener {
        Job job = null;
        synchronized (mRunning) {
            if (mWakeLock == null) {
                mWakeLock = mPowerManager.newWakeLock(
                        PowerManager.PARTIAL_WAKE_LOCK, TAG);
                mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
            }

            List<DocumentInfo> srcs = intent.getParcelableArrayListExtra(EXTRA_SRC_LIST);
            DocumentInfo srcParent = intent.getParcelableExtra(EXTRA_SRC_PARENT);
            DocumentStack stack = intent.getParcelableExtra(Shared.EXTRA_STACK);

            job = createJob(operationType, jobId, srcs, stack);
            job = createJob(operationType, jobId, srcs, srcParent, stack);

            if (job == null) {
                return;
@@ -222,7 +227,8 @@ public class FileOperationService extends Service implements Job.Listener {
     */
    @GuardedBy("mRunning")
    private @Nullable Job createJob(
            @OpType int operationType, String id, List<DocumentInfo> srcs, DocumentStack stack) {
            @OpType int operationType, String id, List<DocumentInfo> srcs, DocumentInfo srcParent,
            DocumentStack stack) {

        if (mRunning.containsKey(id)) {
            Log.w(TAG, "Duplicate job id: " + id
@@ -236,10 +242,12 @@ public class FileOperationService extends Service implements Job.Listener {
                job = jobFactory.createCopy(this, getApplicationContext(), this, id, stack, srcs);
                break;
            case OPERATION_MOVE:
                job = jobFactory.createMove(this, getApplicationContext(), this, id, stack, srcs);
                job = jobFactory.createMove(this, getApplicationContext(), this, id, stack, srcs,
                        srcParent);
                break;
            case OPERATION_DELETE:
                job = jobFactory.createDelete(this, getApplicationContext(), this, id, stack, srcs);
                job = jobFactory.createDelete(this, getApplicationContext(), this, id, stack, srcs,
                        srcParent);
                break;
            default:
                throw new UnsupportedOperationException();
+62 −27
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static com.android.documentsui.services.FileOperationService.EXTRA_DELAY;
import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID;
import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_PARENT;
import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
import static com.android.documentsui.services.FileOperationService.OPERATION_DELETE;
import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
@@ -35,6 +36,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Parcelable;
import android.support.annotation.VisibleForTesting;
import android.support.design.widget.Snackbar;
import android.util.Log;

@@ -65,8 +67,8 @@ public final class FileOperations {
     * Tries to start the activity. Returns the job id.
     */
    public static String start(
            Activity activity, List<DocumentInfo> srcDocs, DocumentStack stack,
            int operationType) {
            Activity activity, List<DocumentInfo> srcDocs,
            DocumentStack stack, int operationType) {

        if (DEBUG) Log.d(TAG, "Handling generic 'start' call.");

@@ -74,7 +76,7 @@ public final class FileOperations {
            case OPERATION_COPY:
                return FileOperations.copy(activity, srcDocs, stack);
            case OPERATION_MOVE:
                return FileOperations.move(activity, srcDocs, stack);
                throw new IllegalArgumentException("Moving requires providing the source parent.");
            case OPERATION_DELETE:
                throw new UnsupportedOperationException("Delete isn't currently supported.");
            default:
@@ -83,14 +85,27 @@ public final class FileOperations {
    }

    /**
     * Makes a best effort to cancel operation identified by jobId.
     *
     * @param context Context for the intent.
     * @param jobId The id of the job to cancel.
     *     Use {@link #createJobId} if you don't have one handy.
     * @param srcDocs A list of src files to copy.
     * @param dstStack The copy destination stack.
     * Tries to start the activity. Returns the job id.
     */
    public static String start(
            Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
            DocumentStack stack, int operationType) {

        if (DEBUG) Log.d(TAG, "Handling generic 'start' call.");

        switch (operationType) {
            case OPERATION_COPY:
                return FileOperations.copy(activity, srcDocs, stack);
            case OPERATION_MOVE:
                return FileOperations.move(activity, srcDocs, srcParent, stack);
            case OPERATION_DELETE:
                throw new UnsupportedOperationException("Delete isn't currently supported.");
            default:
                throw new UnsupportedOperationException("Unknown operation: " + operationType);
        }
    }

    @VisibleForTesting
    public static void cancel(Activity activity, String jobId) {
        if (DEBUG) Log.d(TAG, "Attempting to canceling operation: " + jobId);

@@ -101,15 +116,7 @@ public final class FileOperations {
        activity.startService(intent);
    }

    /**
     * Starts the service for a copy operation.
     *
     * @param context Context for the intent.
     * @param jobId A unique jobid for this job.
     *     Use {@link #createJobId} if you don't have one handy.
     * @param srcDocs A list of src files to copy.
     * @param destination The copy destination stack.
     */
    @VisibleForTesting
    public static String copy(
            Activity activity, List<DocumentInfo> srcDocs, DocumentStack destination) {
        String jobId = createJobId();
@@ -131,14 +138,17 @@ public final class FileOperations {
     * @param jobId A unique jobid for this job.
     *     Use {@link #createJobId} if you don't have one handy.
     * @param srcDocs A list of src files to copy.
     * @param srcParent Parent of all the source documents.
     * @param destination The move destination stack.
     */
    public static String move(
            Activity activity, List<DocumentInfo> srcDocs, DocumentStack destination) {
            Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
            DocumentStack destination) {
        String jobId = createJobId();
        if (DEBUG) Log.d(TAG, "Initiating 'move' operation id: " + jobId);

        Intent intent = createBaseIntent(OPERATION_MOVE, activity, jobId, srcDocs, destination);
        Intent intent = createBaseIntent(OPERATION_MOVE, activity, jobId, srcDocs, srcParent,
                destination);

        createSharedSnackBar(activity, R.plurals.move_begin, srcDocs.size())
                .show();
@@ -154,16 +164,19 @@ public final class FileOperations {
     * @param jobId A unique jobid for this job.
     *     Use {@link #createJobId} if you don't have one handy.
     * @param srcDocs A list of src files to copy.
     * @param srcParent Parent of all the source documents.
     * @param delay Number of milliseconds to wait before executing the job.
     * @return Id of the job.
     */
    public static String delete(
            Activity activity, List<DocumentInfo> srcDocs, DocumentStack location, int delay) {
            Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
            DocumentStack location, int delay) {
        String jobId = createJobId();
        if (DEBUG) Log.d(TAG, "Initiating 'delete' operation id " + jobId
                + " delayed by " + delay + " milliseconds.");

        Intent intent = createBaseIntent(OPERATION_DELETE, activity, jobId, srcDocs, location);
        Intent intent = createBaseIntent(OPERATION_DELETE, activity, jobId, srcDocs, srcParent,
                location);
        intent.putExtra(EXTRA_DELAY, delay);
        activity.startService(intent);

@@ -171,21 +184,43 @@ public final class FileOperations {
    }

    /**
     * Starts the service for a move operation.
     * Starts the service for an operation.
     *
     * @param jobId A unique jobid for this job.
     *     Use {@link #createJobId} if you don't have one handy.
     * @param srcDocs A list of src files to copy.
     * @return Id of the job.
     */
    public static Intent createBaseIntent(
            @OpType int operationType, Context context, String jobId, List<DocumentInfo> srcDocs,
            DocumentStack localeStack) {

        Intent intent = new Intent(context, FileOperationService.class);
        intent.putExtra(EXTRA_JOB_ID, jobId);
        intent.putParcelableArrayListExtra(EXTRA_SRC_LIST, asArrayList(srcDocs));
        intent.putExtra(EXTRA_STACK, (Parcelable) localeStack);
        intent.putExtra(EXTRA_OPERATION, operationType);

        return intent;
    }

    /**
     * Starts the service for an operation.
     *
     * @param jobId A unique jobid for this job.
     *     Use {@link #createJobId} if you don't have one handy.
     * @param srcDocs A list of src files to copy.
     * @param srcParent Parent of all the source documents.
     * @return Id of the job.
     */
    public static Intent createBaseIntent(
            @OpType int operationType, Context context, String jobId,
            List<DocumentInfo> srcDocs, DocumentStack localeStack) {
            List<DocumentInfo> srcDocs, DocumentInfo srcParent, DocumentStack localeStack) {

        Intent intent = new Intent(context, FileOperationService.class);
        intent.putExtra(EXTRA_JOB_ID, jobId);
        intent.putParcelableArrayListExtra(
                EXTRA_SRC_LIST, asArrayList(srcDocs));
        intent.putParcelableArrayListExtra(EXTRA_SRC_LIST, asArrayList(srcDocs));
        intent.putExtra(EXTRA_SRC_PARENT, srcParent);
        intent.putExtra(EXTRA_STACK, (Parcelable) localeStack);
        intent.putExtra(EXTRA_OPERATION, operationType);

Loading