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

Commit d50f4ea1 authored by Austin Tankiang's avatar Austin Tankiang
Browse files

Handle queued state for progress messages

Currently, we delay file URI resolution to when the operation actually
starts as resolution could require I/O in cases where there are many
files in an operation (in which case the list of URIs are passed through
a temporary file). However, we need the filename for single file
operation progress messages while the operation is still queued, so in
that case only, resolve the file URI early.

This also refactors duplicated code in jobs to the resolved resources
common job.

Bug: 407674989
Test: atest -c 'DocumentsUIGoogleTests:com.android.documentsui.services'
Flag: com.android.documentsui.flags.visual_signals_ro
Change-Id: Ic6bc290e48554f29d0ad418a3bac4f9b25f00b10
parent 67b1a972
Loading
Loading
Loading
Loading
+1 −22
Original line number Diff line number Diff line
@@ -25,13 +25,11 @@ import android.app.Notification;
import android.app.Notification.Builder;
import android.content.ContentResolver;
import android.content.Context;
import android.icu.text.MessageFormat;
import android.net.Uri;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.provider.DocumentsContract;
import android.text.BidiFormatter;
import android.util.Log;

import com.android.documentsui.R;
@@ -43,9 +41,6 @@ import com.android.documentsui.base.UserId;
import com.android.documentsui.clipping.UrisSupplier;

import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

// TODO: Stop extending CopyJob.
final class CompressJob extends CopyJob {
@@ -95,23 +90,7 @@ final class CompressJob extends CopyJob {

    @Override
    protected String getProgressMessage() {
        switch (getState()) {
            case Job.STATE_SET_UP:
            case Job.STATE_COMPLETED:
            case Job.STATE_CANCELED:
                Map<String, Object> formatArgs = new HashMap<>();
                formatArgs.put("count", mResolvedDocs.size());
                if (mResolvedDocs.size() == 1) {
                    formatArgs.put("filename", BidiFormatter.getInstance().unicodeWrap(
                            mResolvedDocs.get(0).displayName));
                }
                return (new MessageFormat(
                                service.getString(getRes(R.string.compress_in_progress)),
                                Locale.getDefault()))
                        .format(formatArgs);
            default:
                return "";
        }
        return getProgressMessage(R.string.compress_in_progress);
    }

    @Override
+3 −23
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@ import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.icu.text.MessageFormat;
import android.net.Uri;
import android.os.DeadObjectException;
import android.os.FileUtils;
@@ -99,7 +98,6 @@ import java.io.SyncFailedException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
@@ -210,27 +208,9 @@ class CopyJob extends ResolvedResourcesJob {
    }

    protected String getProgressMessage() {
        switch (getState()) {
            case Job.STATE_SET_UP:
            case Job.STATE_COMPLETED:
            case Job.STATE_CANCELED:
        Map<String, Object> formatArgs = new HashMap<>();
                formatArgs.put("count", mResolvedDocs.size());
                formatArgs.put("directory",
                        BidiFormatter.getInstance().unicodeWrap(mDstInfo.displayName));
                if (mResolvedDocs.size() == 1) {
                    formatArgs.put("filename",
                            BidiFormatter.getInstance().unicodeWrap(
                                    mResolvedDocs.get(0).displayName));
                }
                return (new MessageFormat(
                                service.getString(getRes(R.string.copy_in_progress)),
                                Locale.getDefault()))
                        .format(formatArgs);

            default:
                return "";
        }
        formatArgs.put("directory", BidiFormatter.getInstance().unicodeWrap(mDstInfo.displayName));
        return getProgressMessage(R.string.copy_in_progress, formatArgs);
    }

    @Override
+1 −22
Original line number Diff line number Diff line
@@ -24,9 +24,7 @@ import android.app.Notification;
import android.app.Notification.Builder;
import android.content.ContentResolver;
import android.content.Context;
import android.icu.text.MessageFormat;
import android.net.Uri;
import android.text.BidiFormatter;
import android.util.Log;

import com.android.documentsui.MetricConsts;
@@ -39,9 +37,6 @@ import com.android.documentsui.base.UserId;
import com.android.documentsui.clipping.UrisSupplier;

import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Nullable;

@@ -100,23 +95,7 @@ final class DeleteJob extends ResolvedResourcesJob {
    }

    private String getProgressMessage() {
        switch (getState()) {
            case Job.STATE_SET_UP:
            case Job.STATE_COMPLETED:
            case Job.STATE_CANCELED:
                Map<String, Object> formatArgs = new HashMap<>();
                formatArgs.put("count", mResolvedDocs.size());
                if (mResolvedDocs.size() == 1) {
                    formatArgs.put("filename", BidiFormatter.getInstance().unicodeWrap(
                            mResolvedDocs.get(0).displayName));
                }
                return (new MessageFormat(
                                service.getString(getRes(R.string.delete_in_progress)),
                                Locale.getDefault()))
                        .format(formatArgs);
            default:
                return "";
        }
        return getProgressMessage(R.string.delete_in_progress);
    }

    @Override
+3 −21
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import static com.android.documentsui.util.Material3Config.getRes;
import android.app.Notification;
import android.app.Notification.Builder;
import android.content.Context;
import android.icu.text.MessageFormat;
import android.net.Uri;
import android.os.DeadObjectException;
import android.os.Messenger;
@@ -46,7 +45,6 @@ import com.android.documentsui.clipping.UrisSupplier;

import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Nullable;
@@ -101,25 +99,9 @@ final class MoveJob extends CopyJob {

    @Override
    protected String getProgressMessage() {
        switch (getState()) {
            case Job.STATE_SET_UP:
            case Job.STATE_COMPLETED:
            case Job.STATE_CANCELED:
        Map<String, Object> formatArgs = new HashMap<>();
                formatArgs.put("count", mResolvedDocs.size());
                formatArgs.put("directory",
                        BidiFormatter.getInstance().unicodeWrap(mDstInfo.displayName));
                if (mResolvedDocs.size() == 1) {
                    formatArgs.put("filename", BidiFormatter.getInstance().unicodeWrap(
                            mResolvedDocs.get(0).displayName));
                }
                return (new MessageFormat(
                                service.getString(getRes(R.string.move_in_progress)),
                                Locale.getDefault()))
                        .format(formatArgs);
            default:
                return "";
        }
        formatArgs.put("directory", BidiFormatter.getInstance().unicodeWrap(mDstInfo.displayName));
        return getProgressMessage(R.string.move_in_progress, formatArgs);
    }

    @Override
+47 −1
Original line number Diff line number Diff line
@@ -19,11 +19,15 @@ package com.android.documentsui.services;
import static android.os.SystemClock.uptimeMillis;

import static com.android.documentsui.base.SharedMinimal.DEBUG;
import static com.android.documentsui.util.FlagUtils.isVisualSignalsFlagEnabled;
import static com.android.documentsui.util.Material3Config.getRes;

import android.content.ContentResolver;
import android.content.Context;
import android.icu.text.MessageFormat;
import android.net.Uri;
import android.os.RemoteException;
import android.text.BidiFormatter;
import android.util.Log;

import com.android.documentsui.archives.ArchivesProvider;
@@ -38,7 +42,10 @@ import com.android.documentsui.services.FileOperationService.OpType;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Abstract job that resolves all resource URIs into mResolvedDocs. This provides
@@ -62,6 +69,12 @@ public abstract class ResolvedResourcesJob extends Job {

        // Delay the initialization of it to setUp() because it may be IO extensive.
        mResolvedDocs = new ArrayList<>(srcs.getItemCount());

        if (isVisualSignalsFlagEnabled() && srcs.getItemCount() == 1) {
            // Prebuild the document list so we can get the filename for a single file progress
            // message. With a single file only, this should not be IO intensive.
            buildDocumentList();
        }
    }

    boolean setUp() {
@@ -88,7 +101,7 @@ public abstract class ResolvedResourcesJob extends Job {
            return false;
        }

        int docsResolved = buildDocumentList();
        int docsResolved = refreshDocumentList();
        if (!isCanceled() && docsResolved < mResourceUris.getItemCount()) {
            if (docsResolved == 0) {
                Log.e(TAG, "Cannot load any documents. Aborting.");
@@ -166,4 +179,37 @@ public abstract class ResolvedResourcesJob extends Job {

        return docsLoaded;
    }

    private int refreshDocumentList() {
        // We've never built the list in the first place.
        if (mResolvedDocs.isEmpty() && failureCount == 0) {
            return buildDocumentList();
        }

        final ContentResolver resolver = appContext.getContentResolver();
        mResolvedDocs.removeIf(doc -> {
            try {
                doc.updateSelf(resolver, UserId.DEFAULT_USER);
            } catch (FileNotFoundException e) {
                onFileFailed(doc);
                return true;
            }
            return false;
        });
        return mResolvedDocs.size();
    }

    protected String getProgressMessage(int stringId, Map<String, Object> formatArgs) {
        formatArgs.put("count", mResourceUris.getItemCount());
        if (mResourceUris.getItemCount() == 1 && mResolvedDocs.size() == 1) {
            formatArgs.put("filename",
                    BidiFormatter.getInstance().unicodeWrap(mResolvedDocs.get(0).displayName));
        }
        return (new MessageFormat(service.getString(getRes(stringId)), Locale.getDefault()))
                .format(formatArgs);
    }

    protected String getProgressMessage(int stringId) {
        return getProgressMessage(stringId, new HashMap<>());
    }
}
Loading