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

Commit 8acbb305 authored by Tomasz Mikolajewski's avatar Tomasz Mikolajewski Committed by android-build-merger
Browse files

Limit number of ClipData items for a quick viewer to 1000. am: 32a34d33

am: 9ac2efa6

* commit '9ac2efa6':
  Limit number of ClipData items for a quick viewer to 1000.
parents 2543600d 9ac2efa6
Loading
Loading
Loading
Loading
+73 −33
Original line number Diff line number Diff line
@@ -33,16 +33,19 @@ import android.provider.DocumentsContract.Document;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.util.Range;

import com.android.documentsui.dirlist.Model;
import com.android.documentsui.model.DocumentInfo;

import java.util.ArrayList;
import java.util.List;

/**
 * Provides support for gather a list of quick-viewable files into a quick view intent.
 */
final class QuickViewIntentBuilder {
    private static final int MAX_CLIP_ITEMS = 1000;

    private final DocumentInfo mDocument;
    private final Model mModel;
@@ -50,9 +53,6 @@ final class QuickViewIntentBuilder {
    private final PackageManager mPkgManager;
    private final Resources mResources;

    private ClipData mClipData;
    private int mDocumentLocation;

    public QuickViewIntentBuilder(
            PackageManager pkgManager,
            Resources resources,
@@ -80,12 +80,28 @@ final class QuickViewIntentBuilder {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setPackage(trustedPkg);
            if (hasRegisteredHandler(intent)) {
                List<String> siblingIds = mModel.getModelIds();
                for (int i = 0; i < siblingIds.size(); i++) {
                    onNextItem(i, siblingIds);
                final ArrayList<Uri> uris = new ArrayList<Uri>();
                final int documentLocation = collectViewableUris(uris);
                final Range<Integer> range = computeSiblingsRange(uris, documentLocation);

                ClipData clipData = null;
                ClipData.Item item;
                Uri uri;
                for (int i = range.getLower(); i <= range.getUpper(); i++) {
                    uri = uris.get(i);
                    item = new ClipData.Item(uri);
                    if (DEBUG) Log.d(TAG, "Including file: " + uri);
                    if (clipData == null) {
                        clipData = new ClipData(
                                "URIs", new String[] { ClipDescription.MIMETYPE_TEXT_URILIST },
                                item);
                    } else {
                        clipData.addItem(item);
                    }
                intent.putExtra(Intent.EXTRA_INDEX, mDocumentLocation);
                intent.setClipData(mClipData);
                }

                intent.putExtra(Intent.EXTRA_INDEX, documentLocation);
                intent.setClipData(clipData);

                return intent;
            } else {
@@ -96,39 +112,63 @@ final class QuickViewIntentBuilder {
        return null;
    }

    private boolean hasRegisteredHandler(Intent intent) {
        // Try to resolve the intent. If a matching app isn't installed, it won't resolve.
        return intent.resolveActivity(mPkgManager) != null;
    }
    private int collectViewableUris(ArrayList<Uri> uris) {
        final List<String> siblingIds = mModel.getModelIds();
        uris.ensureCapacity(siblingIds.size());

    private void onNextItem(int index, List<String> siblingIds) {
        final Cursor cursor = mModel.getItem(siblingIds.get(index));
        int documentLocation = 0;
        Cursor cursor;
        String mimeType;
        String id;
        String authority;
        Uri uri;

        if (cursor == null) {
            return;
        }
        // Cursor's are not guaranteed to be immutable. Hence, traverse it only once.
        for (int i = 0; i < siblingIds.size(); i++) {
            cursor = mModel.getItem(siblingIds.get(i));

        String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
            mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
            if (Document.MIME_TYPE_DIR.equals(mimeType)) {
            return;
                continue;
            }

        String id = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
        String authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
        Uri uri = DocumentsContract.buildDocumentUri(authority, id);
        if (DEBUG) Log.d(TAG, "Including file[" + id + "] @ " + uri);
            id = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
            authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
            uri = DocumentsContract.buildDocumentUri(authority, id);

            if (id.equals(mDocument.documentId)) {
            if (DEBUG) Log.d(TAG, "Found starting point for QV. " + index);
            mDocumentLocation = index;
                if (DEBUG) Log.d(TAG, "Found starting point for QV. " + i);
                documentLocation = i;
            }

        ClipData.Item item = new ClipData.Item(uri);
        if (mClipData == null) {
            mClipData = new ClipData(
                    "URIs", new String[]{ClipDescription.MIMETYPE_TEXT_URILIST}, item);
            uris.add(uri);
        }

        return documentLocation;
    }

    private static Range<Integer> computeSiblingsRange(List<Uri> uris, int documentLocation) {
        // Restrict number of siblings to avoid hitting the IPC limit.
        // TODO: Remove this restriction once ClipData can hold an arbitrary number of
        // items.
        int firstSibling;
        int lastSibling;
        if (documentLocation < uris.size() / 2) {
            firstSibling = Math.max(0, documentLocation - MAX_CLIP_ITEMS / 2);
            lastSibling = Math.min(uris.size() - 1, firstSibling + MAX_CLIP_ITEMS - 1);
        } else {
            mClipData.addItem(item);
            lastSibling = Math.min(uris.size() - 1, documentLocation + MAX_CLIP_ITEMS / 2);
            firstSibling = Math.max(0, lastSibling - MAX_CLIP_ITEMS + 1);
        }

        if (DEBUG) Log.d(TAG, "Copmuted siblings from index: " + firstSibling
                + " to: " + lastSibling);

        return new Range(firstSibling, lastSibling);
    }

    private boolean hasRegisteredHandler(Intent intent) {
        // Try to resolve the intent. If a matching app isn't installed, it won't resolve.
        return intent.resolveActivity(mPkgManager) != null;
    }
}