summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tony Huang <tonyychuang@google.com> 2018-11-06 17:16:47 +0800
committer Tony Huang <tonyychuang@google.com> 2019-01-03 14:42:51 +0800
commit7a7e7df7f310c6e46e347f1273755a0eb469df59 (patch)
tree29a3040d98c92921102acc5557ca8c8f9b8b37c5
parenteb43e960649c674c8f0c8c0386c8c48e12574435 (diff)
Implement files preview on pick mode specific action
1. Add preview icon and show on specific action state such as ACTION_OPEN, ACTION_GET_CONTENT and ACTION_OPEN_TREE. if file is not enabled, the icon will be hidden. 2. Fix list item background color bug on tablet in night mode. 3. Ensure sort UI update after restoreRootAndDirectory. 4. Hide "Summary" column in tablet list mode because it seems not display any content. TODO: Delete "Summary" related code if ensure it not work. Bug: 112470012 Bug: 120961136 Test: manual Test: atest DocumentsUITests Change-Id: Id07848ed17933b2938e300d50503afeb1df8c902
-rw-r--r--res/drawable/circle_button_background.xml21
-rw-r--r--res/drawable/ic_zoom_out.xml24
-rw-r--r--res/layout-sw720dp/column_headers.xml14
-rw-r--r--res/layout-sw720dp/item_doc_list.xml45
-rw-r--r--res/layout/item_dir_grid.xml1
-rw-r--r--res/layout/item_doc_grid.xml23
-rw-r--r--res/layout/item_doc_list.xml29
-rw-r--r--res/values/dimens.xml1
-rw-r--r--res/values/strings.xml2
-rw-r--r--src/com/android/documentsui/AbstractActionHandler.java5
-rw-r--r--src/com/android/documentsui/ActionHandler.java2
-rw-r--r--src/com/android/documentsui/BaseActivity.java1
-rw-r--r--src/com/android/documentsui/base/State.java10
-rw-r--r--src/com/android/documentsui/dirlist/DirectoryFragment.java4
-rw-r--r--src/com/android/documentsui/dirlist/DocumentHolder.java28
-rw-r--r--src/com/android/documentsui/dirlist/DocumentItemDetails.java4
-rw-r--r--src/com/android/documentsui/dirlist/GridDocumentHolder.java19
-rw-r--r--src/com/android/documentsui/dirlist/ListDocumentHolder.java24
-rw-r--r--src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java2
-rw-r--r--src/com/android/documentsui/files/ActionHandler.java3
-rw-r--r--src/com/android/documentsui/files/QuickViewIntentBuilder.java19
-rw-r--r--src/com/android/documentsui/picker/ActionHandler.java39
-rw-r--r--tests/common/com/android/documentsui/bots/DirectoryListBot.java19
-rw-r--r--tests/functional/com/android/documentsui/PickerPreviewAllTypeUiTest.java81
-rw-r--r--tests/functional/com/android/documentsui/PickerPreviewTextUiTest.java89
-rw-r--r--tests/unit/com/android/documentsui/AbstractActionHandlerTest.java9
-rw-r--r--tests/unit/com/android/documentsui/base/StateTest.java30
-rw-r--r--tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java20
-rw-r--r--tests/unit/com/android/documentsui/picker/ActionHandlerTest.java9
29 files changed, 549 insertions, 28 deletions
diff --git a/res/drawable/circle_button_background.xml b/res/drawable/circle_button_background.xml
new file mode 100644
index 000000000..d5b3c50d1
--- /dev/null
+++ b/res/drawable/circle_button_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid
+ android:color="#66000000"/>
+</shape> \ No newline at end of file
diff --git a/res/drawable/ic_zoom_out.xml b/res/drawable/ic_zoom_out.xml
new file mode 100644
index 000000000..295054a35
--- /dev/null
+++ b/res/drawable/ic_zoom_out.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M15,3l2.3,2.3 -2.89,2.87 1.42,1.42L18.7,6.7 21,9L21,3zM3,9l2.3,-2.3 2.87,2.89 1.42,-1.42L6.7,5.3 9,3L3,3zM9,21l-2.3,-2.3 2.89,-2.87 -1.42,-1.42L5.3,17.3 3,15v6zM21,15l-2.3,2.3 -2.87,-2.89 -1.42,1.42 2.89,2.87L15,21h6z"/>
+</vector>
diff --git a/res/layout-sw720dp/column_headers.xml b/res/layout-sw720dp/column_headers.xml
index d5bcb766f..60be5dc10 100644
--- a/res/layout-sw720dp/column_headers.xml
+++ b/res/layout-sw720dp/column_headers.xml
@@ -31,7 +31,7 @@
android:gravity="center_vertical"
android:minHeight="@dimen/list_item_height"
android:paddingStart="@dimen/list_item_padding"
- android:paddingEnd="@dimen/list_item_padding"
+ android:paddingEnd="@dimen/list_item_width"
android:orientation="horizontal">
<!-- Placeholder for icon -->
<View
@@ -52,7 +52,7 @@
android:id="@android:id/title"
android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_weight="0.375"
+ android:layout_weight="0.4"
android:layout_marginEnd="12dp"
android:focusable="true"
android:gravity="center_vertical"
@@ -66,8 +66,8 @@
android:id="@android:id/summary"
android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_weight="0.25"
- android:layout_marginEnd="12dp"
+ android:layout_weight="0"
+ android:layout_marginEnd="0dp"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
@@ -80,7 +80,7 @@
android:id="@+id/file_type"
android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_weight="0.125"
+ android:layout_weight="0.2"
android:layout_marginEnd="12dp"
android:focusable="true"
android:gravity="center_vertical"
@@ -94,7 +94,7 @@
android:id="@+id/size"
android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_weight="0.125"
+ android:layout_weight="0.2"
android:layout_marginEnd="12dp"
android:focusable="true"
android:gravity="center_vertical"
@@ -108,7 +108,7 @@
android:id="@+id/date"
android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_weight="0.125"
+ android:layout_weight="0.2"
android:layout_marginEnd="12dp"
android:focusable="true"
android:gravity="center_vertical"
diff --git a/res/layout-sw720dp/item_doc_list.xml b/res/layout-sw720dp/item_doc_list.xml
index 98e19f0d1..8f9eccd45 100644
--- a/res/layout-sw720dp/item_doc_list.xml
+++ b/res/layout-sw720dp/item_doc_list.xml
@@ -18,7 +18,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@drawable/list_item_background"
+ android:background="?android:attr/selectableItemBackground"
android:focusable="true"
android:orientation="horizontal" >
@@ -74,15 +74,14 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:orientation="horizontal"
- android:paddingEnd="@dimen/list_item_padding" >
+ android:orientation="horizontal" >
<TextView
android:id="@android:id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
- android:layout_weight="0.375"
+ android:layout_weight="0.4"
android:ellipsize="middle"
android:singleLine="true"
android:textAlignment="viewStart"
@@ -93,8 +92,8 @@
android:id="@android:id/summary"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginEnd="12dp"
- android:layout_weight="0.25"
+ android:layout_marginEnd="0dp"
+ android:layout_weight="0"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
@@ -106,7 +105,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
- android:layout_weight="0.125"
+ android:layout_weight="0.2"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
@@ -118,7 +117,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
- android:layout_weight="0.125"
+ android:layout_weight="0.2"
android:ellipsize="end"
android:minWidth="70dp"
android:singleLine="true"
@@ -131,7 +130,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
- android:layout_weight="0.125"
+ android:layout_weight="0.2"
android:ellipsize="end"
android:minWidth="70dp"
android:singleLine="true"
@@ -139,6 +138,34 @@
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorSecondary" />
</LinearLayout>
+
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <FrameLayout
+ android:id="@+id/preview_icon"
+ android:layout_width="@dimen/list_item_width"
+ android:layout_height="@dimen/list_item_height"
+ android:padding="@dimen/list_item_icon_padding"
+ android:focusable="true">
+
+ <ImageView
+ android:layout_width="@dimen/check_icon_size"
+ android:layout_height="@dimen/check_icon_size"
+ android:layout_gravity="center"
+ android:scaleType="fitCenter"
+ android:tint="?android:attr/textColorPrimary"
+ android:src="@drawable/ic_zoom_out"/>
+
+ </FrameLayout>
+
+ <android.widget.Space
+ android:layout_width="@dimen/list_item_width"
+ android:layout_height="@dimen/list_item_height"/>
+
+ </FrameLayout>
+
</LinearLayout>
</LinearLayout> \ No newline at end of file
diff --git a/res/layout/item_dir_grid.xml b/res/layout/item_dir_grid.xml
index 4b6f65967..000790e12 100644
--- a/res/layout/item_dir_grid.xml
+++ b/res/layout/item_dir_grid.xml
@@ -23,6 +23,7 @@
decide to rip these out, please be sure to check out focus and keyboards. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/item_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
diff --git a/res/layout/item_doc_grid.xml b/res/layout/item_doc_grid.xml
index ddd3acba4..ed369ef8d 100644
--- a/res/layout/item_doc_grid.xml
+++ b/res/layout/item_doc_grid.xml
@@ -22,6 +22,7 @@
decide to rip these out, please be sure to check out focus and keyboards. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/item_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
@@ -68,6 +69,28 @@
</FrameLayout>
+ <FrameLayout
+ android:id="@+id/preview_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="4dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentEnd="true"
+ android:background="@drawable/circle_button_background"
+ android:pointerIcon="hand"
+ android:focusable="true"
+ android:clickable="true">
+
+ <ImageView
+ android:layout_width="@dimen/zoom_icon_size"
+ android:layout_height="@dimen/zoom_icon_size"
+ android:layout_margin="2dp"
+ android:layout_gravity="center"
+ android:scaleType="fitCenter"
+ android:src="@drawable/ic_zoom_out"/>
+
+ </FrameLayout>
+
<!-- Item nameplate. Has a mime-type icon and some text fields (title,
size, mod-time, etc). -->
diff --git a/res/layout/item_doc_list.xml b/res/layout/item_doc_list.xml
index 6b929b293..d8f3d3425 100644
--- a/res/layout/item_doc_list.xml
+++ b/res/layout/item_doc_list.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/item_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
@@ -96,7 +98,7 @@
<TextView
android:id="@+id/date"
- android:layout_width="90dp"
+ android:layout_width="70dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
@@ -105,7 +107,7 @@
<TextView
android:id="@+id/size"
- android:layout_width="90dp"
+ android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
@@ -115,7 +117,7 @@
<TextView
android:id="@+id/file_type"
- android:layout_width="90dp"
+ android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
@@ -135,6 +137,25 @@
android:textAppearance="@android:style/TextAppearance.Material.Caption"/>
</LinearLayout>
</LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/preview_icon"
+ android:layout_width="@dimen/list_item_width"
+ android:layout_height="@dimen/list_item_height"
+ android:padding="@dimen/list_item_icon_padding"
+ android:focusable="true"
+ android:clickable="true">
+
+ <ImageView
+ android:layout_width="@dimen/check_icon_size"
+ android:layout_height="@dimen/check_icon_size"
+ android:layout_gravity="center"
+ android:scaleType="fitCenter"
+ android:tint="?android:attr/textColorPrimary"
+ android:src="@drawable/ic_zoom_out"/>
+
+ </FrameLayout>
+
</LinearLayout>
</LinearLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index bc3ab5f65..b3dfd1a6b 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -22,6 +22,7 @@
<dimen name="root_icon_margin">0dp</dimen>
<dimen name="root_spacer_padding">0dp</dimen>
<dimen name="check_icon_size">30dp</dimen>
+ <dimen name="zoom_icon_size">22dp</dimen>
<dimen name="list_item_thumbnail_size">40dp</dimen>
<dimen name="grid_item_icon_size">30dp</dimen>
<dimen name="progress_bar_height">4dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5247753f3..5083f51c8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -427,4 +427,6 @@
<!-- Hint on text input field for rename the file or the folder. [CHAR_LIMIT=48] -->
<string name="input_hint_rename">New name</string>
+ <!-- Content description for preivew function. -->
+ <string name="preview_file">Preview the file <xliff:g id="fileName" example="example.jpg">%1$s</xliff:g></string>
</resources>
diff --git a/src/com/android/documentsui/AbstractActionHandler.java b/src/com/android/documentsui/AbstractActionHandler.java
index b6ea20e6b..0eef2d76d 100644
--- a/src/com/android/documentsui/AbstractActionHandler.java
+++ b/src/com/android/documentsui/AbstractActionHandler.java
@@ -349,6 +349,11 @@ public abstract class AbstractActionHandler<T extends FragmentActivity & CommonA
}
}
+ @Override
+ public boolean previewItem(ItemDetails<String> doc) {
+ throw new UnsupportedOperationException("Can't handle preview.");
+ }
+
private void openFolderInSearchResult(@Nullable DocumentStack stack, DocumentInfo doc) {
if (stack == null) {
mState.stack.popToRootDocument();
diff --git a/src/com/android/documentsui/ActionHandler.java b/src/com/android/documentsui/ActionHandler.java
index 0ff6e34f9..5f74b583e 100644
--- a/src/com/android/documentsui/ActionHandler.java
+++ b/src/com/android/documentsui/ActionHandler.java
@@ -130,6 +130,8 @@ public interface ActionHandler {
void openContainerDocument(DocumentInfo doc);
+ boolean previewItem(ItemDetails<String> doc);
+
void cutToClipboard();
void copyToClipboard();
diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java
index 20d8f0d6f..87438a8db 100644
--- a/src/com/android/documentsui/BaseActivity.java
+++ b/src/com/android/documentsui/BaseActivity.java
@@ -455,6 +455,7 @@ public abstract class BaseActivity
setTitle(mState.stack.getTitle());
invalidateOptionsMenu();
+ mSortController.onViewModeChanged(mState.derivedMode);
}
private final List<String> getExcludedAuthorities() {
diff --git a/src/com/android/documentsui/base/State.java b/src/com/android/documentsui/base/State.java
index a2e5ba3a2..bd4d86273 100644
--- a/src/com/android/documentsui/base/State.java
+++ b/src/com/android/documentsui/base/State.java
@@ -115,6 +115,16 @@ public class State implements android.os.Parcelable {
}
}
+ /**
+ * Check current action should have preview function or not.
+ * @return True, if the action should have preview.
+ */
+ public boolean shouldShowPreview() {
+ return action == ACTION_GET_CONTENT
+ || action == ACTION_OPEN_TREE
+ || action == ACTION_OPEN;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/src/com/android/documentsui/dirlist/DirectoryFragment.java b/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 2171f8601..064cb35be 100644
--- a/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -489,6 +489,10 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On
}
private boolean onItemActivated(ItemDetails<String> item, MotionEvent e) {
+ if (((DocumentItemDetails) item).inPreviewIconHotspot(e)) {
+ return mActions.previewItem(item);
+ }
+
return mActions.openItem(
item,
ActionHandler.VIEW_TYPE_PREVIEW,
diff --git a/src/com/android/documentsui/dirlist/DocumentHolder.java b/src/com/android/documentsui/dirlist/DocumentHolder.java
index c1c5c1ee3..41257cce9 100644
--- a/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -18,6 +18,7 @@ package com.android.documentsui.dirlist;
import android.content.Context;
import android.database.Cursor;
+import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -26,10 +27,14 @@ import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.widget.ImageView;
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.android.documentsui.base.Shared;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
import javax.annotation.Nullable;
/**
@@ -94,6 +99,8 @@ public abstract class DocumentHolder
setEnabledRecursive(itemView, enabled);
}
+ public void bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback) {}
+
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
assert(mKeyEventListener != null);
@@ -124,6 +131,10 @@ public abstract class DocumentHolder
return false;
}
+ public boolean inPreviewIconRegion(MotionEvent event) {
+ return false;
+ }
+
public DocumentItemDetails getItemDetails() {
return mDetails;
}
@@ -151,4 +162,21 @@ public abstract class DocumentHolder
static ViewPropertyAnimator fade(ImageView view, float alpha) {
return view.animate().setDuration(Shared.CHECK_ANIMATION_DURATION).alpha(alpha);
}
+
+ protected static class PreviewAccessibilityDelegate extends View.AccessibilityDelegate {
+ private Function<View, Boolean> mCallback;
+
+ public PreviewAccessibilityDelegate(Function<View, Boolean> clickCallback) {
+ super();
+ mCallback = clickCallback;
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
+ return mCallback.apply(host);
+ }
+ return super.performAccessibilityAction(host, action, args);
+ }
+ }
}
diff --git a/src/com/android/documentsui/dirlist/DocumentItemDetails.java b/src/com/android/documentsui/dirlist/DocumentItemDetails.java
index bf6d7ddd5..ab8644836 100644
--- a/src/com/android/documentsui/dirlist/DocumentItemDetails.java
+++ b/src/com/android/documentsui/dirlist/DocumentItemDetails.java
@@ -56,4 +56,8 @@ public final class DocumentItemDetails extends ItemDetails<String> {
public boolean inSelectionHotspot(MotionEvent e) {
return mDocumentHolder.inSelectRegion(e);
}
+
+ public boolean inPreviewIconHotspot(MotionEvent e) {
+ return mDocumentHolder.inPreviewIconRegion(e);
+ }
}
diff --git a/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/src/com/android/documentsui/dirlist/GridDocumentHolder.java
index e89e6963e..e27d21097 100644
--- a/src/com/android/documentsui/dirlist/GridDocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/GridDocumentHolder.java
@@ -37,6 +37,8 @@ import com.android.documentsui.base.Shared;
import com.android.documentsui.roots.RootCursorWrapper;
import com.android.documentsui.ui.Views;
+import java.util.function.Function;
+
final class GridDocumentHolder extends DocumentHolder {
final TextView mTitle;
@@ -48,6 +50,7 @@ final class GridDocumentHolder extends DocumentHolder {
final ImageView mIconCheck;
final IconHelper mIconHelper;
final View mIconLayout;
+ final View mPreviewIcon;
// This is used in as a convenience in our bind method.
private final DocumentInfo mDoc = new DocumentInfo();
@@ -63,6 +66,7 @@ final class GridDocumentHolder extends DocumentHolder {
mIconMimeSm = (ImageView) itemView.findViewById(R.id.icon_mime_sm);
mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb);
mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check);
+ mPreviewIcon = itemView.findViewById(R.id.preview_icon);
mIconHelper = iconHelper;
}
@@ -107,6 +111,16 @@ final class GridDocumentHolder extends DocumentHolder {
}
@Override
+ public void bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback) {
+ mPreviewIcon.setVisibility(show ? View.VISIBLE : View.GONE);
+ if (show) {
+ mPreviewIcon.setContentDescription(
+ itemView.getResources().getString(R.string.preview_file, mDoc.displayName));
+ mPreviewIcon.setAccessibilityDelegate(new PreviewAccessibilityDelegate(clickCallback));
+ }
+ }
+
+ @Override
public boolean inDragRegion(MotionEvent event) {
// Entire grid box should be draggable
return true;
@@ -117,6 +131,11 @@ final class GridDocumentHolder extends DocumentHolder {
return Views.isEventOver(event, mIconLayout);
}
+ @Override
+ public boolean inPreviewIconRegion(MotionEvent event) {
+ return Views.isEventOver(event, mPreviewIcon);
+ }
+
/**
* Bind this view to the given document for display.
* @param cursor Pointing to the item to be bound.
diff --git a/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index a33aa9a6e..5232f26f7 100644
--- a/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -37,6 +37,8 @@ import com.android.documentsui.base.Shared;
import com.android.documentsui.roots.RootCursorWrapper;
import com.android.documentsui.ui.Views;
+import java.util.function.Function;
+
final class ListDocumentHolder extends DocumentHolder {
private final TextView mTitle;
@@ -49,6 +51,7 @@ final class ListDocumentHolder extends DocumentHolder {
private final ImageView mIconThumb;
private final ImageView mIconCheck;
private final View mIconLayout;
+ final View mPreviewIcon;
private final IconHelper mIconHelper;
private final Lookup<String, String> mFileTypeLookup;
@@ -70,6 +73,7 @@ final class ListDocumentHolder extends DocumentHolder {
mType = (TextView) itemView.findViewById(R.id.file_type);
// Warning: mDetails view doesn't exists in layout-sw720dp-land layout
mDetails = (LinearLayout) itemView.findViewById(R.id.line2);
+ mPreviewIcon = itemView.findViewById(R.id.preview_icon);
mIconHelper = iconHelper;
mFileTypeLookup = fileTypeLookup;
@@ -115,6 +119,21 @@ final class ListDocumentHolder extends DocumentHolder {
}
@Override
+ public void bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback) {
+ if (mDoc.isDirectory()) {
+ mPreviewIcon.setVisibility(View.GONE);
+ } else {
+ mPreviewIcon.setVisibility(show ? View.VISIBLE : View.GONE);
+ if (show) {
+ mPreviewIcon.setContentDescription(
+ itemView.getResources().getString(R.string.preview_file, mDoc.displayName));
+ mPreviewIcon.setAccessibilityDelegate(
+ new PreviewAccessibilityDelegate(clickCallback));
+ }
+ }
+ }
+
+ @Override
public boolean inDragRegion(MotionEvent event) {
// If itemView is activated = selected, then whole region is interactive
if (itemView.isActivated()) {
@@ -144,6 +163,11 @@ final class ListDocumentHolder extends DocumentHolder {
return Views.isEventOver(event, mIconLayout);
}
+ @Override
+ public boolean inPreviewIconRegion(MotionEvent event) {
+ return Views.isEventOver(event, mPreviewIcon);
+ }
+
/**
* Bind this view to the given document for display.
* @param cursor Pointing to the item to be bound.
diff --git a/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index 604badf4f..08f15221c 100644
--- a/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -136,6 +136,8 @@ final class ModelBackedDocumentsAdapter extends DocumentsAdapter {
}
holder.setEnabled(enabled);
holder.setSelected(mEnv.isSelected(modelId), false);
+ holder.bindPreviewIcon(mEnv.getDisplayState().shouldShowPreview() && enabled,
+ view -> mEnv.getActionHandler().previewItem(holder.getItemDetails()));
mEnv.onBindDocumentHolder(holder, cursor);
}
diff --git a/src/com/android/documentsui/files/ActionHandler.java b/src/com/android/documentsui/files/ActionHandler.java
index 5ade6b1ea..af48af069 100644
--- a/src/com/android/documentsui/files/ActionHandler.java
+++ b/src/com/android/documentsui/files/ActionHandler.java
@@ -611,7 +611,8 @@ public class ActionHandler<T extends FragmentActivity & Addons> extends Abstract
mActivity.getPackageManager(),
mActivity.getResources(),
doc,
- mModel).build();
+ mModel,
+ false /* fromPicker */).build();
if (intent != null) {
// TODO: un-work around issue b/24963914. Should be fixed soon.
diff --git a/src/com/android/documentsui/files/QuickViewIntentBuilder.java b/src/com/android/documentsui/files/QuickViewIntentBuilder.java
index 7a7245d10..f7d757117 100644
--- a/src/com/android/documentsui/files/QuickViewIntentBuilder.java
+++ b/src/com/android/documentsui/files/QuickViewIntentBuilder.java
@@ -67,6 +67,9 @@ public final class QuickViewIntentBuilder {
QuickViewConstants.FEATURE_DOWNLOAD,
QuickViewConstants.FEATURE_PRINT
};
+ private static final String[] PICKER_FEATURES = {
+ QuickViewConstants.FEATURE_VIEW
+ };
private final DocumentInfo mDocument;
private final Model mModel;
@@ -74,11 +77,14 @@ public final class QuickViewIntentBuilder {
private final PackageManager mPackageMgr;
private final Resources mResources;
+ private final boolean mFromPicker;
+
public QuickViewIntentBuilder(
PackageManager packageMgr,
Resources resources,
DocumentInfo doc,
- Model model) {
+ Model model,
+ boolean fromPicker) {
assert(packageMgr != null);
assert(resources != null);
@@ -89,13 +95,14 @@ public final class QuickViewIntentBuilder {
mResources = resources;
mDocument = doc;
mModel = model;
+ mFromPicker = fromPicker;
}
/**
* Builds the intent for quick viewing. Short circuits building if a handler cannot
* be resolved; in this case {@code null} is returned.
*/
- @Nullable Intent build() {
+ @Nullable public Intent build() {
if (DEBUG) Log.d(TAG, "Preparing intent for doc:" + mDocument.documentId);
String trustedPkg = getQuickViewPackage();
@@ -107,7 +114,7 @@ public final class QuickViewIntentBuilder {
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setPackage(trustedPkg);
if (hasRegisteredHandler(intent)) {
- includeQuickViewFeaturesFlag(intent, mDocument);
+ includeQuickViewFeaturesFlag(intent, mDocument, mFromPicker);
final ArrayList<Uri> uris = new ArrayList<>();
final int documentLocation = collectViewableUris(uris);
@@ -213,10 +220,12 @@ public final class QuickViewIntentBuilder {
return intent.resolveActivity(mPackageMgr) != null;
}
- private static void includeQuickViewFeaturesFlag(Intent intent, DocumentInfo doc) {
+ private static void includeQuickViewFeaturesFlag(Intent intent, DocumentInfo doc,
+ boolean fromPicker) {
intent.putExtra(
Intent.EXTRA_QUICK_VIEW_FEATURES,
- doc.isInArchive() ? IN_ARCHIVE_FEATURES : FULL_FEATURES);
+ doc.isInArchive() ? IN_ARCHIVE_FEATURES
+ : fromPicker ? PICKER_FEATURES : FULL_FEATURES);
}
private static Range<Integer> computeSiblingsRange(List<Uri> uris, int documentLocation) {
diff --git a/src/com/android/documentsui/picker/ActionHandler.java b/src/com/android/documentsui/picker/ActionHandler.java
index 1a1bcb057..4438e12d9 100644
--- a/src/com/android/documentsui/picker/ActionHandler.java
+++ b/src/com/android/documentsui/picker/ActionHandler.java
@@ -26,6 +26,7 @@ import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.QuickViewConstants;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.AsyncTask;
@@ -53,6 +54,7 @@ import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.Shared;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.AnimationView;
+import com.android.documentsui.files.QuickViewIntentBuilder;
import com.android.documentsui.picker.ActionHandler.Addons;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.roots.ProvidersAccess;
@@ -70,6 +72,9 @@ import javax.annotation.Nullable;
class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionHandler<T> {
private static final String TAG = "PickerActionHandler";
+ private static final String[] PREVIEW_FEATURES = {
+ QuickViewConstants.FEATURE_VIEW
+ };
private final Features mFeatures;
private final ActivityConfig mConfig;
@@ -269,6 +274,40 @@ class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionH
return false;
}
+ @Override
+ public boolean previewItem(ItemDetails<String> details) {
+ final DocumentInfo doc = mModel.getDocument(details.getSelectionKey());
+ if (doc == null) {
+ Log.w(TAG, "Can't view item. No Document available for modeId: "
+ + details.getSelectionKey());
+ return false;
+ }
+ return priviewDocument(doc);
+
+ }
+
+ @VisibleForTesting
+ boolean priviewDocument(DocumentInfo doc) {
+ Intent intent = new QuickViewIntentBuilder(
+ mActivity.getPackageManager(),
+ mActivity.getResources(),
+ doc,
+ mModel,
+ true /* fromPicker */).build();
+
+ if (intent != null) {
+ try {
+ mActivity.startActivity(intent);
+ return true;
+ } catch (SecurityException e) {
+ Log.e(TAG, "Caught security error: " + e.getLocalizedMessage());
+ }
+ } else {
+ Log.e(TAG, "Quick view intetn is null");
+ }
+ return false;
+ }
+
void pickDocument(DocumentInfo pickTarget) {
assert(pickTarget != null);
Uri result;
diff --git a/tests/common/com/android/documentsui/bots/DirectoryListBot.java b/tests/common/com/android/documentsui/bots/DirectoryListBot.java
index cb287dbff..665c0ac18 100644
--- a/tests/common/com/android/documentsui/bots/DirectoryListBot.java
+++ b/tests/common/com/android/documentsui/bots/DirectoryListBot.java
@@ -54,6 +54,10 @@ import java.util.regex.Pattern;
public class DirectoryListBot extends Bots.BaseBot {
private static final String DIR_CONTAINER_ID = "com.android.documentsui:id/container_directory";
private static final String DIR_LIST_ID = "com.android.documentsui:id/dir_list";
+ private static final String ITEM_ROOT_ID = "com.android.documentsui:id/item_root";
+ private static final String PREVIEW_ID = "com.android.documentsui:id/preview_icon";
+
+ private static final int MAX_LAYOUT_LEVEL = 10;
private static final BySelector SNACK_DELETE =
By.text(Pattern.compile("^Deleting [0-9]+ item.+"));
@@ -273,6 +277,21 @@ public class DirectoryListBot extends Bots.BaseBot {
return true;
}
+ public boolean hasDocumentPreview(String label) {
+ final BySelector list = By.res(DIR_LIST_ID);
+ final UiObject2 text = mDevice.findObject(list).findObject(By.text(label));
+
+ UiObject2 parent = text;
+ for (int i = 1; i <= MAX_LAYOUT_LEVEL; i++) {
+ parent = parent.getParent();
+ if (ITEM_ROOT_ID.equals(parent.getResourceName())) {
+ break;
+ }
+ }
+
+ return parent.hasObject(By.res(PREVIEW_ID));
+ }
+
public void assertFirstDocumentHasFocus() throws UiObjectNotFoundException {
final UiSelector docList = new UiSelector().resourceId(
DIR_CONTAINER_ID).childSelector(
diff --git a/tests/functional/com/android/documentsui/PickerPreviewAllTypeUiTest.java b/tests/functional/com/android/documentsui/PickerPreviewAllTypeUiTest.java
new file mode 100644
index 000000000..fdd9cc55f
--- /dev/null
+++ b/tests/functional/com/android/documentsui/PickerPreviewAllTypeUiTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.content.Intent;
+import android.provider.DocumentsContract;
+
+import androidx.test.filters.LargeTest;
+
+import com.android.documentsui.bots.UiBot;
+import com.android.documentsui.picker.PickActivity;
+
+@LargeTest
+public class PickerPreviewAllTypeUiTest extends ActivityTest<PickActivity> {
+
+ public PickerPreviewAllTypeUiTest() {
+ super(PickActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ initTestFiles();
+ }
+
+ @Override
+ protected void launchActivity() {
+ final Intent intent = context.getPackageManager().getLaunchIntentForPackage(
+ UiBot.TARGET_PKG);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setAction(Intent.ACTION_GET_CONTENT);
+ if (getInitialRoot() != null) {
+ intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, getInitialRoot().getUri());
+ }
+ intent.setType("*/*");
+ setActivityIntent(intent);
+ getActivity(); // Launch the activity.
+ }
+
+ public void testPreviewInvisible_directory_gridMode() throws Exception {
+ bots.main.switchToGridMode();
+ assertTrue(bots.directory.findDocument(dirName1).isEnabled());
+ assertFalse(bots.directory.hasDocumentPreview(dirName1));
+ }
+
+ public void testPreviewInvisible_directory_listMode() throws Exception {
+ bots.main.switchToListMode();
+ assertTrue(bots.directory.findDocument(dirName1).isEnabled());
+ assertFalse(bots.directory.hasDocumentPreview(dirName1));
+ }
+
+ public void testPreviewVisible_allType_girdMode() throws Exception {
+ bots.main.switchToGridMode();
+ assertTrue(bots.directory.findDocument(fileName1).isEnabled());
+ assertTrue(bots.directory.hasDocumentPreview(fileName1));
+ assertTrue(bots.directory.findDocument(fileName2).isEnabled());
+ assertTrue(bots.directory.hasDocumentPreview(fileName2));
+ }
+
+ public void testPreviewVisible_allType_listMode() throws Exception {
+ bots.main.switchToListMode();
+ assertTrue(bots.directory.findDocument(fileName1).isEnabled());
+ assertTrue(bots.directory.hasDocumentPreview(fileName1));
+ assertTrue(bots.directory.findDocument(fileName2).isEnabled());
+ assertTrue(bots.directory.hasDocumentPreview(fileName2));
+ }
+}
diff --git a/tests/functional/com/android/documentsui/PickerPreviewTextUiTest.java b/tests/functional/com/android/documentsui/PickerPreviewTextUiTest.java
new file mode 100644
index 000000000..501a9283a
--- /dev/null
+++ b/tests/functional/com/android/documentsui/PickerPreviewTextUiTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.content.Intent;
+import android.provider.DocumentsContract;
+
+import androidx.test.filters.LargeTest;
+
+import com.android.documentsui.bots.UiBot;
+import com.android.documentsui.picker.PickActivity;
+
+@LargeTest
+public class PickerPreviewTextUiTest extends ActivityTest<PickActivity>{
+
+ public PickerPreviewTextUiTest() {
+ super(PickActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ initTestFiles();
+ }
+
+ @Override
+ protected void launchActivity() {
+ final Intent intent = context.getPackageManager().getLaunchIntentForPackage(
+ UiBot.TARGET_PKG);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setAction(Intent.ACTION_GET_CONTENT);
+ if (getInitialRoot() != null) {
+ intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, getInitialRoot().getUri());
+ }
+ intent.setType("text/*");
+ setActivityIntent(intent);
+ getActivity(); // Launch the activity.
+ }
+
+ public void testPreviewInvisible_disabled_gridMode() throws Exception {
+ bots.main.switchToGridMode();
+ assertFalse(bots.directory.findDocument(fileName2).isEnabled());
+ assertFalse(bots.directory.hasDocumentPreview(fileName2));
+ }
+
+ public void testPreviewInvisible_disabled_listMode() throws Exception {
+ bots.main.switchToListMode();
+ assertFalse(bots.directory.findDocument(fileName2).isEnabled());
+ assertFalse(bots.directory.hasDocumentPreview(fileName2));
+ }
+
+ public void testPreviewInvisible_directory_gridMode() throws Exception {
+ bots.main.switchToGridMode();
+ assertTrue(bots.directory.findDocument(dirName1).isEnabled());
+ assertFalse(bots.directory.hasDocumentPreview(dirName1));
+ }
+
+ public void testPreviewInvisible_directory_listMode() throws Exception {
+ bots.main.switchToListMode();
+ assertTrue(bots.directory.findDocument(dirName1).isEnabled());
+ assertFalse(bots.directory.hasDocumentPreview(dirName1));
+ }
+
+ public void testPreviewVisible_enabled_gridMode() throws Exception {
+ bots.main.switchToGridMode();
+ assertTrue(bots.directory.findDocument(fileName1).isEnabled());
+ assertTrue(bots.directory.hasDocumentPreview(fileName1));
+ }
+
+ public void testPreviewVisible_enabled_listMode() throws Exception {
+ bots.main.switchToListMode();
+ assertTrue(bots.directory.findDocument(fileName1).isEnabled());
+ assertTrue(bots.directory.hasDocumentPreview(fileName1));
+ }
+}
diff --git a/tests/unit/com/android/documentsui/AbstractActionHandlerTest.java b/tests/unit/com/android/documentsui/AbstractActionHandlerTest.java
index 4012bdd0c..3d1e0dbf9 100644
--- a/tests/unit/com/android/documentsui/AbstractActionHandlerTest.java
+++ b/tests/unit/com/android/documentsui/AbstractActionHandlerTest.java
@@ -285,4 +285,13 @@ public class AbstractActionHandlerTest {
assertTrue(listener.getLastValue().hasException());
}
+
+ @Test
+ public void testPreviewItem_throwException() throws Exception {
+ try {
+ mHandler.previewItem(null);
+ fail("Should have thrown UnsupportedOperationException.");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
}
diff --git a/tests/unit/com/android/documentsui/base/StateTest.java b/tests/unit/com/android/documentsui/base/StateTest.java
index 9631ada2d..06fdfeb1d 100644
--- a/tests/unit/com/android/documentsui/base/StateTest.java
+++ b/tests/unit/com/android/documentsui/base/StateTest.java
@@ -18,6 +18,8 @@ package com.android.documentsui.base;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.content.Intent;
@@ -58,4 +60,32 @@ public class StateTest {
assertArrayEquals(new String[] { MIME_TYPES[0] }, mState.acceptMimes);
}
+
+ @Test
+ public void testShouldShowPreview_actionBrowse() {
+ mState.action = State.ACTION_BROWSE;
+
+ assertFalse(mState.shouldShowPreview());
+ }
+
+ @Test
+ public void testShouldShowPreview_actionOpen() {
+ mState.action = State.ACTION_OPEN;
+
+ assertTrue(mState.shouldShowPreview());
+ }
+
+ @Test
+ public void testShouldShowPreview_actionGetContent() {
+ mState.action = State.ACTION_GET_CONTENT;
+
+ assertTrue(mState.shouldShowPreview());
+ }
+
+ @Test
+ public void testShouldShowPreview_actionOpenTree() {
+ mState.action = State.ACTION_OPEN_TREE;
+
+ assertTrue(mState.shouldShowPreview());
+ }
}
diff --git a/tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java b/tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java
index 95485276d..26355e6e3 100644
--- a/tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java
+++ b/tests/unit/com/android/documentsui/files/QuickViewIntentBuilderTest.java
@@ -42,7 +42,8 @@ public class QuickViewIntentBuilderTest {
@Test
public void testSetsNoFeatures_InArchiveDocument() {
QuickViewIntentBuilder builder =
- new QuickViewIntentBuilder(mPm, mRes, TestEnv.FILE_IN_ARCHIVE, mEnv.archiveModel);
+ new QuickViewIntentBuilder(
+ mPm, mRes, TestEnv.FILE_IN_ARCHIVE, mEnv.archiveModel, false);
Intent intent = builder.build();
@@ -53,7 +54,7 @@ public class QuickViewIntentBuilderTest {
@Test
public void testSetsFullFeatures_RegularDocument() {
QuickViewIntentBuilder builder =
- new QuickViewIntentBuilder(mPm, mRes, TestEnv.FILE_JPG, mEnv.model);
+ new QuickViewIntentBuilder(mPm, mRes, TestEnv.FILE_JPG, mEnv.model, false);
Intent intent = builder.build();
@@ -68,4 +69,19 @@ public class QuickViewIntentBuilderTest {
assertTrue(features.contains(QuickViewConstants.FEATURE_DOWNLOAD));
assertTrue(features.contains(QuickViewConstants.FEATURE_PRINT));
}
+
+ @Test
+ public void testPickerFeatures_RegularDocument() {
+
+ QuickViewIntentBuilder builder =
+ new QuickViewIntentBuilder(mPm, mRes, TestEnv.FILE_JPG, mEnv.model, true);
+
+ Intent intent = builder.build();
+
+ Set<String> features = new HashSet<>(
+ Arrays.asList(intent.getStringArrayExtra(Intent.EXTRA_QUICK_VIEW_FEATURES)));
+
+ assertEquals("Unexpected features set: " + features, 1, features.size());
+ assertTrue(features.contains(QuickViewConstants.FEATURE_VIEW));
+ }
}
diff --git a/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java b/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java
index 69cfa3eb2..ba62e2fa4 100644
--- a/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java
+++ b/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java
@@ -465,6 +465,15 @@ public class ActionHandlerTest {
assertNotNull(mActivity.startActivityForResult.getLastValue().first);
}
+ @Test
+ public void testPreviewItem() throws Exception {
+ mActivity.resources.setQuickViewerPackage("corptropolis.viewer");
+ mActivity.currentRoot = TestProvidersAccess.HOME;
+
+ mHandler.priviewDocument(TestEnv.FILE_GIF);
+ mActivity.assertActivityStarted(Intent.ACTION_QUICK_VIEW);
+ }
+
private void testInitLocationDefaultToRecentsOnAction(@ActionType int action)
throws Exception {
mEnv.state.action = action;