From 33501f3823153799e2b12dfc44eb9d292e106e18 Mon Sep 17 00:00:00 2001 From: Joshua Trask Date: Wed, 15 Dec 2021 18:40:44 -0500 Subject: [PATCH] Decompose ChooserActivityTest for reuse. Prepare build targets and set up design to share test suite across different ChooserActivity subclasses. (This was somewhat tricky because the tests need to use wrapped activities for instrumentation; those activities need to have the same inheritance relationship with ChooserActivity as the chooser-under-test would normally have; and shared test code needs to use a common type to refer to the wrapped activities.) Test: `atest ChooserActivityTest` (modulo standing flakes); also tested a proof-of-concept unbundled version locally (CL to follow). Bug: 202166045 Change-Id: I8dc317ed9fac7195e525d62fdd386dcf11ef7dba --- core/tests/coretests/Android.bp | 36 + .../app/ChooserActivityOverrideData.java | 115 +++ .../internal/app/ChooserActivityTest.java | 977 ++++++++++++------ .../internal/app/ChooserWrapperActivity.java | 109 +- .../android/internal/app/IChooserWrapper.java | 44 + 5 files changed, 884 insertions(+), 397 deletions(-) create mode 100644 core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java create mode 100644 core/tests/coretests/src/com/android/internal/app/IChooserWrapper.java diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp index 32d72b37b8afc..c18a70c5dd2ab 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -138,3 +138,39 @@ java_genrule { "done && " + "$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res", } + +// In addition to running as part of FrameworksCoreTests, we run (a subclass of) +// ChooserActivityTest against the unbundled ChooserActivity implementation in +// //packages/modules/IntentResolver/. The following library provides the +// minimum dependencies required to build that test in the unbundled package. +android_library { + name: "ChooserActivityTestsLib", + visibility: ["//packages/modules/IntentResolver/java/tests:__pkg__"], + + srcs: [ + "src/com/android/internal/app/ChooserActivityLoggerFake.java", + "src/com/android/internal/app/ChooserActivityOverrideData.java", + "src/com/android/internal/app/ChooserActivityTest.java", + "src/com/android/internal/app/ChooserWrapperActivity.java", + "src/com/android/internal/app/IChooserWrapper.java", + "src/com/android/internal/app/MatcherUtils.java", + "src/com/android/internal/app/ResolverDataProvider.java", + ], + + static_libs: [ + "androidx.test.espresso.core", + "androidx.test.ext.junit", + "androidx.test.runner", + "androidx.test.rules", + "mockito-target-minus-junit4", + "truth-prebuilt", + ], + + libs: [ + "android.test.runner", + "android.test.base", + "android.test.mock", + "framework", + "framework-res", + ], +} \ No newline at end of file diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java new file mode 100644 index 0000000000000..499f7a55996b0 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2021 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.internal.app; + +import static org.mockito.Mockito.mock; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.os.UserHandle; + +import com.android.internal.app.chooser.TargetInfo; +import com.android.internal.logging.MetricsLogger; + +import java.util.List; +import java.util.function.Function; + +/** + * Singleton providing overrides to be applied by any {@code IChooserWrapper} used in testing. + * We cannot directly mock the activity created since instrumentation creates it, so instead we use + * this singleton to modify behavior. + */ +public class ChooserActivityOverrideData { + private static ChooserActivityOverrideData sInstance = null; + + public static ChooserActivityOverrideData getInstance() { + if (sInstance == null) { + sInstance = new ChooserActivityOverrideData(); + } + return sInstance; + } + + @SuppressWarnings("Since15") + public Function createPackageManager; + public Function onSafelyStartCallback; + public Function onQueryDirectShareTargets; + public ResolverListController resolverListController; + public ResolverListController workResolverListController; + public Boolean isVoiceInteraction; + public boolean isImageType; + public Cursor resolverCursor; + public boolean resolverForceException; + public Bitmap previewThumbnail; + public MetricsLogger metricsLogger; + public ChooserActivityLogger chooserActivityLogger; + public int alternateProfileSetting; + public Resources resources; + public UserHandle workProfileUserHandle; + public boolean hasCrossProfileIntents; + public boolean isQuietModeEnabled; + public boolean isWorkProfileUserRunning; + public boolean isWorkProfileUserUnlocked; + public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector; + public PackageManager packageManager; + + public void reset() { + onSafelyStartCallback = null; + onQueryDirectShareTargets = null; + isVoiceInteraction = null; + createPackageManager = null; + previewThumbnail = null; + isImageType = false; + resolverCursor = null; + resolverForceException = false; + resolverListController = mock(ResolverListController.class); + workResolverListController = mock(ResolverListController.class); + metricsLogger = mock(MetricsLogger.class); + chooserActivityLogger = new ChooserActivityLoggerFake(); + alternateProfileSetting = 0; + resources = null; + workProfileUserHandle = null; + hasCrossProfileIntents = true; + isQuietModeEnabled = false; + isWorkProfileUserRunning = true; + isWorkProfileUserUnlocked = true; + packageManager = null; + multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() { + @Override + public boolean hasCrossProfileIntents(List intents, int sourceUserId, + int targetUserId) { + return hasCrossProfileIntents; + } + + @Override + public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) { + return isQuietModeEnabled; + } + + @Override + public void requestQuietModeEnabled(boolean enabled, + UserHandle workProfileUserHandle) { + isQuietModeEnabled = enabled; + } + }; + } + + private ChooserActivityOverrideData() {} +} + diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index 45504c0b4a34d..c69cb4b7e302a 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -34,7 +34,6 @@ import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FRO import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER; import static com.android.internal.app.ChooserListAdapter.CALLER_TARGET_SCORE_BOOST; import static com.android.internal.app.ChooserListAdapter.SHORTCUT_TARGET_SCORE_BOOST; -import static com.android.internal.app.ChooserWrapperActivity.sOverrides; import static com.android.internal.app.MatcherUtils.first; import static junit.framework.Assert.assertFalse; @@ -82,6 +81,7 @@ import android.os.UserHandle; import android.provider.DeviceConfig; import android.service.chooser.ChooserTarget; +import androidx.annotation.CallSuper; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; @@ -111,11 +111,29 @@ import java.util.Map; import java.util.function.Function; /** - * Chooser activity instrumentation tests + * Instrumentation tests for chooser activities that derive from the system + * {@code com.android.internal.ChooserActivity}. This class is used directly to test the system + * implementation, but clients can inherit from this test to apply the same suite of chooser tests + * to their own ChooserActivity implementations. Clients should override + * #getConcreteIntentForLaunch() to configure an intent that will launch their concrete + * ChooserActivity subtype. Tests will assume that this subtype implements the IChooserWrapper + * interface, which is only appropriate for testing. Clients will typically create their own + * "ChooserWrapperActivity" by copy-and-pasting the system implementation, parenting to their own + * ChooserActivity subclass instead of directly to the system implementation. Code comments in this + * file provide direction for developers creating derived test suites, and eventually for removing + * the extra complexity once we no longer need to support parallel ChooserActivity implementations. */ @RunWith(Parameterized.class) public class ChooserActivityTest { + /* -------- + * Subclasses should copy the following section verbatim (or alternatively could specify some + * additional @Parameterized.Parameters, as long as the correct parameters are used to + * initialize the ChooserActivityTest). The subclasses should also be @RunWith the + * `Parameterized` runner. + * -------- + */ + private static final Function DEFAULT_PM = pm -> pm; private static final Function NO_APP_PREDICTION_SERVICE_PM = pm -> { @@ -132,6 +150,66 @@ public class ChooserActivityTest { }); } + /* -------- + * Subclasses can override the following methods to customize test behavior. + * -------- + */ + + /** + * Perform any necessary per-test initialization steps (subclasses may add additional steps + * before and/or after calling up to the superclass implementation). + */ + @CallSuper + protected void setup() { + cleanOverrideData(); + } + + /** + * Given an intent that was constructed in a test, perform any additional configuration to + * specify the appropriate concrete ChooserActivity subclass. The activity launched by this + * intent must descend from android.internal.app.ChooserActivity (for our ActivityTestRule), and + * must also implement the android.internal.app.IChooserWrapper interface (since test code will + * assume the ability to make unsafe downcasts). + */ + protected Intent getConcreteIntentForLaunch(Intent clientIntent) { + clientIntent.setClass( + InstrumentationRegistry.getInstrumentation().getTargetContext(), + com.android.internal.app.ChooserWrapperActivity.class); + return clientIntent; + } + + /* -------- + * The code in this section is unorthodox and can be simplified/reverted when we no longer need + * to support the parallel chooser implementations. + * -------- + */ + + // Shared test code references the activity under test as ChooserActivity, the common ancestor + // of any (inheritance-based) chooser implementation. For testing purposes, that activity will + // usually be cast to IChooserWrapper to expose instrumentation. + @Rule + public ActivityTestRule mActivityRule = + new ActivityTestRule<>(ChooserActivity.class, false, false) { + @Override + public ChooserActivity launchActivity(Intent clientIntent) { + return super.launchActivity(getConcreteIntentForLaunch(clientIntent)); + } + }; + + @Before + public final void doPolymorphicSetup() { + // The base class needs a @Before-annotated setup for when it runs against the system + // chooser, while subclasses need to be able to specify their own setup behavior. Notably + // the unbundled chooser, running in user-space, needs to take additional steps before it + // can run #cleanOverrideData() (which writes to DeviceConfig). + setup(); + } + + /* -------- + * Subclasses can ignore the remaining code and inherit the full suite of tests. + * -------- + */ + private static final String TEST_MIME_TYPE = "application/TestType"; private static final int CONTENT_PREVIEW_IMAGE = 1; @@ -140,10 +218,6 @@ public class ChooserActivityTest { private Function mPackageManagerOverride; private int mTestNum; - @Rule - public ActivityTestRule mActivityRule = - new ActivityTestRule<>(ChooserWrapperActivity.class, false, - false); public ChooserActivityTest( int testNum, @@ -153,10 +227,9 @@ public class ChooserActivityTest { mTestNum = testNum; } - @Before public void cleanOverrideData() { - sOverrides.reset(); - sOverrides.createPackageManager = mPackageManagerOverride; + ChooserActivityOverrideData.getInstance().reset(); + ChooserActivityOverrideData.getInstance().createPackageManager = mPackageManagerOverride; DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, SystemUiDeviceConfigFlags.APPLY_SHARING_APP_LIMITS_IN_SYSUI, Boolean.toString(true), @@ -168,10 +241,16 @@ public class ChooserActivityTest { Intent viewIntent = createViewTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule.launchActivity( + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); + final IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity( Intent.createChooser(viewIntent, "chooser test")); waitForIdle(); @@ -185,9 +264,15 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test")); waitForIdle(); onView(withId(R.id.title)).check(matches(withText(R.string.whichSendApplication))); @@ -198,9 +283,15 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.title)) @@ -212,9 +303,15 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntentWithPreview(null, null); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_title)).check(matches(not(isDisplayed()))); @@ -227,9 +324,15 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntentWithPreview(previewTitle, null); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_title)).check(matches(isDisplayed())); @@ -244,9 +347,15 @@ public class ChooserActivityTest { Uri.parse("tel:(+49)12345789")); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_title)).check(matches(isDisplayed())); @@ -259,12 +368,18 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntentWithPreview(previewTitle, Uri.parse("android.resource://com.android.frameworks.coretests/" + com.android.frameworks.coretests.R.drawable.test320x240)); - sOverrides.previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_title)).check(matches(isDisplayed())); @@ -276,19 +391,25 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); assertThat(activity.getAdapter().getCount(), is(2)); onView(withId(R.id.profile_button)).check(doesNotExist()); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -324,19 +445,25 @@ public class ChooserActivityTest { } resolvedComponentInfos.addAll(infosToStack); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); // expect 1 unique targets + 1 group + 4 ranked app targets assertThat(activity.getAdapter().getCount(), is(6)); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -358,27 +485,33 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); UsageStatsManager usm = activity.getUsageStatsManager(); - verify(sOverrides.resolverListController, times(1)) + verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1)) .topK(any(List.class), anyInt()); assertThat(activity.getIsSelected(), is(false)); - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { return true; }; ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0); onView(withText(toChoose.activityInfo.name)) .perform(click()); waitForIdle(); - verify(sOverrides.resolverListController, times(1)) + verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1)) .updateChooserCounts(Mockito.anyString(), anyInt(), Mockito.anyString()); - verify(sOverrides.resolverListController, times(1)) + verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1)) .updateModel(toChoose.activityInfo.getComponentName()); assertThat(activity.getIsSelected(), is(true)); } @@ -386,19 +519,27 @@ public class ChooserActivityTest { @Ignore // b/148158199 @Test public void noResultsFromPackageManager() { - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(null); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(null); Intent sendIntent = createSendTextIntent(); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper wrapper = (IChooserWrapper) activity; + waitForIdle(); assertThat(activity.isFinishing(), is(false)); onView(withId(R.id.empty)).check(matches(isDisplayed())); onView(withId(R.id.profile_pager)).check(matches(not(isDisplayed()))); InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> activity.getAdapter().handlePackagesChanged() + () -> wrapper.getAdapter().handlePackagesChanged() ); // backward compatibility. looks like we finish when data is empty after package change assertThat(activity.isFinishing(), is(true)); @@ -407,19 +548,25 @@ public class ChooserActivityTest { @Test public void autoLaunchSingleResult() throws InterruptedException { ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; List resolvedComponentInfos = createResolvedComponentsForTest(1); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); Intent sendIntent = createSendTextIntent(); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0))); @@ -438,15 +585,15 @@ public class ChooserActivityTest { ResolveInfo toChoose = personalResolvedComponentInfos.get(1).getResolveInfoAt(0); Intent sendIntent = createSendTextIntent(); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); // The other entry is filtered to the other profile slot assertThat(activity.getAdapter().getCount(), is(1)); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -473,22 +620,22 @@ public class ChooserActivityTest { createResolvedComponentsForTestWithOtherProfile(3); ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0); - when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent( + when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent( Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); - when(ChooserWrapperActivity.sOverrides.resolverListController.getLastChosen()) + when(ChooserActivityOverrideData.getInstance().resolverListController.getLastChosen()) .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0)); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); // The other entry is filtered to the other profile slot assertThat(activity.getAdapter().getCount(), is(2)); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -512,20 +659,20 @@ public class ChooserActivityTest { createResolvedComponentsForTestWithOtherProfile(3); ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0); - when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent( + when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent( Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); // The other entry is filtered to the last used slot assertThat(activity.getAdapter().getCount(), is(2)); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -544,13 +691,13 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent( + when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent( Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed())); @@ -571,16 +718,15 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent( + when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent( Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); - MetricsLogger mockLogger = sOverrides.metricsLogger; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed())); @@ -600,13 +746,13 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent( + when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent( Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.chooser_nearby_button)).check(matches(isDisplayed())); @@ -664,18 +810,18 @@ public class ChooserActivityTest { Uri.parse("android.resource://com.android.frameworks.coretests/" + com.android.frameworks.coretests.R.drawable.test320x240)); - sOverrides.previewThumbnail = createBitmap(); - sOverrides.isImageType = true; + ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().isImageType = true; List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent( + when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent( Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.chooser_edit_button)).check(matches(isDisplayed())); @@ -735,14 +881,20 @@ public class ChooserActivityTest { uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); - sOverrides.previewThumbnail = createBitmap(); - sOverrides.isImageType = true; + ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().isImageType = true; List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); @@ -761,14 +913,20 @@ public class ChooserActivityTest { uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); - sOverrides.previewThumbnail = createBitmap(); - sOverrides.isImageType = true; + ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().isImageType = true; List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); @@ -790,14 +948,20 @@ public class ChooserActivityTest { uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); - sOverrides.previewThumbnail = createBitmap(); - sOverrides.isImageType = true; + ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().isImageType = true; List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); @@ -811,7 +975,7 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - MetricsLogger mockLogger = sOverrides.metricsLogger; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test")); waitForIdle(); @@ -836,8 +1000,9 @@ public class ChooserActivityTest { public void testOnCreateLoggingFromWorkProfile() { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - sOverrides.alternateProfileSetting = MetricsEvent.MANAGED_PROFILE; - MetricsLogger mockLogger = sOverrides.metricsLogger; + ChooserActivityOverrideData.getInstance().alternateProfileSetting = + MetricsEvent.MANAGED_PROFILE; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test")); waitForIdle(); @@ -862,7 +1027,7 @@ public class ChooserActivityTest { public void testEmptyPreviewLogging() { Intent sendIntent = createSendTextIntentWithPreview(null, null); - MetricsLogger mockLogger = sOverrides.metricsLogger; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); mActivityRule.launchActivity(Intent.createChooser(sendIntent, "empty preview logger test")); waitForIdle(); @@ -877,12 +1042,12 @@ public class ChooserActivityTest { public void testTitlePreviewLogging() { Intent sendIntent = createSendTextIntentWithPreview("TestTitle", null); - MetricsLogger mockLogger = sOverrides.metricsLogger; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent( + when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent( Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); @@ -906,16 +1071,22 @@ public class ChooserActivityTest { uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); - sOverrides.previewThumbnail = createBitmap(); - sOverrides.isImageType = true; + ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().isImageType = true; List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - MetricsLogger mockLogger = sOverrides.metricsLogger; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); @@ -938,9 +1109,15 @@ public class ChooserActivityTest { List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed())); @@ -962,9 +1139,15 @@ public class ChooserActivityTest { List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed())); @@ -982,11 +1165,17 @@ public class ChooserActivityTest { Intent sendIntent = createSendUriIntentWithPreview(uris); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - sOverrides.resolverForceException = true; + ChooserActivityOverrideData.getInstance().resolverForceException = true; mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); @@ -1006,9 +1195,15 @@ public class ChooserActivityTest { Intent sendIntent = createSendUriIntentWithPreview(uris); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); Cursor cursor = mock(Cursor.class); when(cursor.getCount()).thenReturn(1); @@ -1016,7 +1211,7 @@ public class ChooserActivityTest { when(cursor.moveToFirst()).thenReturn(true); when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1); - sOverrides.resolverCursor = cursor; + ChooserActivityOverrideData.getInstance().resolverCursor = cursor; mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); @@ -1032,14 +1227,24 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); - when(sOverrides.resolverListController.getScore(Mockito.isA(DisplayResolveInfo.class))) + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getScore(Mockito.isA(DisplayResolveInfo.class))) .thenReturn(testBaseScore); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); final DisplayResolveInfo testDri = @@ -1066,12 +1271,18 @@ public class ChooserActivityTest { public void testIsAppPredictionServiceAvailable() { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); if (activity.getPackageManager().getAppPredictionServicePackageName() == null) { @@ -1079,8 +1290,13 @@ public class ChooserActivityTest { } else { assertThat(activity.isAppPredictionServiceAvailable(), is(true)); - sOverrides.resources = Mockito.spy(activity.getResources()); - when(sOverrides.resources.getString(R.string.config_defaultAppPredictionService)) + ChooserActivityOverrideData.getInstance().resources = + Mockito.spy(activity.getResources()); + when( + ChooserActivityOverrideData + .getInstance() + .resources + .getString(R.string.config_defaultAppPredictionService)) .thenReturn("ComponentNameThatDoesNotExist"); assertThat(activity.isAppPredictionServiceAvailable(), is(false)); @@ -1091,12 +1307,18 @@ public class ChooserActivityTest { public void testConvertToChooserTarget_predictionService() { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); List shortcuts = createShortcuts(activity); @@ -1127,12 +1349,18 @@ public class ChooserActivityTest { public void testConvertToChooserTarget_shortcutManager() { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); List shortcuts = createShortcuts(activity); @@ -1165,20 +1393,26 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); // We need app targets for direct targets to get displayed List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); // Set up resources - MetricsLogger mockLogger = sOverrides.metricsLogger; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); // Create direct share target List serviceTargets = createDirectShareTargets(1, ""); ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0); // Start activity - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); // Insert the direct share target Map directShareToShortcutInfos = new HashMap<>(); @@ -1235,12 +1469,18 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); // We need app targets for direct targets to get displayed List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); // Set up resources - MetricsLogger mockLogger = sOverrides.metricsLogger; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); // Create direct share target List serviceTargets = createDirectShareTargets(1, @@ -1248,8 +1488,8 @@ public class ChooserActivityTest { ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0); // Start activity - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); // Insert the direct share target Map directShareToShortcutInfos = new HashMap<>(); @@ -1298,24 +1538,35 @@ public class ChooserActivityTest { @Test @Ignore public void testShortcutTargetWithApplyAppLimits() throws InterruptedException { // Set up resources - sOverrides.resources = Mockito.spy( + ChooserActivityOverrideData.getInstance().resources = Mockito.spy( InstrumentationRegistry.getInstrumentation().getContext().getResources()); - when(sOverrides.resources.getInteger(R.integer.config_maxShortcutTargetsPerApp)) + when( + ChooserActivityOverrideData + .getInstance() + .resources + .getInteger(R.integer.config_maxShortcutTargetsPerApp)) .thenReturn(1); Intent sendIntent = createSendTextIntent(); // We need app targets for direct targets to get displayed List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); // Create direct share target List serviceTargets = createDirectShareTargets(2, resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName); ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0); // Start activity - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper wrapper = (IChooserWrapper) activity; // Insert the direct share target Map directShareToShortcutInfos = new HashMap<>(); @@ -1325,8 +1576,8 @@ public class ChooserActivityTest { directShareToShortcutInfos.put(serviceTargets.get(1), shortcutInfos.get(1).getShortcutInfo()); InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> activity.getAdapter().addServiceResults( - activity.createTestDisplayResolveInfo(sendIntent, + () -> wrapper.getAdapter().addServiceResults( + wrapper.createTestDisplayResolveInfo(sendIntent, ri, "testLabel", "testInfo", @@ -1342,13 +1593,13 @@ public class ChooserActivityTest { Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); assertThat("Chooser should have 3 targets (2 apps, 1 direct)", - activity.getAdapter().getCount(), is(3)); + wrapper.getAdapter().getCount(), is(3)); assertThat("Chooser should have exactly one selectable direct target", - activity.getAdapter().getSelectableServiceTargetCount(), is(1)); + wrapper.getAdapter().getSelectableServiceTargetCount(), is(1)); assertThat("The resolver info must match the resolver info used to create the target", - activity.getAdapter().getItem(0).getResolveInfo(), is(ri)); + wrapper.getAdapter().getItem(0).getResolveInfo(), is(ri)); assertThat("The display label must match", - activity.getAdapter().getItem(0).getDisplayLabel(), is("testTitle0")); + wrapper.getAdapter().getItem(0).getDisplayLabel(), is("testTitle0")); } @Test @Ignore @@ -1358,24 +1609,35 @@ public class ChooserActivityTest { Boolean.toString(false), true /* makeDefault*/); // Set up resources - sOverrides.resources = Mockito.spy( + ChooserActivityOverrideData.getInstance().resources = Mockito.spy( InstrumentationRegistry.getInstrumentation().getContext().getResources()); - when(sOverrides.resources.getInteger(R.integer.config_maxShortcutTargetsPerApp)) + when( + ChooserActivityOverrideData + .getInstance() + .resources + .getInteger(R.integer.config_maxShortcutTargetsPerApp)) .thenReturn(1); Intent sendIntent = createSendTextIntent(); // We need app targets for direct targets to get displayed List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); // Create direct share target List serviceTargets = createDirectShareTargets(2, resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName); ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0); // Start activity - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper wrapper = (IChooserWrapper) activity; // Insert the direct share target Map directShareToShortcutInfos = new HashMap<>(); @@ -1385,8 +1647,8 @@ public class ChooserActivityTest { directShareToShortcutInfos.put(serviceTargets.get(1), shortcutInfos.get(1).getShortcutInfo()); InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> activity.getAdapter().addServiceResults( - activity.createTestDisplayResolveInfo(sendIntent, + () -> wrapper.getAdapter().addServiceResults( + wrapper.createTestDisplayResolveInfo(sendIntent, ri, "testLabel", "testInfo", @@ -1402,15 +1664,15 @@ public class ChooserActivityTest { Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS); assertThat("Chooser should have 4 targets (2 apps, 2 direct)", - activity.getAdapter().getCount(), is(4)); + wrapper.getAdapter().getCount(), is(4)); assertThat("Chooser should have exactly two selectable direct target", - activity.getAdapter().getSelectableServiceTargetCount(), is(2)); + wrapper.getAdapter().getSelectableServiceTargetCount(), is(2)); assertThat("The resolver info must match the resolver info used to create the target", - activity.getAdapter().getItem(0).getResolveInfo(), is(ri)); + wrapper.getAdapter().getItem(0).getResolveInfo(), is(ri)); assertThat("The display label must match", - activity.getAdapter().getItem(0).getDisplayLabel(), is("testTitle0")); + wrapper.getAdapter().getItem(0).getDisplayLabel(), is("testTitle0")); assertThat("The display label must match", - activity.getAdapter().getItem(1).getDisplayLabel(), is("testTitle1")); + wrapper.getAdapter().getItem(1).getDisplayLabel(), is("testTitle1")); } // This test is too long and too slow and should not be taken as an example for future tests. @@ -1434,19 +1696,30 @@ public class ChooserActivityTest { .getResources().getConfiguration()); configuration.orientation = orientation; - sOverrides.resources = Mockito.spy( + ChooserActivityOverrideData.getInstance().resources = Mockito.spy( InstrumentationRegistry.getInstrumentation().getContext().getResources()); - when(sOverrides.resources.getConfiguration()).thenReturn(configuration); + when( + ChooserActivityOverrideData + .getInstance() + .resources + .getConfiguration()) + .thenReturn(configuration); Intent sendIntent = createSendTextIntent(); // We need app targets for direct targets to get displayed List resolvedComponentInfos = createResolvedComponentsForTest(15); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); // Set up resources - MetricsLogger mockLogger = sOverrides.metricsLogger; + MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger; ArgumentCaptor logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); // Create direct share target List serviceTargets = createDirectShareTargets(1, @@ -1454,14 +1727,15 @@ public class ChooserActivityTest { ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0); // Start activity - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper wrapper = (IChooserWrapper) activity; // Insert the direct share target Map directShareToShortcutInfos = new HashMap<>(); directShareToShortcutInfos.put(serviceTargets.get(0), null); InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> activity.getAdapter().addServiceResults( - activity.createTestDisplayResolveInfo(sendIntent, + () -> wrapper.getAdapter().addServiceResults( + wrapper.createTestDisplayResolveInfo(sendIntent, ri, "testLabel", "testInfo", @@ -1479,11 +1753,11 @@ public class ChooserActivityTest { assertThat( String.format("Chooser should have %d targets (%d apps, 1 direct, 15 A-Z)", appTargetsExpected + 16, appTargetsExpected), - activity.getAdapter().getCount(), is(appTargetsExpected + 16)); + wrapper.getAdapter().getCount(), is(appTargetsExpected + 16)); assertThat("Chooser should have exactly one selectable direct target", - activity.getAdapter().getSelectableServiceTargetCount(), is(1)); + wrapper.getAdapter().getSelectableServiceTargetCount(), is(1)); assertThat("The resolver info must match the resolver info used to create the target", - activity.getAdapter().getItem(0).getResolveInfo(), is(ri)); + wrapper.getAdapter().getItem(0).getResolveInfo(), is(ri)); // Click on the direct target String name = serviceTargets.get(0).getTitle().toString(); @@ -1546,7 +1820,7 @@ public class ChooserActivityTest { sendIntent.setType(TEST_MIME_TYPE); markWorkProfileUserAvailable(); - final ChooserWrapperActivity activity = + final IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); waitForIdle(); @@ -1571,7 +1845,7 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - final ChooserWrapperActivity activity = + final IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); waitForIdle(); onView(withText(R.string.resolver_work_tab)).perform(click()); @@ -1594,7 +1868,7 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -1625,13 +1899,12 @@ public class ChooserActivityTest { createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10); List workResolvedComponentInfos = createResolvedComponentsForTest(workProfileTargets); - sOverrides.hasCrossProfileIntents = false; + ChooserActivityOverrideData.getInstance().hasCrossProfileIntents = false; setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - final ChooserWrapperActivity activity = - mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); waitForIdle(); onView(withText(R.string.resolver_work_tab)).perform(click()); waitForIdle(); @@ -1651,14 +1924,13 @@ public class ChooserActivityTest { createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10); List workResolvedComponentInfos = createResolvedComponentsForTest(workProfileTargets); - sOverrides.isQuietModeEnabled = true; + ChooserActivityOverrideData.getInstance().isQuietModeEnabled = true; setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); ResolverActivity.ENABLE_TABBED_VIEW = true; - final ChooserWrapperActivity activity = - mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); waitForIdle(); onView(withId(R.id.contentPanel)) .perform(swipeUp()); @@ -1682,8 +1954,7 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - final ChooserWrapperActivity activity = - mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); waitForIdle(); onView(withId(R.id.contentPanel)) .perform(swipeUp()); @@ -1704,8 +1975,8 @@ public class ChooserActivityTest { List workResolvedComponentInfos = createResolvedComponentsForTest(0); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); - sOverrides.isQuietModeEnabled = true; - sOverrides.hasCrossProfileIntents = false; + ChooserActivityOverrideData.getInstance().isQuietModeEnabled = true; + ChooserActivityOverrideData.getInstance().hasCrossProfileIntents = false; Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); @@ -1730,7 +2001,7 @@ public class ChooserActivityTest { List workResolvedComponentInfos = createResolvedComponentsForTest(0); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); - sOverrides.isQuietModeEnabled = true; + ChooserActivityOverrideData.getInstance().isQuietModeEnabled = true; Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); @@ -1750,19 +2021,25 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); assertThat(activity.getAdapter().getCount(), is(2)); onView(withId(R.id.profile_button)).check(doesNotExist()); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -1821,9 +2098,15 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); // We need app targets for direct targets to get displayed List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); // Create direct share target List serviceTargets = createDirectShareTargets(1, @@ -1831,8 +2114,8 @@ public class ChooserActivityTest { ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0); // Start activity - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); // Insert the direct share target Map directShareToShortcutInfos = new HashMap<>(); @@ -1901,13 +2184,19 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); // We need app targets for direct targets to get displayed List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); // Start activity - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured @@ -1962,13 +2251,18 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); List resolvedComponentInfos = createResolvedComponentsForTest(2); - when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent( - Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); - final ChooserWrapperActivity activity = mActivityRule - .launchActivity(Intent.createChooser(sendIntent, null)); + final IChooserWrapper activity = (IChooserWrapper) + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed())); @@ -2032,7 +2326,7 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - final ChooserWrapperActivity activity = + final IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); waitForIdle(); onView(withText(R.string.resolver_work_tab)).perform(click()); @@ -2108,14 +2402,19 @@ public class ChooserActivityTest { ResolverActivity.ENABLE_TABBED_VIEW = false; List personalResolvedComponentInfos = createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))) + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -2132,14 +2431,19 @@ public class ChooserActivityTest { ResolverActivity.ENABLE_TABBED_VIEW = false; List personalResolvedComponentInfos = createResolvedComponentsForTest(1); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))) + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -2161,11 +2465,11 @@ public class ChooserActivityTest { createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10); List workResolvedComponentInfos = createResolvedComponentsForTest(workProfileTargets); - sOverrides.hasCrossProfileIntents = false; + ChooserActivityOverrideData.getInstance().hasCrossProfileIntents = false; setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createSendTextIntent(); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -2180,27 +2484,37 @@ public class ChooserActivityTest { public void testOneInitialIntent_noAutolaunch() { List personalResolvedComponentInfos = createResolvedComponentsForTest(1); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))) + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); Intent chooserIntent = createChooserIntent(createSendTextIntent(), new Intent[] {new Intent("action.fake")}); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; - sOverrides.packageManager = mock(PackageManager.class); + ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class); ResolveInfo ri = createFakeResolveInfo(); - when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(ri); + when( + ChooserActivityOverrideData + .getInstance().packageManager + .resolveActivity(any(Intent.class), anyInt())) + .thenReturn(ri); waitForIdle(); - ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent); + IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(chooserIntent); waitForIdle(); assertNull(chosen[0]); - assertThat(activity.getPersonalListAdapter().getCallerTargetCount(), is(1)); + assertThat(activity + .getPersonalListAdapter().getCallerTargetCount(), is(1)); } @Test @@ -2219,12 +2533,16 @@ public class ChooserActivityTest { new Intent("action.fake2") }; Intent chooserIntent = createChooserIntent(createSendTextIntent(), initialIntents); - sOverrides.packageManager = mock(PackageManager.class); - when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())) + ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class); + when( + ChooserActivityOverrideData + .getInstance() + .packageManager + .resolveActivity(any(Intent.class), anyInt())) .thenReturn(createFakeResolveInfo()); waitForIdle(); - ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent); + IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(chooserIntent); waitForIdle(); assertThat(activity.getPersonalListAdapter().getCallerTargetCount(), is(2)); @@ -2241,18 +2559,22 @@ public class ChooserActivityTest { createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10); List workResolvedComponentInfos = createResolvedComponentsForTest(workProfileTargets); - sOverrides.hasCrossProfileIntents = false; + ChooserActivityOverrideData.getInstance().hasCrossProfileIntents = false; setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent[] initialIntents = { new Intent("action.fake1"), new Intent("action.fake2") }; Intent chooserIntent = createChooserIntent(new Intent(), initialIntents); - sOverrides.packageManager = mock(PackageManager.class); - when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())) + ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class); + when( + ChooserActivityOverrideData + .getInstance() + .packageManager + .resolveActivity(any(Intent.class), anyInt())) .thenReturn(createFakeResolveInfo()); - final ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent); + mActivityRule.launchActivity(chooserIntent); waitForIdle(); onView(withText(R.string.resolver_work_tab)).perform(click()); waitForIdle(); @@ -2278,8 +2600,12 @@ public class ChooserActivityTest { new Intent("action.fake2") }; Intent chooserIntent = createChooserIntent(new Intent(), initialIntents); - sOverrides.packageManager = mock(PackageManager.class); - when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())) + ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class); + when( + ChooserActivityOverrideData + .getInstance() + .packageManager + .resolveActivity(any(Intent.class), anyInt())) .thenReturn(createFakeResolveInfo()); mActivityRule.launchActivity(chooserIntent); @@ -2298,20 +2624,26 @@ public class ChooserActivityTest { // Create 4 ranked app targets. List personalResolvedComponentInfos = createResolvedComponentsForTest(4); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent( Mockito.anyBoolean(), - Mockito.isA(List.class))) + Mockito.anyBoolean(), + Mockito.isA(List.class))) .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); // Create caller target which is duplicate with one of app targets Intent chooserIntent = createChooserIntent(createSendTextIntent(), new Intent[] {new Intent("action.fake")}); - sOverrides.packageManager = mock(PackageManager.class); + ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class); ResolveInfo ri = ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT); - when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(ri); + when( + ChooserActivityOverrideData + .getInstance() + .packageManager + .resolveActivity(any(Intent.class), anyInt())) + .thenReturn(ri); waitForIdle(); - ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent); + IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(chooserIntent); waitForIdle(); // Total 4 targets (1 caller target, 3 ranked targets) @@ -2330,13 +2662,14 @@ public class ChooserActivityTest { List workResolvedComponentInfos = createResolvedComponentsForTest(3); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); - sOverrides.isQuietModeEnabled = true; + ChooserActivityOverrideData.getInstance().isQuietModeEnabled = true; boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false }; - sOverrides.onQueryDirectShareTargets = chooserListAdapter -> { - isQueryDirectShareCalledOnWorkProfile[0] = - (chooserListAdapter.getUserHandle().getIdentifier() == 10); - return null; - }; + ChooserActivityOverrideData.getInstance().onQueryDirectShareTargets = + chooserListAdapter -> { + isQueryDirectShareCalledOnWorkProfile[0] = + (chooserListAdapter.getUserHandle().getIdentifier() == 10); + return null; + }; Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); @@ -2361,13 +2694,14 @@ public class ChooserActivityTest { List workResolvedComponentInfos = createResolvedComponentsForTest(3); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); - sOverrides.isWorkProfileUserRunning = false; + ChooserActivityOverrideData.getInstance().isWorkProfileUserRunning = false; boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false }; - sOverrides.onQueryDirectShareTargets = chooserListAdapter -> { - isQueryDirectShareCalledOnWorkProfile[0] = - (chooserListAdapter.getUserHandle().getIdentifier() == 10); - return null; - }; + ChooserActivityOverrideData.getInstance().onQueryDirectShareTargets = + chooserListAdapter -> { + isQueryDirectShareCalledOnWorkProfile[0] = + (chooserListAdapter.getUserHandle().getIdentifier() == 10); + return null; + }; Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); @@ -2394,17 +2728,18 @@ public class ChooserActivityTest { setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - sOverrides.isWorkProfileUserRunning = false; + ChooserActivityOverrideData.getInstance().isWorkProfileUserRunning = false; - final ChooserWrapperActivity activity = + final ChooserActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); + final IChooserWrapper wrapper = (IChooserWrapper) activity; waitForIdle(); onView(withId(R.id.contentPanel)) .perform(swipeUp()); onView(withText(R.string.resolver_work_tab)).perform(click()); waitForIdle(); - assertEquals(3, activity.getWorkListAdapter().getCount()); + assertEquals(3, wrapper.getWorkListAdapter().getCount()); } @Test @@ -2417,13 +2752,14 @@ public class ChooserActivityTest { List workResolvedComponentInfos = createResolvedComponentsForTest(3); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); - sOverrides.isWorkProfileUserUnlocked = false; + ChooserActivityOverrideData.getInstance().isWorkProfileUserUnlocked = false; boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false }; - sOverrides.onQueryDirectShareTargets = chooserListAdapter -> { - isQueryDirectShareCalledOnWorkProfile[0] = - (chooserListAdapter.getUserHandle().getIdentifier() == 10); - return null; - }; + ChooserActivityOverrideData.getInstance().onQueryDirectShareTargets = + chooserListAdapter -> { + isQueryDirectShareCalledOnWorkProfile[0] = + (chooserListAdapter.getUserHandle().getIdentifier() == 10); + return null; + }; Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); @@ -2450,17 +2786,18 @@ public class ChooserActivityTest { setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); - sOverrides.isWorkProfileUserUnlocked = false; + ChooserActivityOverrideData.getInstance().isWorkProfileUserUnlocked = false; - final ChooserWrapperActivity activity = + final ChooserActivity activity = mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test")); + final IChooserWrapper wrapper = (IChooserWrapper) activity; waitForIdle(); onView(withId(R.id.contentPanel)) .perform(swipeUp()); onView(withText(R.string.resolver_work_tab)).perform(click()); waitForIdle(); - assertEquals(3, activity.getWorkListAdapter().getCount()); + assertEquals(3, wrapper.getWorkListAdapter().getCount()); } private Intent createChooserIntent(Intent intent, Intent[] initialIntents) { @@ -2671,23 +3008,39 @@ public class ChooserActivityTest { } private void markWorkProfileUserAvailable() { - sOverrides.workProfileUserHandle = UserHandle.of(10); + ChooserActivityOverrideData.getInstance().workProfileUserHandle = UserHandle.of(10); } private void setupResolverControllers( List personalResolvedComponentInfos, List workResolvedComponentInfos) { - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))) + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); - when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); - when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), - Mockito.anyBoolean(), - Mockito.isA(List.class), - eq(UserHandle.SYSTEM))) + when( + ChooserActivityOverrideData + .getInstance() + .workResolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(new ArrayList<>(workResolvedComponentInfos)); + when( + ChooserActivityOverrideData + .getInstance() + .workResolverListController + .getResolversForIntentAsUser( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))) .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); } } diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java index 6b3d657f9450d..d4f08ba5d65df 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java @@ -16,7 +16,6 @@ package com.android.internal.app; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.annotation.Nullable; @@ -41,13 +40,15 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import java.util.List; -import java.util.function.Function; -public class ChooserWrapperActivity extends ChooserActivity { - /* - * Simple wrapper around chooser activity to be able to initiate it under test - */ - static final OverrideData sOverrides = new OverrideData(); +/** + * Simple wrapper around chooser activity to be able to initiate it under test with overrides + * specified in the {@code ChooserActivityOverrideData} singleton. This should be copy-and-pasted + * verbatim to test other {@code ChooserActivity} subclasses (updating only the `extends` to match + * the concrete activity under test). + */ +public class ChooserWrapperActivity extends ChooserActivity implements IChooserWrapper { + static final ChooserActivityOverrideData sOverrides = ChooserActivityOverrideData.getInstance(); private UsageStatsManager mUsm; @Override @@ -72,16 +73,19 @@ public class ChooserWrapperActivity extends ChooserActivity { getChooserActivityLogger()); } - ChooserListAdapter getAdapter() { + @Override + public ChooserListAdapter getAdapter() { return mChooserMultiProfilePagerAdapter.getActiveListAdapter(); } - ChooserListAdapter getPersonalListAdapter() { + @Override + public ChooserListAdapter getPersonalListAdapter() { return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(0)) .getListAdapter(); } - ChooserListAdapter getWorkListAdapter() { + @Override + public ChooserListAdapter getWorkListAdapter() { if (mMultiProfilePagerAdapter.getInactiveListAdapter() == null) { return null; } @@ -89,7 +93,10 @@ public class ChooserWrapperActivity extends ChooserActivity { .getListAdapter(); } - boolean getIsSelected() { return mIsSuccessfullySelected; } + @Override + public boolean getIsSelected() { + return mIsSuccessfullySelected; + } @Override protected ComponentName getNearbySharingComponent() { @@ -103,7 +110,8 @@ public class ChooserWrapperActivity extends ChooserActivity { return new ChooserWrapperActivity.EmptyTargetInfo(); } - UsageStatsManager getUsageStatsManager() { + @Override + public UsageStatsManager getUsageStatsManager() { if (mUsm == null) { mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); } @@ -172,7 +180,7 @@ public class ChooserWrapperActivity extends ChooserActivity { } @Override - protected ChooserActivityLogger getChooserActivityLogger() { + public ChooserActivityLogger getChooserActivityLogger() { return sOverrides.chooserActivityLogger; } @@ -197,6 +205,7 @@ public class ChooserWrapperActivity extends ChooserActivity { return super.isWorkProfile(); } + @Override public DisplayResolveInfo createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, CharSequence pInfo, Intent replacementIntent, @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter) { @@ -209,7 +218,8 @@ public class ChooserWrapperActivity extends ChooserActivity { return sOverrides.workProfileUserHandle; } - protected UserHandle getCurrentUserHandle() { + @Override + public UserHandle getCurrentUserHandle() { return mMultiProfilePagerAdapter.getCurrentUserHandle(); } @@ -248,75 +258,4 @@ public class ChooserWrapperActivity extends ChooserActivity { } return sOverrides.isWorkProfileUserUnlocked; } - - /** - * We cannot directly mock the activity created since instrumentation creates it. - *

- * Instead, we use static instances of this object to modify behavior. - */ - static class OverrideData { - @SuppressWarnings("Since15") - public Function createPackageManager; - public Function onSafelyStartCallback; - public Function onQueryDirectShareTargets; - public ResolverListController resolverListController; - public ResolverListController workResolverListController; - public Boolean isVoiceInteraction; - public boolean isImageType; - public Cursor resolverCursor; - public boolean resolverForceException; - public Bitmap previewThumbnail; - public MetricsLogger metricsLogger; - public ChooserActivityLogger chooserActivityLogger; - public int alternateProfileSetting; - public Resources resources; - public UserHandle workProfileUserHandle; - public boolean hasCrossProfileIntents; - public boolean isQuietModeEnabled; - public boolean isWorkProfileUserRunning; - public boolean isWorkProfileUserUnlocked; - public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector; - public PackageManager packageManager; - - public void reset() { - onSafelyStartCallback = null; - onQueryDirectShareTargets = null; - isVoiceInteraction = null; - createPackageManager = null; - previewThumbnail = null; - isImageType = false; - resolverCursor = null; - resolverForceException = false; - resolverListController = mock(ResolverListController.class); - workResolverListController = mock(ResolverListController.class); - metricsLogger = mock(MetricsLogger.class); - chooserActivityLogger = new ChooserActivityLoggerFake(); - alternateProfileSetting = 0; - resources = null; - workProfileUserHandle = null; - hasCrossProfileIntents = true; - isQuietModeEnabled = false; - isWorkProfileUserRunning = true; - isWorkProfileUserUnlocked = true; - packageManager = null; - multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() { - @Override - public boolean hasCrossProfileIntents(List intents, int sourceUserId, - int targetUserId) { - return hasCrossProfileIntents; - } - - @Override - public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) { - return isQuietModeEnabled; - } - - @Override - public void requestQuietModeEnabled(boolean enabled, - UserHandle workProfileUserHandle) { - isQuietModeEnabled = enabled; - } - }; - } - } } diff --git a/core/tests/coretests/src/com/android/internal/app/IChooserWrapper.java b/core/tests/coretests/src/com/android/internal/app/IChooserWrapper.java new file mode 100644 index 0000000000000..05f82529e760f --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/app/IChooserWrapper.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 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.internal.app; + +import android.annotation.Nullable; +import android.app.usage.UsageStatsManager; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.os.UserHandle; + +import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter; +import com.android.internal.app.chooser.DisplayResolveInfo; + +/** + * Test-only extended API capabilities that an instrumented ChooserActivity subclass provides in + * order to expose the internals for override/inspection. Implementations should apply the overrides + * specified by the {@code ChooserActivityOverrideData} singleton. + */ +public interface IChooserWrapper { + ChooserListAdapter getAdapter(); + ChooserListAdapter getPersonalListAdapter(); + ChooserListAdapter getWorkListAdapter(); + boolean getIsSelected(); + UsageStatsManager getUsageStatsManager(); + DisplayResolveInfo createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri, + CharSequence pLabel, CharSequence pInfo, Intent replacementIntent, + @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter); + UserHandle getCurrentUserHandle(); + ChooserActivityLogger getChooserActivityLogger(); +}