diff options
| author | 2016-02-16 09:43:30 +0900 | |
|---|---|---|
| committer | 2016-02-18 00:54:26 +0000 | |
| commit | 32a34d337977618d95ab183f65627a4ff4b9a390 (patch) | |
| tree | 0f04c549de9434dab632b8061b5340f6de55a518 | |
| parent | 40089ca9950221d633e8e8662384a2ae132aa236 (diff) | |
Limit number of ClipData items for a quick viewer to 1000.
Bug: 20822219
Change-Id: I774be914ddeea0335dc646000a1d5c997ea73fd4
| -rw-r--r-- | packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java | 106 |
1 files changed, 73 insertions, 33 deletions
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java index c34cec0d57bb..a77a9b3559dc 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java +++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java @@ -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); - if (Document.MIME_TYPE_DIR.equals(mimeType)) { - return; - } + mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); + if (Document.MIME_TYPE_DIR.equals(mimeType)) { + continue; + } + + id = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID); + authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY); + uri = DocumentsContract.buildDocumentUri(authority, id); - 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); + if (id.equals(mDocument.documentId)) { + if (DEBUG) Log.d(TAG, "Found starting point for QV. " + i); + documentLocation = i; + } - if (id.equals(mDocument.documentId)) { - if (DEBUG) Log.d(TAG, "Found starting point for QV. " + index); - mDocumentLocation = index; + uris.add(uri); } - ClipData.Item item = new ClipData.Item(uri); - if (mClipData == null) { - mClipData = new ClipData( - "URIs", new String[]{ClipDescription.MIMETYPE_TEXT_URILIST}, item); + 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; } } |