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

Commit ab75f530 authored by François Degros's avatar François Degros
Browse files

Report failed paths when unpacking archive

Put in place all the infrastructure needed to faithfully report the
paths of the files that cannot be extracted by UnpackJob when unpacking
an archive.

Limit the size of the lists transmitted by getFailureNotification() in
order to avoid running into a serialization buffer size limit.

Bug: 422855509
Bug: 417360945
Bug: 409148842
Flag: com.android.documentsui.flags.use_material3
Flag: com.android.documentsui.flags.zip_ng_ro
Test: atest DocumentsUIGoogleTests:com.android.documentsui.services.UnpackJobTest
Test: atest DocumentsUIGoogleTests:com.android.documentsui.ui.MessageBuilderTest
Change-Id: I902f2d99b0a53b8107afe8bdde0c9d21e97d3498
parent 9634676d
Loading
Loading
Loading
Loading
+16 −10
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.text.Html;
import android.widget.TextView;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
@@ -44,6 +45,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

/**
 * Alert dialog for operation dialogs.
@@ -68,16 +70,18 @@ public class OperationDialogFragment extends DialogFragment {
    public static void show(
            FragmentManager fm,
            @DialogType int dialogType,
            ArrayList<DocumentInfo> failedSrcList,
            ArrayList<Uri> uriList,
            ArrayList<DocumentInfo> failedDocs,
            ArrayList<Uri> failedUris,
            ArrayList<String> failedPaths,
            DocumentStack dstStack,
            @OpType int operationType) {

        final Bundle args = new Bundle();
        args.putInt(FileOperationService.EXTRA_DIALOG_TYPE, dialogType);
        args.putInt(FileOperationService.EXTRA_OPERATION_TYPE, operationType);
        args.putParcelableArrayList(FileOperationService.EXTRA_FAILED_DOCS, failedSrcList);
        args.putParcelableArrayList(FileOperationService.EXTRA_FAILED_URIS, uriList);
        args.putParcelableArrayList(FileOperationService.EXTRA_FAILED_DOCS, failedDocs);
        args.putParcelableArrayList(FileOperationService.EXTRA_FAILED_URIS, failedUris);
        args.putStringArrayList(FileOperationService.EXTRA_FAILED_PATHS, failedPaths);

        final FragmentTransaction ft = fm.beginTransaction();
        final OperationDialogFragment fragment = new OperationDialogFragment();
@@ -88,21 +92,23 @@ public class OperationDialogFragment extends DialogFragment {
    }

    @Override
    public Dialog onCreateDialog(Bundle inState) {
    public @NonNull Dialog onCreateDialog(Bundle inState) {
        super.onCreate(inState);

        final @DialogType int dialogType =
              getArguments().getInt(FileOperationService.EXTRA_DIALOG_TYPE);
        final @OpType int operationType =
              getArguments().getInt(FileOperationService.EXTRA_OPERATION_TYPE);
        final ArrayList<Uri> uriList = getArguments().getParcelableArrayList(
                FileOperationService.EXTRA_FAILED_URIS);
        final ArrayList<DocumentInfo> docList = getArguments().getParcelableArrayList(
                FileOperationService.EXTRA_FAILED_DOCS);
        final List<DocumentInfo> failedDocs = getArguments().getParcelableArrayList(
                FileOperationService.EXTRA_FAILED_DOCS, DocumentInfo.class);
        final List<Uri> failedUris = getArguments().getParcelableArrayList(
                FileOperationService.EXTRA_FAILED_URIS, Uri.class);
        final List<String> failedPaths = getArguments().getStringArrayList(
                FileOperationService.EXTRA_FAILED_PATHS);

        final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getActivity());
        final String message = new MessageBuilder(getContext()).generateListMessage(
                dialogType, operationType, docList, uriList);
                dialogType, operationType, failedDocs, failedUris, failedPaths);

        builder.setMessage(Html.fromHtml(message));
        builder.setPositiveButton(
+9 −6
Original line number Diff line number Diff line
@@ -317,15 +317,18 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler
            final int opType = intent.getIntExtra(
                    FileOperationService.EXTRA_OPERATION_TYPE,
                    FileOperationService.OPERATION_COPY);
            final ArrayList<DocumentInfo> docList =
                    intent.getParcelableArrayListExtra(FileOperationService.EXTRA_FAILED_DOCS);
            final ArrayList<Uri> uriList =
                    intent.getParcelableArrayListExtra(FileOperationService.EXTRA_FAILED_URIS);
            final ArrayList<DocumentInfo> failedDocs = intent.getParcelableArrayListExtra(
                    FileOperationService.EXTRA_FAILED_DOCS, DocumentInfo.class);
            final ArrayList<Uri> failedUris = intent.getParcelableArrayListExtra(
                    FileOperationService.EXTRA_FAILED_URIS, Uri.class);
            final ArrayList<String> failedPaths = intent.getStringArrayListExtra(
                    FileOperationService.EXTRA_FAILED_PATHS);
            OperationDialogFragment.show(
                    getSupportFragmentManager(),
                    dialogType,
                    docList,
                    uriList,
                    failedDocs,
                    failedUris,
                    failedPaths,
                    mState.stack,
                    opType);
        }
+4 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ public class FileOperationService extends Service implements Job.Listener {

    public static final String EXTRA_FAILED_URIS = "com.android.documentsui.FAILED_URIS";
    public static final String EXTRA_FAILED_DOCS = "com.android.documentsui.FAILED_DOCS";
    public static final String EXTRA_FAILED_PATHS = "com.android.documentsui.FAILED_PATHS";

    // Extras used to start or cancel a file operation...
    public static final String EXTRA_JOB_ID = "com.android.documentsui.JOB_ID";
@@ -510,6 +511,9 @@ public class FileOperationService extends Service implements Job.Listener {
            if (!job.failedDocs.isEmpty()) {
                Log.e(TAG, "Job failed to process docs: " + job.failedDocs + ".");
            }
            if (!job.failedPaths.isEmpty()) {
                Log.e(TAG, "Job failed to extract paths: " + job.failedPaths);
            }
            notificationManager.notify(
                    job.id, NOTIFICATION_ID_FAILURE, job.getFailureNotification());
        }
+20 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static com.android.documentsui.DocumentsApplication.acquireUnstableProvid
import static com.android.documentsui.services.FileOperationService.EXTRA_CANCEL;
import static com.android.documentsui.services.FileOperationService.EXTRA_DIALOG_TYPE;
import static com.android.documentsui.services.FileOperationService.EXTRA_FAILED_DOCS;
import static com.android.documentsui.services.FileOperationService.EXTRA_FAILED_PATHS;
import static com.android.documentsui.services.FileOperationService.EXTRA_FAILED_URIS;
import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID;
import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION_TYPE;
@@ -46,6 +47,7 @@ import android.util.Log;

import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.PluralsRes;

import com.android.documentsui.Metrics;
@@ -110,6 +112,7 @@ abstract public class Job implements Runnable {
    volatile int failureCount = 0;
    final ArrayList<DocumentInfo> failedDocs = new ArrayList<>();
    final ArrayList<Uri> failedUris = new ArrayList<>();
    final ArrayList<String> failedPaths = new ArrayList<>();

    final Notification.Builder mProgressBuilder;

@@ -274,6 +277,11 @@ abstract public class Job implements Runnable {
        failedUris.add(uri);
    }

    void onPathFailed(@NonNull String path) {
        failureCount++;
        failedPaths.add(path);
    }

    final boolean hasFailures() {
        return failureCount > 0;
    }
@@ -313,8 +321,18 @@ abstract public class Job implements Runnable {
        final Intent navigateIntent = buildNavigateIntent(INTENT_TAG_FAILURE);
        navigateIntent.putExtra(EXTRA_DIALOG_TYPE, OperationDialogFragment.DIALOG_TYPE_FAILURE);
        navigateIntent.putExtra(EXTRA_OPERATION_TYPE, operationType);
        navigateIntent.putParcelableArrayListExtra(EXTRA_FAILED_DOCS, failedDocs);
        navigateIntent.putParcelableArrayListExtra(EXTRA_FAILED_URIS, failedUris);

        // Limit the size of the lists getting passed with the failure notification.
        final int maxListSize = 100;
        navigateIntent.putParcelableArrayListExtra(EXTRA_FAILED_DOCS,
                failedDocs.size() <= maxListSize ? failedDocs
                        : new ArrayList<>(failedDocs.subList(0, maxListSize)));
        navigateIntent.putParcelableArrayListExtra(EXTRA_FAILED_URIS,
                failedUris.size() <= maxListSize ? failedUris
                        : new ArrayList<>(failedUris.subList(0, maxListSize)));
        navigateIntent.putStringArrayListExtra(EXTRA_FAILED_PATHS,
                failedPaths.size() <= maxListSize ? failedPaths
                        : new ArrayList<>(failedPaths.subList(0, maxListSize)));

        final Notification.Builder errorBuilder =
                createNotificationBuilder()
+1 −1
Original line number Diff line number Diff line
@@ -322,7 +322,7 @@ class UnpackJob(
            synchronized(this) {
                tracker.filesRequired--
            }
            onResolveFailed(Uri.withAppendedPath(dirUri, fileName))
            onPathFailed(path.toString())
        }

        // Adjust progress expectations after extracting a file.
Loading