summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2023-02-04 00:19:55 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-02-04 00:19:55 +0000
commit3d094b80389b2386b9f724217ef593dc64a3ca8b (patch)
treed5bd64546039ae0c3cbcb49ad55307b998aec41f /java
parent3fd3c66efa00ed9da270e85753defa666bb9af62 (diff)
parent150f8b476d622b592ce9192aed2e106076f2f67e (diff)
Merge "Enable scrollable image preview view" into tm-qpr-dev
Diffstat (limited to 'java')
-rw-r--r--java/res/layout/chooser_grid_preview_image.xml6
-rw-r--r--java/res/layout/chooser_image_preview_view.xml24
-rw-r--r--java/res/layout/chooser_image_preview_view_internals.xml (renamed from java/res/layout/image_preview_view.xml)0
-rw-r--r--java/res/layout/scrollable_image_preview_view.xml24
-rw-r--r--java/src/com/android/intentresolver/ChooserContentPreviewUi.java17
-rw-r--r--java/src/com/android/intentresolver/flags/Flags.kt6
-rw-r--r--java/src/com/android/intentresolver/widget/ChooserImagePreviewView.kt3
-rw-r--r--java/tests/Android.bp7
-rw-r--r--java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt30
-rw-r--r--java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java134
10 files changed, 194 insertions, 57 deletions
diff --git a/java/res/layout/chooser_grid_preview_image.xml b/java/res/layout/chooser_grid_preview_image.xml
index d43a26de..6af0af11 100644
--- a/java/res/layout/chooser_grid_preview_image.xml
+++ b/java/res/layout/chooser_grid_preview_image.xml
@@ -16,7 +16,6 @@
* limitations under the License.
*/
-->
-<!-- Layout Option: Supporting up to 3 images for preview -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
@@ -32,8 +31,9 @@
android:gravity="center_horizontal"
android:layout_marginBottom="@dimen/chooser_view_spacing">
- <com.android.intentresolver.widget.ChooserImagePreviewView
- android:id="@androidprv:id/content_preview_image_area"
+ <ViewStub
+ android:id="@+id/image_preview_stub"
+ android:inflatedId="@androidprv:id/content_preview_image_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="@dimen/chooser_edge_margin_normal"
diff --git a/java/res/layout/chooser_image_preview_view.xml b/java/res/layout/chooser_image_preview_view.xml
new file mode 100644
index 00000000..a111b923
--- /dev/null
+++ b/java/res/layout/chooser_image_preview_view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<com.android.intentresolver.widget.ChooserImagePreviewView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:paddingBottom="@dimen/chooser_view_spacing"
+ android:background="?android:attr/colorBackground" />
diff --git a/java/res/layout/image_preview_view.xml b/java/res/layout/chooser_image_preview_view_internals.xml
index 8730fc30..8730fc30 100644
--- a/java/res/layout/image_preview_view.xml
+++ b/java/res/layout/chooser_image_preview_view_internals.xml
diff --git a/java/res/layout/scrollable_image_preview_view.xml b/java/res/layout/scrollable_image_preview_view.xml
new file mode 100644
index 00000000..ff2f273f
--- /dev/null
+++ b/java/res/layout/scrollable_image_preview_view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<com.android.intentresolver.widget.ScrollableImagePreviewView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:paddingBottom="@dimen/chooser_view_spacing"
+ android:background="?android:attr/colorBackground" />
diff --git a/java/src/com/android/intentresolver/ChooserContentPreviewUi.java b/java/src/com/android/intentresolver/ChooserContentPreviewUi.java
index 553a36c6..9bef3553 100644
--- a/java/src/com/android/intentresolver/ChooserContentPreviewUi.java
+++ b/java/src/com/android/intentresolver/ChooserContentPreviewUi.java
@@ -363,8 +363,7 @@ public final class ChooserContentPreviewUi {
@LayoutRes int actionRowLayout) {
ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
R.layout.chooser_grid_preview_image, parent, false);
- ImagePreviewView imagePreview = contentPreviewLayout.findViewById(
- com.android.internal.R.id.content_preview_image_area);
+ ImagePreviewView imagePreview = inflateImagePreviewView(contentPreviewLayout);
final ActionRow actionRow = inflateActionRow(contentPreviewLayout, actionRowLayout);
if (actionRow != null) {
@@ -431,6 +430,20 @@ public final class ChooserContentPreviewUi {
return actions;
}
+ private ImagePreviewView inflateImagePreviewView(ViewGroup previewLayout) {
+ ViewStub stub = previewLayout.findViewById(R.id.image_preview_stub);
+ if (stub != null) {
+ int layoutId =
+ mFeatureFlagRepository.isEnabled(Flags.SHARESHEET_SCROLLABLE_IMAGE_PREVIEW)
+ ? R.layout.scrollable_image_preview_view
+ : R.layout.chooser_image_preview_view;
+ stub.setLayoutResource(layoutId);
+ stub.inflate();
+ }
+ return previewLayout.findViewById(
+ com.android.internal.R.id.content_preview_image_area);
+ }
+
private static ViewGroup displayFileContentPreview(
Intent targetIntent,
Resources resources,
diff --git a/java/src/com/android/intentresolver/flags/Flags.kt b/java/src/com/android/intentresolver/flags/Flags.kt
index db00a751..9c206265 100644
--- a/java/src/com/android/intentresolver/flags/Flags.kt
+++ b/java/src/com/android/intentresolver/flags/Flags.kt
@@ -35,6 +35,12 @@ object Flags {
id = 1503, name = "sharesheet_image_text_preview", teamfood = true
)
+ // TODO(b/267355521) Tracking Bug
+ @JvmField
+ val SHARESHEET_SCROLLABLE_IMAGE_PREVIEW = unreleasedFlag(
+ 1504, "sharesheet_scrollable_image_preview"
+ )
+
private fun unreleasedFlag(id: Int, name: String, teamfood: Boolean = false) =
UnreleasedFlag(id, name, "systemui", teamfood)
}
diff --git a/java/src/com/android/intentresolver/widget/ChooserImagePreviewView.kt b/java/src/com/android/intentresolver/widget/ChooserImagePreviewView.kt
index bf10bfaa..ca94a95d 100644
--- a/java/src/com/android/intentresolver/widget/ChooserImagePreviewView.kt
+++ b/java/src/com/android/intentresolver/widget/ChooserImagePreviewView.kt
@@ -57,7 +57,8 @@ class ChooserImagePreviewView : RelativeLayout, ImagePreviewView {
private var transitionStatusElementCallback: TransitionElementStatusCallback? = null
override fun onFinishInflate() {
- LayoutInflater.from(context).inflate(R.layout.image_preview_view, this, true)
+ LayoutInflater.from(context)
+ .inflate(R.layout.chooser_image_preview_view_internals, this, true)
mainImage = requireViewById(IntR.id.content_preview_image_1_large)
secondLargeImage = requireViewById(IntR.id.content_preview_image_2_large)
secondSmallImage = requireViewById(IntR.id.content_preview_image_2_small)
diff --git a/java/tests/Android.bp b/java/tests/Android.bp
index a62c52e6..4e835ec8 100644
--- a/java/tests/Android.bp
+++ b/java/tests/Android.bp
@@ -21,11 +21,12 @@ android_test {
"IntentResolver-core",
"androidx.test.rules",
"androidx.test.ext.junit",
+ "androidx.test.espresso.contrib",
"mockito-target-minus-junit4",
"androidx.test.espresso.core",
- "androidx.lifecycle_lifecycle-common-java8",
- "androidx.lifecycle_lifecycle-extensions",
- "androidx.lifecycle_lifecycle-runtime-ktx",
+ "androidx.lifecycle_lifecycle-common-java8",
+ "androidx.lifecycle_lifecycle-extensions",
+ "androidx.lifecycle_lifecycle-runtime-ktx",
"truth-prebuilt",
"testables",
"testng",
diff --git a/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt b/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt
new file mode 100644
index 00000000..abc24efb
--- /dev/null
+++ b/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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.intentresolver
+
+import com.android.intentresolver.flags.FeatureFlagRepository
+import com.android.systemui.flags.ReleasedFlag
+import com.android.systemui.flags.UnreleasedFlag
+
+internal class TestFeatureFlagRepository(
+ private val overrides: Map<UnreleasedFlag, Boolean>
+) : FeatureFlagRepository {
+ override fun isEnabled(flag: UnreleasedFlag): Boolean =
+ overrides.getOrDefault(flag, flag.default)
+
+ override fun isEnabled(flag: ReleasedFlag): Boolean = flag.default
+}
diff --git a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java
index 2d8a74b9..249dca62 100644
--- a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java
+++ b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java
@@ -90,24 +90,23 @@ import android.util.HashedStringCache;
import android.util.Pair;
import android.util.SparseArray;
import android.view.View;
+import android.view.ViewGroup;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.espresso.contrib.RecyclerViewActions;
import androidx.test.espresso.matcher.BoundedDiagnosingMatcher;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import com.android.intentresolver.ResolverActivity.ResolvedComponentInfo;
import com.android.intentresolver.chooser.DisplayResolveInfo;
-import com.android.intentresolver.flags.FeatureFlagRepository;
import com.android.intentresolver.flags.Flags;
import com.android.intentresolver.shortcuts.ShortcutLoader;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.flags.ReleasedFlag;
-import com.android.systemui.flags.UnreleasedFlag;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
@@ -124,6 +123,7 @@ import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -859,7 +859,7 @@ public class UnbundledChooserActivityTest {
@Test
- public void oneVisibleImagePreview() throws InterruptedException {
+ public void oneVisibleImagePreview() {
Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
+ R.drawable.test320x240);
@@ -884,18 +884,31 @@ public class UnbundledChooserActivityTest {
.thenReturn(resolvedComponentInfos);
mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
waitForIdle();
- onView(withId(com.android.internal.R.id.content_preview_image_1_large))
- .check(matches(isDisplayed()));
- onView(withId(com.android.internal.R.id.content_preview_image_2_large))
- .check(matches(not(isDisplayed())));
- onView(withId(com.android.internal.R.id.content_preview_image_2_small))
- .check(matches(not(isDisplayed())));
- onView(withId(com.android.internal.R.id.content_preview_image_3_small))
- .check(matches(not(isDisplayed())));
+ onView(withId(com.android.internal.R.id.content_preview_image_area))
+ .check((view, exception) -> {
+ if (exception != null) {
+ throw exception;
+ }
+ ViewGroup parent = (ViewGroup) view;
+ ArrayList<View> visibleViews = new ArrayList<>();
+ for (int i = 0, count = parent.getChildCount(); i < count; i++) {
+ View child = parent.getChildAt(i);
+ if (child.getVisibility() == View.VISIBLE) {
+ visibleViews.add(child);
+ }
+ }
+ assertThat(visibleViews.size(), is(1));
+ assertThat(
+ "image preview view is fully visible",
+ isDisplayed().matches(visibleViews.get(0)));
+ });
}
@Test
- public void twoVisibleImagePreview() throws InterruptedException {
+ public void twoVisibleImagePreview() {
+ ChooserActivityOverrideData.getInstance().featureFlagRepository =
+ new TestFeatureFlagRepository(
+ Collections.singletonMap(Flags.SHARESHEET_SCROLLABLE_IMAGE_PREVIEW, false));
Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
+ R.drawable.test320x240);
@@ -932,7 +945,11 @@ public class UnbundledChooserActivityTest {
}
@Test
- public void threeOrMoreVisibleImagePreview() throws InterruptedException {
+ public void threeOrMoreVisibleImagePreview() {
+ ChooserActivityOverrideData.getInstance().featureFlagRepository =
+ new TestFeatureFlagRepository(
+ Collections.singletonMap(
+ Flags.SHARESHEET_SCROLLABLE_IMAGE_PREVIEW, false));
Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
+ R.drawable.test320x240);
@@ -972,20 +989,60 @@ public class UnbundledChooserActivityTest {
}
@Test
- public void testImageAndTextPreview() {
+ public void testManyVisibleImagePreview_ScrollableImagePreview() {
ChooserActivityOverrideData.getInstance().featureFlagRepository =
- new FeatureFlagRepository() {
- @Override
- public boolean isEnabled(@NonNull UnreleasedFlag flag) {
- return Flags.SHARESHEET_IMAGE_AND_TEXT_PREVIEW.equals(flag)
- || flag.getDefault();
- }
+ new TestFeatureFlagRepository(
+ Collections.singletonMap(
+ Flags.SHARESHEET_SCROLLABLE_IMAGE_PREVIEW, true));
+ Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
+ + R.drawable.test320x240);
+
+ ArrayList<Uri> uris = new ArrayList<>();
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
+ ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap();
+ ChooserActivityOverrideData.getInstance().isImageType = true;
+
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
- @Override
- public boolean isEnabled(@NonNull ReleasedFlag flag) {
- return false;
+ when(
+ ChooserActivityOverrideData
+ .getInstance()
+ .resolverListController
+ .getResolversForIntent(
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class)))
+ .thenReturn(resolvedComponentInfos);
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+ onView(withId(com.android.internal.R.id.content_preview_image_area))
+ .perform(RecyclerViewActions.scrollToLastPosition())
+ .check((view, exception) -> {
+ if (exception != null) {
+ throw exception;
}
- };
+ RecyclerView recyclerView = (RecyclerView) view;
+ assertThat(recyclerView.getAdapter().getItemCount(), is(uris.size()));
+ });
+ }
+
+ @Test
+ public void testImageAndTextPreview() {
+ ChooserActivityOverrideData.getInstance().featureFlagRepository =
+ new TestFeatureFlagRepository(
+ Collections.singletonMap(Flags.SHARESHEET_IMAGE_AND_TEXT_PREVIEW, true));
final Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
+ R.drawable.test320x240);
final String sharedText = "text-" + System.currentTimeMillis();
@@ -1723,17 +1780,8 @@ public class UnbundledChooserActivityTest {
@Test
public void testLaunchWithCustomAction() throws InterruptedException {
ChooserActivityOverrideData.getInstance().featureFlagRepository =
- new FeatureFlagRepository() {
- @Override
- public boolean isEnabled(@NonNull UnreleasedFlag flag) {
- return Flags.SHARESHEET_CUSTOM_ACTIONS.equals(flag) || flag.getDefault();
- }
-
- @Override
- public boolean isEnabled(@NonNull ReleasedFlag flag) {
- return false;
- }
- };
+ new TestFeatureFlagRepository(
+ Collections.singletonMap(Flags.SHARESHEET_CUSTOM_ACTIONS, true));
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
when(
ChooserActivityOverrideData
@@ -1787,18 +1835,8 @@ public class UnbundledChooserActivityTest {
@Test
public void testLaunchWithPayloadReselection() throws InterruptedException {
ChooserActivityOverrideData.getInstance().featureFlagRepository =
- new FeatureFlagRepository() {
- @Override
- public boolean isEnabled(@NonNull UnreleasedFlag flag) {
- return Flags.SHARESHEET_RESELECTION_ACTION.equals(flag)
- || flag.getDefault();
- }
-
- @Override
- public boolean isEnabled(@NonNull ReleasedFlag flag) {
- return false;
- }
- };
+ new TestFeatureFlagRepository(
+ Collections.singletonMap(Flags.SHARESHEET_RESELECTION_ACTION, true));
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
when(
ChooserActivityOverrideData