1  /*
2   * Copyright (C) 2016 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.android.internal.app;
18  
19  import static android.app.Activity.RESULT_OK;
20  
21  import static androidx.test.espresso.Espresso.onView;
22  import static androidx.test.espresso.action.ViewActions.click;
23  import static androidx.test.espresso.action.ViewActions.swipeUp;
24  import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
25  import static androidx.test.espresso.assertion.ViewAssertions.matches;
26  import static androidx.test.espresso.matcher.ViewMatchers.hasSibling;
27  import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
28  import static androidx.test.espresso.matcher.ViewMatchers.withId;
29  import static androidx.test.espresso.matcher.ViewMatchers.withText;
30  
31  import static com.android.internal.app.ChooserActivity.TARGET_TYPE_CHOOSER_TARGET;
32  import static com.android.internal.app.ChooserActivity.TARGET_TYPE_DEFAULT;
33  import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE;
34  import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER;
35  import static com.android.internal.app.ChooserListAdapter.CALLER_TARGET_SCORE_BOOST;
36  import static com.android.internal.app.ChooserListAdapter.SHORTCUT_TARGET_SCORE_BOOST;
37  import static com.android.internal.app.MatcherUtils.first;
38  
39  import static junit.framework.Assert.assertFalse;
40  import static junit.framework.Assert.assertNull;
41  import static junit.framework.Assert.assertTrue;
42  
43  import static org.hamcrest.CoreMatchers.allOf;
44  import static org.hamcrest.CoreMatchers.is;
45  import static org.hamcrest.CoreMatchers.not;
46  import static org.hamcrest.CoreMatchers.notNullValue;
47  import static org.hamcrest.MatcherAssert.assertThat;
48  import static org.hamcrest.Matchers.greaterThan;
49  import static org.junit.Assert.assertEquals;
50  import static org.mockito.ArgumentMatchers.any;
51  import static org.mockito.ArgumentMatchers.anyInt;
52  import static org.mockito.ArgumentMatchers.eq;
53  import static org.mockito.Mockito.atLeastOnce;
54  import static org.mockito.Mockito.mock;
55  import static org.mockito.Mockito.times;
56  import static org.mockito.Mockito.verify;
57  import static org.mockito.Mockito.when;
58  
59  import android.app.usage.UsageStatsManager;
60  import android.content.ClipData;
61  import android.content.ClipDescription;
62  import android.content.ClipboardManager;
63  import android.content.ComponentName;
64  import android.content.Context;
65  import android.content.Intent;
66  import android.content.pm.ActivityInfo;
67  import android.content.pm.ApplicationInfo;
68  import android.content.pm.PackageManager;
69  import android.content.pm.ResolveInfo;
70  import android.content.pm.ShortcutInfo;
71  import android.content.pm.ShortcutManager.ShareShortcutInfo;
72  import android.content.res.Configuration;
73  import android.database.Cursor;
74  import android.graphics.Bitmap;
75  import android.graphics.Canvas;
76  import android.graphics.Color;
77  import android.graphics.Paint;
78  import android.graphics.drawable.Icon;
79  import android.metrics.LogMaker;
80  import android.net.Uri;
81  import android.os.UserHandle;
82  import android.provider.DeviceConfig;
83  import android.service.chooser.ChooserTarget;
84  import android.util.Pair;
85  import android.view.View;
86  
87  import androidx.annotation.CallSuper;
88  import androidx.test.espresso.matcher.BoundedDiagnosingMatcher;
89  import androidx.test.platform.app.InstrumentationRegistry;
90  import androidx.test.rule.ActivityTestRule;
91  
92  import com.android.internal.R;
93  import com.android.internal.app.ChooserActivity.ServiceResultInfo;
94  import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
95  import com.android.internal.app.chooser.DisplayResolveInfo;
96  import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
97  import com.android.internal.logging.MetricsLogger;
98  import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
99  import com.android.internal.util.FrameworkStatsLog;
100  import com.android.internal.widget.GridLayoutManager;
101  import com.android.internal.widget.RecyclerView;
102  
103  import org.hamcrest.Description;
104  import org.hamcrest.Matcher;
105  import org.hamcrest.Matchers;
106  import org.junit.Before;
107  import org.junit.Ignore;
108  import org.junit.Rule;
109  import org.junit.Test;
110  import org.junit.runner.RunWith;
111  import org.junit.runners.Parameterized;
112  import org.mockito.ArgumentCaptor;
113  import org.mockito.Mockito;
114  
115  import java.util.ArrayList;
116  import java.util.Arrays;
117  import java.util.Collection;
118  import java.util.HashMap;
119  import java.util.List;
120  import java.util.Map;
121  import java.util.function.Function;
122  
123  /**
124   * Instrumentation tests for chooser activities that derive from the system
125   * {@code com.android.internal.ChooserActivity}. This class is used directly to test the system
126   * implementation, but clients can inherit from this test to apply the same suite of chooser tests
127   * to their own ChooserActivity implementations. Clients should override
128   * #getConcreteIntentForLaunch() to configure an intent that will launch their concrete
129   * ChooserActivity subtype. Tests will assume that this subtype implements the IChooserWrapper
130   * interface, which is only appropriate for testing. Clients will typically create their own
131   * "ChooserWrapperActivity" by copy-and-pasting the system implementation, parenting to their own
132   * ChooserActivity subclass instead of directly to the system implementation. Code comments in this
133   * file provide direction for developers creating derived test suites, and eventually for removing
134   * the extra complexity once we no longer need to support parallel ChooserActivity implementations.
135   */
136  @RunWith(Parameterized.class)
137  public class ChooserActivityTest {
138  
139      /* --------
140       * Subclasses should copy the following section verbatim (or alternatively could specify some
141       * additional @Parameterized.Parameters, as long as the correct parameters are used to
142       * initialize the ChooserActivityTest). The subclasses should also be @RunWith the
143       * `Parameterized` runner.
144       * --------
145       */
146      private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
147              .getInstrumentation().getTargetContext().getUser();
148      private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm;
149      private static final Function<PackageManager, PackageManager> NO_APP_PREDICTION_SERVICE_PM =
150              pm -> {
151                  PackageManager mock = Mockito.spy(pm);
152                  when(mock.getAppPredictionServicePackageName()).thenReturn(null);
153                  return mock;
154              };
155  
156      @Parameterized.Parameters
packageManagers()157      public static Collection packageManagers() {
158          return Arrays.asList(new Object[][] {
159                  {0, "Default PackageManager", DEFAULT_PM},
160                  {1, "No App Prediction Service", NO_APP_PREDICTION_SERVICE_PM}
161          });
162      }
163  
164      /* --------
165       * Subclasses can override the following methods to customize test behavior.
166       * --------
167       */
168  
169      /**
170       * Perform any necessary per-test initialization steps (subclasses may add additional steps
171       * before and/or after calling up to the superclass implementation).
172       */
173      @CallSuper
setup()174      protected void setup() {
175          cleanOverrideData();
176      }
177  
178      /**
179       * Given an intent that was constructed in a test, perform any additional configuration to
180       * specify the appropriate concrete ChooserActivity subclass. The activity launched by this
181       * intent must descend from android.internal.app.ChooserActivity (for our ActivityTestRule), and
182       * must also implement the android.internal.app.IChooserWrapper interface (since test code will
183       * assume the ability to make unsafe downcasts).
184       */
getConcreteIntentForLaunch(Intent clientIntent)185      protected Intent getConcreteIntentForLaunch(Intent clientIntent) {
186          clientIntent.setClass(
187                  InstrumentationRegistry.getInstrumentation().getTargetContext(),
188                  com.android.internal.app.ChooserWrapperActivity.class);
189          return clientIntent;
190      }
191  
192      /**
193       * Whether {@code #testIsAppPredictionServiceAvailable} should verify the behavior after
194       * changing the availability conditions at runtime. In the unbundled chooser, the availability
195       * is cached at start and will never be re-evaluated.
196       * TODO: remove when we no longer want to test the system's on-the-fly evaluation.
197       */
shouldTestTogglingAppPredictionServiceAvailabilityAtRuntime()198      protected boolean shouldTestTogglingAppPredictionServiceAvailabilityAtRuntime() {
199          return false;
200      }
201  
202      /* --------
203       * The code in this section is unorthodox and can be simplified/reverted when we no longer need
204       * to support the parallel chooser implementations.
205       * --------
206       */
207  
208      // Shared test code references the activity under test as ChooserActivity, the common ancestor
209      // of any (inheritance-based) chooser implementation. For testing purposes, that activity will
210      // usually be cast to IChooserWrapper to expose instrumentation.
211      @Rule
212      public ActivityTestRule<ChooserActivity> mActivityRule =
213              new ActivityTestRule<>(ChooserActivity.class, false, false) {
214                  @Override
215                  public ChooserActivity launchActivity(Intent clientIntent) {
216                      return super.launchActivity(getConcreteIntentForLaunch(clientIntent));
217                  }
218              };
219  
220      @Before
doPolymorphicSetup()221      public final void doPolymorphicSetup() {
222          // The base class needs a @Before-annotated setup for when it runs against the system
223          // chooser, while subclasses need to be able to specify their own setup behavior. Notably
224          // the unbundled chooser, running in user-space, needs to take additional steps before it
225          // can run #cleanOverrideData() (which writes to DeviceConfig).
226          setup();
227      }
228  
229      /* --------
230       * Subclasses can ignore the remaining code and inherit the full suite of tests.
231       * --------
232       */
233  
234      private static final String TEST_MIME_TYPE = "application/TestType";
235  
236      private static final int CONTENT_PREVIEW_IMAGE = 1;
237      private static final int CONTENT_PREVIEW_FILE = 2;
238      private static final int CONTENT_PREVIEW_TEXT = 3;
239      private Function<PackageManager, PackageManager> mPackageManagerOverride;
240      private int mTestNum;
241  
242  
ChooserActivityTest( int testNum, String testName, Function<PackageManager, PackageManager> packageManagerOverride)243      public ChooserActivityTest(
244                  int testNum,
245                  String testName,
246                  Function<PackageManager, PackageManager> packageManagerOverride) {
247          mPackageManagerOverride = packageManagerOverride;
248          mTestNum = testNum;
249      }
250  
cleanOverrideData()251      public void cleanOverrideData() {
252          ChooserActivityOverrideData.getInstance().reset();
253          ChooserActivityOverrideData.getInstance().createPackageManager = mPackageManagerOverride;
254          DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
255                  SystemUiDeviceConfigFlags.APPLY_SHARING_APP_LIMITS_IN_SYSUI,
256                  Boolean.toString(true),
257                  true /* makeDefault*/);
258      }
259  
260      @Test
customTitle()261      public void customTitle() throws InterruptedException {
262          Intent viewIntent = createViewTextIntent();
263          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
264  
265          when(
266                  ChooserActivityOverrideData
267                          .getInstance()
268                          .resolverListController
269                          .getResolversForIntent(
270                                  Mockito.anyBoolean(),
271                                  Mockito.anyBoolean(),
272                                  Mockito.anyBoolean(),
273                                  Mockito.isA(List.class)))
274                  .thenReturn(resolvedComponentInfos);
275          final IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(
276                  Intent.createChooser(viewIntent, "chooser test"));
277  
278          waitForIdle();
279          assertThat(activity.getAdapter().getCount(), is(2));
280          assertThat(activity.getAdapter().getServiceTargetCount(), is(0));
281          onView(withIdFromRuntimeResource("title")).check(matches(withText("chooser test")));
282      }
283  
284      @Test
customTitleIgnoredForSendIntents()285      public void customTitleIgnoredForSendIntents() throws InterruptedException {
286          Intent sendIntent = createSendTextIntent();
287          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
288  
289          when(
290                  ChooserActivityOverrideData
291                          .getInstance()
292                          .resolverListController
293                          .getResolversForIntent(
294                                  Mockito.anyBoolean(),
295                                  Mockito.anyBoolean(),
296                                  Mockito.anyBoolean(),
297                                  Mockito.isA(List.class)))
298                  .thenReturn(resolvedComponentInfos);
299          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test"));
300          waitForIdle();
301          onView(withIdFromRuntimeResource("title"))
302                  .check(matches(withTextFromRuntimeResource("whichSendApplication")));
303      }
304  
305      @Test
emptyTitle()306      public void emptyTitle() throws InterruptedException {
307          Intent sendIntent = createSendTextIntent();
308          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
309  
310          when(
311                  ChooserActivityOverrideData
312                          .getInstance()
313                          .resolverListController
314                          .getResolversForIntent(
315                                  Mockito.anyBoolean(),
316                                  Mockito.anyBoolean(),
317                                  Mockito.anyBoolean(),
318                                  Mockito.isA(List.class)))
319                  .thenReturn(resolvedComponentInfos);
320          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
321          waitForIdle();
322          onView(withIdFromRuntimeResource("title"))
323                  .check(matches(withTextFromRuntimeResource("whichSendApplication")));
324      }
325  
326      @Test
emptyPreviewTitleAndThumbnail()327      public void emptyPreviewTitleAndThumbnail() throws InterruptedException {
328          Intent sendIntent = createSendTextIntentWithPreview(null, null);
329          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
330  
331          when(
332                  ChooserActivityOverrideData
333                          .getInstance()
334                          .resolverListController
335                          .getResolversForIntent(
336                                  Mockito.anyBoolean(),
337                                  Mockito.anyBoolean(),
338                                  Mockito.anyBoolean(),
339                                  Mockito.isA(List.class)))
340                  .thenReturn(resolvedComponentInfos);
341          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
342          waitForIdle();
343          onView(withIdFromRuntimeResource("content_preview_title"))
344                  .check(matches(not(isDisplayed())));
345          onView(withIdFromRuntimeResource("content_preview_thumbnail"))
346                  .check(matches(not(isDisplayed())));
347      }
348  
349      @Test
visiblePreviewTitleWithoutThumbnail()350      public void visiblePreviewTitleWithoutThumbnail() throws InterruptedException {
351          String previewTitle = "My Content Preview Title";
352          Intent sendIntent = createSendTextIntentWithPreview(previewTitle, null);
353          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
354  
355          when(
356                  ChooserActivityOverrideData
357                          .getInstance()
358                          .resolverListController
359                          .getResolversForIntent(
360                                  Mockito.anyBoolean(),
361                                  Mockito.anyBoolean(),
362                                  Mockito.anyBoolean(),
363                                  Mockito.isA(List.class)))
364                  .thenReturn(resolvedComponentInfos);
365          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
366          waitForIdle();
367          onView(withIdFromRuntimeResource("content_preview_title"))
368                  .check(matches(isDisplayed()));
369          onView(withIdFromRuntimeResource("content_preview_title"))
370                  .check(matches(withText(previewTitle)));
371          onView(withIdFromRuntimeResource("content_preview_thumbnail"))
372                  .check(matches(not(isDisplayed())));
373      }
374  
375      @Test
visiblePreviewTitleWithInvalidThumbnail()376      public void visiblePreviewTitleWithInvalidThumbnail() throws InterruptedException {
377          String previewTitle = "My Content Preview Title";
378          Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
379                  Uri.parse("tel:(+49)12345789"));
380          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
381  
382          when(
383                  ChooserActivityOverrideData
384                          .getInstance()
385                          .resolverListController
386                          .getResolversForIntent(
387                                  Mockito.anyBoolean(),
388                                  Mockito.anyBoolean(),
389                                  Mockito.anyBoolean(),
390                                  Mockito.isA(List.class)))
391                  .thenReturn(resolvedComponentInfos);
392          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
393          waitForIdle();
394          onView(withIdFromRuntimeResource("content_preview_title")).check(matches(isDisplayed()));
395          onView(withIdFromRuntimeResource("content_preview_thumbnail"))
396                  .check(matches(not(isDisplayed())));
397      }
398  
399      @Test
visiblePreviewTitleAndThumbnail()400      public void visiblePreviewTitleAndThumbnail() throws InterruptedException {
401          String previewTitle = "My Content Preview Title";
402          Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
403                  Uri.parse("android.resource://com.android.frameworks.coretests/"
404                          + com.android.frameworks.coretests.R.drawable.test320x240));
405          ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap();
406          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
407  
408          when(
409                  ChooserActivityOverrideData
410                          .getInstance()
411                          .resolverListController
412                          .getResolversForIntent(
413                                  Mockito.anyBoolean(),
414                                  Mockito.anyBoolean(),
415                                  Mockito.anyBoolean(),
416                                  Mockito.isA(List.class)))
417                  .thenReturn(resolvedComponentInfos);
418          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
419          waitForIdle();
420          onView(withIdFromRuntimeResource("content_preview_title")).check(matches(isDisplayed()));
421          onView(withIdFromRuntimeResource("content_preview_thumbnail"))
422                  .check(matches(isDisplayed()));
423      }
424  
425      @Test @Ignore
twoOptionsAndUserSelectsOne()426      public void twoOptionsAndUserSelectsOne() throws InterruptedException {
427          Intent sendIntent = createSendTextIntent();
428          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
429  
430          when(
431                  ChooserActivityOverrideData
432                          .getInstance()
433                          .resolverListController
434                          .getResolversForIntent(
435                                  Mockito.anyBoolean(),
436                                  Mockito.anyBoolean(),
437                                  Mockito.anyBoolean(),
438                                  Mockito.isA(List.class)))
439                  .thenReturn(resolvedComponentInfos);
440  
441          final IChooserWrapper activity = (IChooserWrapper)
442                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
443          waitForIdle();
444  
445          assertThat(activity.getAdapter().getCount(), is(2));
446          onView(withIdFromRuntimeResource("profile_button")).check(doesNotExist());
447  
448          ResolveInfo[] chosen = new ResolveInfo[1];
449          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
450              chosen[0] = targetInfo.getResolveInfo();
451              return true;
452          };
453  
454          ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
455          onView(withText(toChoose.activityInfo.name))
456                  .perform(click());
457          waitForIdle();
458          assertThat(chosen[0], is(toChoose));
459      }
460  
461      @Test @Ignore
fourOptionsStackedIntoOneTarget()462      public void fourOptionsStackedIntoOneTarget() throws InterruptedException {
463          Intent sendIntent = createSendTextIntent();
464  
465          // create just enough targets to ensure the a-z list should be shown
466          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
467  
468          // next create 4 targets in a single app that should be stacked into a single target
469          String packageName = "xxx.yyy";
470          String appName = "aaa";
471          ComponentName cn = new ComponentName(packageName, appName);
472          Intent intent = new Intent("fakeIntent");
473          List<ResolvedComponentInfo> infosToStack = new ArrayList<>();
474          for (int i = 0; i < 4; i++) {
475              ResolveInfo resolveInfo = ResolverDataProvider.createResolveInfo(i,
476                      UserHandle.USER_CURRENT, PERSONAL_USER_HANDLE);
477              resolveInfo.activityInfo.applicationInfo.name = appName;
478              resolveInfo.activityInfo.applicationInfo.packageName = packageName;
479              resolveInfo.activityInfo.packageName = packageName;
480              resolveInfo.activityInfo.name = "ccc" + i;
481              infosToStack.add(new ResolvedComponentInfo(cn, intent, resolveInfo));
482          }
483          resolvedComponentInfos.addAll(infosToStack);
484  
485          when(
486                  ChooserActivityOverrideData
487                          .getInstance()
488                          .resolverListController
489                          .getResolversForIntent(
490                                  Mockito.anyBoolean(),
491                                  Mockito.anyBoolean(),
492                                  Mockito.anyBoolean(),
493                                  Mockito.isA(List.class)))
494                  .thenReturn(resolvedComponentInfos);
495  
496          final IChooserWrapper activity = (IChooserWrapper)
497                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
498          waitForIdle();
499  
500          // expect 1 unique targets + 1 group + 4 ranked app targets
501          assertThat(activity.getAdapter().getCount(), is(6));
502  
503          ResolveInfo[] chosen = new ResolveInfo[1];
504          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
505              chosen[0] = targetInfo.getResolveInfo();
506              return true;
507          };
508  
509          onView(allOf(withText(appName), hasSibling(withText("")))).perform(click());
510          waitForIdle();
511  
512          // clicking will launch a dialog to choose the activity within the app
513          onView(withText(appName)).check(matches(isDisplayed()));
514          int i = 0;
515          for (ResolvedComponentInfo rci: infosToStack) {
516              onView(withText("ccc" + i)).check(matches(isDisplayed()));
517              ++i;
518          }
519      }
520  
521      @Test @Ignore
updateChooserCountsAndModelAfterUserSelection()522      public void updateChooserCountsAndModelAfterUserSelection() throws InterruptedException {
523          Intent sendIntent = createSendTextIntent();
524          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
525  
526          when(
527                  ChooserActivityOverrideData
528                          .getInstance()
529                          .resolverListController
530                          .getResolversForIntent(
531                                  Mockito.anyBoolean(),
532                                  Mockito.anyBoolean(),
533                                  Mockito.anyBoolean(),
534                                  Mockito.isA(List.class)))
535                  .thenReturn(resolvedComponentInfos);
536  
537          final IChooserWrapper activity = (IChooserWrapper)
538                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
539          waitForIdle();
540          UsageStatsManager usm = activity.getUsageStatsManager();
541          verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1))
542                  .topK(any(List.class), anyInt());
543          assertThat(activity.getIsSelected(), is(false));
544          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
545              return true;
546          };
547          ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
548          DisplayResolveInfo testDri =
549                  activity.createTestDisplayResolveInfo(sendIntent, toChoose, "testLabel", "testInfo",
550                          sendIntent,/* resolveInfoPresentationGetter */ null);
551          onView(withText(toChoose.activityInfo.name))
552                  .perform(click());
553          waitForIdle();
554          verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1))
555                  .updateChooserCounts(Mockito.anyString(), any(UserHandle.class),
556                          Mockito.anyString());
557          verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1))
558                  .updateModel(testDri);
559          assertThat(activity.getIsSelected(), is(true));
560      }
561  
562      @Ignore // b/148158199
563      @Test
noResultsFromPackageManager()564      public void noResultsFromPackageManager() {
565          when(
566                  ChooserActivityOverrideData
567                          .getInstance()
568                          .resolverListController
569                          .getResolversForIntent(
570                                  Mockito.anyBoolean(),
571                                  Mockito.anyBoolean(),
572                                  Mockito.anyBoolean(),
573                                  Mockito.isA(List.class)))
574                  .thenReturn(null);
575          Intent sendIntent = createSendTextIntent();
576          final ChooserActivity activity =
577                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
578          final IChooserWrapper wrapper = (IChooserWrapper) activity;
579  
580          waitForIdle();
581          assertThat(activity.isFinishing(), is(false));
582  
583          onView(withIdFromRuntimeResource("empty")).check(matches(isDisplayed()));
584          onView(withIdFromRuntimeResource("profile_pager")).check(matches(not(isDisplayed())));
585          InstrumentationRegistry.getInstrumentation().runOnMainSync(
586                  () -> wrapper.getAdapter().handlePackagesChanged()
587          );
588          // backward compatibility. looks like we finish when data is empty after package change
589          assertThat(activity.isFinishing(), is(true));
590      }
591  
592      @Test
autoLaunchSingleResult()593      public void autoLaunchSingleResult() throws InterruptedException {
594          ResolveInfo[] chosen = new ResolveInfo[1];
595          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
596              chosen[0] = targetInfo.getResolveInfo();
597              return true;
598          };
599  
600          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
601          when(
602                  ChooserActivityOverrideData
603                          .getInstance()
604                          .resolverListController
605                          .getResolversForIntent(
606                                  Mockito.anyBoolean(),
607                                  Mockito.anyBoolean(),
608                                  Mockito.anyBoolean(),
609                                  Mockito.isA(List.class)))
610                  .thenReturn(resolvedComponentInfos);
611  
612          Intent sendIntent = createSendTextIntent();
613          final ChooserActivity activity =
614                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
615          waitForIdle();
616  
617          assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0)));
618          assertThat(activity.isFinishing(), is(true));
619      }
620  
621      @Test @Ignore
hasOtherProfileOneOption()622      public void hasOtherProfileOneOption() throws Exception {
623          // enable the work tab feature flag
624          ResolverActivity.ENABLE_TABBED_VIEW = true;
625          List<ResolvedComponentInfo> personalResolvedComponentInfos =
626                  createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
627          List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
628          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
629          markWorkProfileUserAvailable();
630  
631          ResolveInfo toChoose = personalResolvedComponentInfos.get(1).getResolveInfoAt(0);
632          Intent sendIntent = createSendTextIntent();
633          final IChooserWrapper activity = (IChooserWrapper)
634                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
635          waitForIdle();
636  
637          // The other entry is filtered to the other profile slot
638          assertThat(activity.getAdapter().getCount(), is(1));
639  
640          ResolveInfo[] chosen = new ResolveInfo[1];
641          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
642              chosen[0] = targetInfo.getResolveInfo();
643              return true;
644          };
645  
646          // Make a stable copy of the components as the original list may be modified
647          List<ResolvedComponentInfo> stableCopy =
648                  createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10);
649          waitForIdle();
650          Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs);
651  
652          onView(first(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name)))
653                  .perform(click());
654          waitForIdle();
655          assertThat(chosen[0], is(toChoose));
656      }
657  
658      @Test @Ignore
hasOtherProfileTwoOptionsAndUserSelectsOne()659      public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
660          // enable the work tab feature flag
661          ResolverActivity.ENABLE_TABBED_VIEW = true;
662  
663          Intent sendIntent = createSendTextIntent();
664          List<ResolvedComponentInfo> resolvedComponentInfos =
665                  createResolvedComponentsForTestWithOtherProfile(3);
666          ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
667  
668          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
669                  Mockito.anyBoolean(),
670                  Mockito.anyBoolean(),
671                  Mockito.anyBoolean(),
672                  Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
673          when(ChooserActivityOverrideData.getInstance().resolverListController.getLastChosen())
674                  .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
675  
676          final IChooserWrapper activity = (IChooserWrapper)
677                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
678          waitForIdle();
679  
680          // The other entry is filtered to the other profile slot
681          assertThat(activity.getAdapter().getCount(), is(2));
682  
683          ResolveInfo[] chosen = new ResolveInfo[1];
684          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
685              chosen[0] = targetInfo.getResolveInfo();
686              return true;
687          };
688  
689          // Make a stable copy of the components as the original list may be modified
690          List<ResolvedComponentInfo> stableCopy =
691                  createResolvedComponentsForTestWithOtherProfile(3);
692          onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
693                  .perform(click());
694          waitForIdle();
695          assertThat(chosen[0], is(toChoose));
696      }
697  
698      @Test @Ignore
hasLastChosenActivityAndOtherProfile()699      public void hasLastChosenActivityAndOtherProfile() throws Exception {
700          // enable the work tab feature flag
701          ResolverActivity.ENABLE_TABBED_VIEW = true;
702  
703          Intent sendIntent = createSendTextIntent();
704          List<ResolvedComponentInfo> resolvedComponentInfos =
705                  createResolvedComponentsForTestWithOtherProfile(3);
706          ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
707  
708          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
709                  Mockito.anyBoolean(),
710                  Mockito.anyBoolean(),
711                  Mockito.anyBoolean(),
712                  Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
713  
714          final IChooserWrapper activity = (IChooserWrapper)
715                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
716          waitForIdle();
717  
718          // The other entry is filtered to the last used slot
719          assertThat(activity.getAdapter().getCount(), is(2));
720  
721          ResolveInfo[] chosen = new ResolveInfo[1];
722          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
723              chosen[0] = targetInfo.getResolveInfo();
724              return true;
725          };
726  
727          // Make a stable copy of the components as the original list may be modified
728          List<ResolvedComponentInfo> stableCopy =
729                  createResolvedComponentsForTestWithOtherProfile(3);
730          onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
731                  .perform(click());
732          waitForIdle();
733          assertThat(chosen[0], is(toChoose));
734      }
735  
736      @Test
copyTextToClipboard()737      public void copyTextToClipboard() throws Exception {
738          Intent sendIntent = createSendTextIntent();
739          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
740  
741          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
742              Mockito.anyBoolean(),
743              Mockito.anyBoolean(),
744              Mockito.anyBoolean(),
745              Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
746  
747          final ChooserActivity activity =
748                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
749          waitForIdle();
750  
751          onView(withIdFromRuntimeResource("chooser_copy_button")).check(matches(isDisplayed()));
752          onView(withIdFromRuntimeResource("chooser_copy_button")).perform(click());
753          ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(
754                  Context.CLIPBOARD_SERVICE);
755          ClipData clipData = clipboard.getPrimaryClip();
756          assertThat("testing intent sending", is(clipData.getItemAt(0).getText()));
757  
758          ClipDescription clipDescription = clipData.getDescription();
759          assertThat("text/plain", is(clipDescription.getMimeType(0)));
760  
761          assertEquals(mActivityRule.getActivityResult().getResultCode(), RESULT_OK);
762      }
763  
764      @Test
copyTextToClipboardLogging()765      public void copyTextToClipboardLogging() throws Exception {
766          Intent sendIntent = createSendTextIntent();
767          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
768  
769          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
770              Mockito.anyBoolean(),
771              Mockito.anyBoolean(),
772              Mockito.anyBoolean(),
773              Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
774  
775          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
776          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
777  
778          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
779          waitForIdle();
780  
781          onView(withIdFromRuntimeResource("chooser_copy_button")).check(matches(isDisplayed()));
782          onView(withIdFromRuntimeResource("chooser_copy_button")).perform(click());
783  
784          verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
785  
786          // The last captured event is the selection of the target.
787          assertThat(logMakerCaptor.getValue().getCategory(),
788                  is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SYSTEM_TARGET));
789          assertThat(logMakerCaptor.getValue().getSubtype(), is(1));
790      }
791  
792  
793      @Test
794      @Ignore
testNearbyShareLogging()795      public void testNearbyShareLogging() throws Exception {
796          Intent sendIntent = createSendTextIntent();
797          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
798  
799          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
800                  Mockito.anyBoolean(),
801                  Mockito.anyBoolean(),
802                  Mockito.anyBoolean(),
803                  Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
804  
805          final IChooserWrapper activity = (IChooserWrapper)
806                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
807          waitForIdle();
808  
809          onView(withIdFromRuntimeResource("chooser_nearby_button")).check(matches(isDisplayed()));
810          onView(withIdFromRuntimeResource("chooser_nearby_button")).perform(click());
811  
812          ChooserActivityLoggerFake logger =
813                  (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
814  
815          // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events.
816          logger.removeCallsForUiEventsOfType(
817                  ChooserActivityLogger.SharesheetStandardEvent
818                          .SHARESHEET_DIRECT_LOAD_COMPLETE.getId());
819  
820          // SHARESHEET_TRIGGERED:
821          assertThat(logger.event(0).getId(),
822                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
823  
824          // SHARESHEET_STARTED:
825          assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
826          assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
827          assertThat(logger.get(1).mimeType, is("text/plain"));
828          assertThat(logger.get(1).packageName, is(
829                  InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName()));
830          assertThat(logger.get(1).appProvidedApp, is(0));
831          assertThat(logger.get(1).appProvidedDirect, is(0));
832          assertThat(logger.get(1).isWorkprofile, is(false));
833          assertThat(logger.get(1).previewType, is(3));
834  
835          // SHARESHEET_APP_LOAD_COMPLETE:
836          assertThat(logger.event(2).getId(),
837                  is(ChooserActivityLogger
838                          .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
839  
840          // Next are just artifacts of test set-up:
841          assertThat(logger.event(3).getId(),
842                  is(ChooserActivityLogger
843                          .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
844          assertThat(logger.event(4).getId(),
845                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId()));
846  
847          // SHARESHEET_NEARBY_TARGET_SELECTED:
848          assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
849          assertThat(logger.get(5).targetType,
850                  is(ChooserActivityLogger
851                          .SharesheetTargetSelectedEvent.SHARESHEET_NEARBY_TARGET_SELECTED.getId()));
852  
853          // No more events.
854          assertThat(logger.numCalls(), is(6));
855      }
856  
857  
858  
859      @Test @Ignore
testEditImageLogs()860      public void testEditImageLogs() throws Exception {
861          Intent sendIntent = createSendImageIntent(
862                  Uri.parse("android.resource://com.android.frameworks.coretests/"
863                          + com.android.frameworks.coretests.R.drawable.test320x240));
864  
865          ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap();
866          ChooserActivityOverrideData.getInstance().isImageType = true;
867  
868          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
869  
870          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
871                  Mockito.anyBoolean(),
872                  Mockito.anyBoolean(),
873                  Mockito.anyBoolean(),
874                  Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
875  
876          final IChooserWrapper activity = (IChooserWrapper)
877                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
878          waitForIdle();
879  
880          onView(withIdFromRuntimeResource("chooser_edit_button")).check(matches(isDisplayed()));
881          onView(withIdFromRuntimeResource("chooser_edit_button")).perform(click());
882  
883          ChooserActivityLoggerFake logger =
884                  (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
885  
886          // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events.
887          logger.removeCallsForUiEventsOfType(
888                  ChooserActivityLogger.SharesheetStandardEvent
889                          .SHARESHEET_DIRECT_LOAD_COMPLETE.getId());
890  
891          // SHARESHEET_TRIGGERED:
892          assertThat(logger.event(0).getId(),
893                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
894  
895          // SHARESHEET_STARTED:
896          assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
897          assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
898          assertThat(logger.get(1).mimeType, is("image/png"));
899          assertThat(logger.get(1).packageName, is(
900                  InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName()));
901          assertThat(logger.get(1).appProvidedApp, is(0));
902          assertThat(logger.get(1).appProvidedDirect, is(0));
903          assertThat(logger.get(1).isWorkprofile, is(false));
904          assertThat(logger.get(1).previewType, is(1));
905  
906          // SHARESHEET_APP_LOAD_COMPLETE:
907          assertThat(logger.event(2).getId(),
908                  is(ChooserActivityLogger
909                          .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
910  
911          // Next are just artifacts of test set-up:
912          assertThat(logger.event(3).getId(),
913                  is(ChooserActivityLogger
914                          .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
915          assertThat(logger.event(4).getId(),
916                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId()));
917  
918          // SHARESHEET_EDIT_TARGET_SELECTED:
919          assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
920          assertThat(logger.get(5).targetType,
921                  is(ChooserActivityLogger
922                          .SharesheetTargetSelectedEvent.SHARESHEET_EDIT_TARGET_SELECTED.getId()));
923  
924          // No more events.
925          assertThat(logger.numCalls(), is(6));
926      }
927  
928  
929      @Test
oneVisibleImagePreview()930      public void oneVisibleImagePreview() throws InterruptedException {
931          Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
932                  + com.android.frameworks.coretests.R.drawable.test320x240);
933  
934          ArrayList<Uri> uris = new ArrayList<>();
935          uris.add(uri);
936  
937          Intent sendIntent = createSendUriIntentWithPreview(uris);
938          ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap();
939          ChooserActivityOverrideData.getInstance().isImageType = true;
940  
941          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
942  
943          when(
944                  ChooserActivityOverrideData
945                          .getInstance()
946                          .resolverListController
947                          .getResolversForIntent(
948                                  Mockito.anyBoolean(),
949                                  Mockito.anyBoolean(),
950                                  Mockito.anyBoolean(),
951                                  Mockito.isA(List.class)))
952                  .thenReturn(resolvedComponentInfos);
953          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
954          waitForIdle();
955          onView(withIdFromRuntimeResource("content_preview_image_1_large"))
956                  .check(matches(isDisplayed()));
957          onView(withIdFromRuntimeResource("content_preview_image_2_large"))
958                  .check(matches(not(isDisplayed())));
959          onView(withIdFromRuntimeResource("content_preview_image_2_small"))
960                  .check(matches(not(isDisplayed())));
961          onView(withIdFromRuntimeResource("content_preview_image_3_small"))
962                  .check(matches(not(isDisplayed())));
963      }
964  
965      @Test
twoVisibleImagePreview()966      public void twoVisibleImagePreview() throws InterruptedException {
967          Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
968                  + com.android.frameworks.coretests.R.drawable.test320x240);
969  
970          ArrayList<Uri> uris = new ArrayList<>();
971          uris.add(uri);
972          uris.add(uri);
973  
974          Intent sendIntent = createSendUriIntentWithPreview(uris);
975          ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap();
976          ChooserActivityOverrideData.getInstance().isImageType = true;
977  
978          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
979  
980          when(
981                  ChooserActivityOverrideData
982                          .getInstance()
983                          .resolverListController
984                          .getResolversForIntent(
985                                  Mockito.anyBoolean(),
986                                  Mockito.anyBoolean(),
987                                  Mockito.anyBoolean(),
988                                  Mockito.isA(List.class)))
989                  .thenReturn(resolvedComponentInfos);
990          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
991          waitForIdle();
992          onView(withIdFromRuntimeResource("content_preview_image_1_large"))
993                  .check(matches(isDisplayed()));
994          onView(withIdFromRuntimeResource("content_preview_image_2_large"))
995                  .check(matches(isDisplayed()));
996          onView(withIdFromRuntimeResource("content_preview_image_2_small"))
997                  .check(matches(not(isDisplayed())));
998          onView(withIdFromRuntimeResource("content_preview_image_3_small"))
999                  .check(matches(not(isDisplayed())));
1000      }
1001  
1002      @Test
threeOrMoreVisibleImagePreview()1003      public void threeOrMoreVisibleImagePreview() throws InterruptedException {
1004          Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
1005                  + com.android.frameworks.coretests.R.drawable.test320x240);
1006  
1007          ArrayList<Uri> uris = new ArrayList<>();
1008          uris.add(uri);
1009          uris.add(uri);
1010          uris.add(uri);
1011          uris.add(uri);
1012          uris.add(uri);
1013  
1014          Intent sendIntent = createSendUriIntentWithPreview(uris);
1015          ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap();
1016          ChooserActivityOverrideData.getInstance().isImageType = true;
1017  
1018          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1019  
1020          when(
1021                  ChooserActivityOverrideData
1022                          .getInstance()
1023                          .resolverListController
1024                          .getResolversForIntent(
1025                                  Mockito.anyBoolean(),
1026                                  Mockito.anyBoolean(),
1027                                  Mockito.anyBoolean(),
1028                                  Mockito.isA(List.class)))
1029                  .thenReturn(resolvedComponentInfos);
1030          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1031          waitForIdle();
1032          onView(withIdFromRuntimeResource("content_preview_image_1_large"))
1033                  .check(matches(isDisplayed()));
1034          onView(withIdFromRuntimeResource("content_preview_image_2_large"))
1035                  .check(matches(not(isDisplayed())));
1036          onView(withIdFromRuntimeResource("content_preview_image_2_small"))
1037                  .check(matches(isDisplayed()));
1038          onView(withIdFromRuntimeResource("content_preview_image_3_small"))
1039                  .check(matches(isDisplayed()));
1040      }
1041  
1042      @Test
testOnCreateLogging()1043      public void testOnCreateLogging() {
1044          Intent sendIntent = createSendTextIntent();
1045          sendIntent.setType(TEST_MIME_TYPE);
1046  
1047          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
1048          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1049          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
1050          waitForIdle();
1051          verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
1052          assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
1053                  is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
1054          assertThat(logMakerCaptor
1055                  .getAllValues().get(0)
1056                  .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
1057                  is(notNullValue()));
1058          assertThat(logMakerCaptor
1059                  .getAllValues().get(0)
1060                  .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
1061                  is(TEST_MIME_TYPE));
1062          assertThat(logMakerCaptor
1063                          .getAllValues().get(0)
1064                          .getSubtype(),
1065                  is(MetricsEvent.PARENT_PROFILE));
1066      }
1067  
1068      @Test
testOnCreateLoggingFromWorkProfile()1069      public void testOnCreateLoggingFromWorkProfile() {
1070          Intent sendIntent = createSendTextIntent();
1071          sendIntent.setType(TEST_MIME_TYPE);
1072          ChooserActivityOverrideData.getInstance().alternateProfileSetting =
1073                  MetricsEvent.MANAGED_PROFILE;
1074          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
1075          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1076          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
1077          waitForIdle();
1078          verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
1079          assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
1080                  is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
1081          assertThat(logMakerCaptor
1082                          .getAllValues().get(0)
1083                          .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
1084                  is(notNullValue()));
1085          assertThat(logMakerCaptor
1086                          .getAllValues().get(0)
1087                          .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
1088                  is(TEST_MIME_TYPE));
1089          assertThat(logMakerCaptor
1090                          .getAllValues().get(0)
1091                          .getSubtype(),
1092                  is(MetricsEvent.MANAGED_PROFILE));
1093      }
1094  
1095      @Test
testEmptyPreviewLogging()1096      public void testEmptyPreviewLogging() {
1097          Intent sendIntent = createSendTextIntentWithPreview(null, null);
1098  
1099          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
1100          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1101          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "empty preview logger test"));
1102          waitForIdle();
1103  
1104          verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
1105          // First invocation is from onCreate
1106          assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
1107                  is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
1108      }
1109  
1110      @Test
testTitlePreviewLogging()1111      public void testTitlePreviewLogging() {
1112          Intent sendIntent = createSendTextIntentWithPreview("TestTitle", null);
1113  
1114          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
1115          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1116  
1117          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1118  
1119          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
1120              Mockito.anyBoolean(),
1121              Mockito.anyBoolean(),
1122              Mockito.anyBoolean(),
1123              Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1124  
1125          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1126          waitForIdle();
1127          // Second invocation is from onCreate
1128          verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
1129          assertThat(logMakerCaptor.getAllValues().get(0).getSubtype(),
1130                  is(CONTENT_PREVIEW_TEXT));
1131          assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
1132                  is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
1133      }
1134  
1135      @Test
testImagePreviewLogging()1136      public void testImagePreviewLogging() {
1137          Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
1138                  + com.android.frameworks.coretests.R.drawable.test320x240);
1139  
1140          ArrayList<Uri> uris = new ArrayList<>();
1141          uris.add(uri);
1142  
1143          Intent sendIntent = createSendUriIntentWithPreview(uris);
1144          ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap();
1145          ChooserActivityOverrideData.getInstance().isImageType = true;
1146  
1147          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1148  
1149          when(
1150                  ChooserActivityOverrideData
1151                          .getInstance()
1152                          .resolverListController
1153                          .getResolversForIntent(
1154                                  Mockito.anyBoolean(),
1155                                  Mockito.anyBoolean(),
1156                                  Mockito.anyBoolean(),
1157                                  Mockito.isA(List.class)))
1158                  .thenReturn(resolvedComponentInfos);
1159  
1160          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
1161          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1162          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1163          waitForIdle();
1164          verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
1165          // First invocation is from onCreate
1166          assertThat(logMakerCaptor.getAllValues().get(0).getSubtype(),
1167                  is(CONTENT_PREVIEW_IMAGE));
1168          assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
1169                  is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
1170      }
1171  
1172      @Test
oneVisibleFilePreview()1173      public void oneVisibleFilePreview() throws InterruptedException {
1174          Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
1175  
1176          ArrayList<Uri> uris = new ArrayList<>();
1177          uris.add(uri);
1178  
1179          Intent sendIntent = createSendUriIntentWithPreview(uris);
1180  
1181          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1182  
1183          when(
1184                  ChooserActivityOverrideData
1185                      .getInstance()
1186                      .resolverListController
1187                      .getResolversForIntent(
1188                              Mockito.anyBoolean(),
1189                              Mockito.anyBoolean(),
1190                              Mockito.anyBoolean(),
1191                              Mockito.isA(List.class)))
1192                  .thenReturn(resolvedComponentInfos);
1193          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1194          waitForIdle();
1195          onView(withIdFromRuntimeResource("content_preview_filename")).check(matches(isDisplayed()));
1196          onView(withIdFromRuntimeResource("content_preview_filename"))
1197                  .check(matches(withText("app.pdf")));
1198          onView(withIdFromRuntimeResource("content_preview_file_icon"))
1199                  .check(matches(isDisplayed()));
1200      }
1201  
1202  
1203      @Test
moreThanOneVisibleFilePreview()1204      public void moreThanOneVisibleFilePreview() throws InterruptedException {
1205          Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
1206  
1207          ArrayList<Uri> uris = new ArrayList<>();
1208          uris.add(uri);
1209          uris.add(uri);
1210          uris.add(uri);
1211  
1212          Intent sendIntent = createSendUriIntentWithPreview(uris);
1213  
1214          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1215  
1216          when(
1217                  ChooserActivityOverrideData
1218                          .getInstance()
1219                          .resolverListController
1220                          .getResolversForIntent(
1221                                  Mockito.anyBoolean(),
1222                                  Mockito.anyBoolean(),
1223                                  Mockito.anyBoolean(),
1224                                  Mockito.isA(List.class)))
1225                  .thenReturn(resolvedComponentInfos);
1226          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1227          waitForIdle();
1228          onView(withIdFromRuntimeResource("content_preview_filename"))
1229                  .check(matches(isDisplayed()));
1230          onView(withIdFromRuntimeResource("content_preview_filename"))
1231                  .check(matches(withText("app.pdf + 2 files")));
1232          onView(withIdFromRuntimeResource("content_preview_file_icon"))
1233                  .check(matches(isDisplayed()));
1234      }
1235  
1236      @Test
contentProviderThrowSecurityException()1237      public void contentProviderThrowSecurityException() throws InterruptedException {
1238          Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
1239  
1240          ArrayList<Uri> uris = new ArrayList<>();
1241          uris.add(uri);
1242  
1243          Intent sendIntent = createSendUriIntentWithPreview(uris);
1244  
1245          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1246          when(
1247                  ChooserActivityOverrideData
1248                          .getInstance()
1249                          .resolverListController
1250                          .getResolversForIntent(
1251                                  Mockito.anyBoolean(),
1252                                  Mockito.anyBoolean(),
1253                                  Mockito.anyBoolean(),
1254                                  Mockito.isA(List.class)))
1255                  .thenReturn(resolvedComponentInfos);
1256  
1257          ChooserActivityOverrideData.getInstance().resolverForceException = true;
1258  
1259          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1260          waitForIdle();
1261          onView(withIdFromRuntimeResource("content_preview_filename")).check(matches(isDisplayed()));
1262          onView(withIdFromRuntimeResource("content_preview_filename"))
1263                  .check(matches(withText("app.pdf")));
1264          onView(withIdFromRuntimeResource("content_preview_file_icon"))
1265                  .check(matches(isDisplayed()));
1266      }
1267  
1268      @Test
contentProviderReturnsNoColumns()1269      public void contentProviderReturnsNoColumns() throws InterruptedException {
1270          Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
1271  
1272          ArrayList<Uri> uris = new ArrayList<>();
1273          uris.add(uri);
1274          uris.add(uri);
1275  
1276          Intent sendIntent = createSendUriIntentWithPreview(uris);
1277  
1278          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1279          when(
1280                  ChooserActivityOverrideData
1281                          .getInstance()
1282                          .resolverListController
1283                          .getResolversForIntent(
1284                                  Mockito.anyBoolean(),
1285                                  Mockito.anyBoolean(),
1286                                  Mockito.anyBoolean(),
1287                                  Mockito.isA(List.class)))
1288                  .thenReturn(resolvedComponentInfos);
1289  
1290          Cursor cursor = mock(Cursor.class);
1291          when(cursor.getCount()).thenReturn(1);
1292          Mockito.doNothing().when(cursor).close();
1293          when(cursor.moveToFirst()).thenReturn(true);
1294          when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1);
1295  
1296          ChooserActivityOverrideData.getInstance().resolverCursor = cursor;
1297  
1298          mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1299          waitForIdle();
1300          onView(withIdFromRuntimeResource("content_preview_filename")).check(matches(isDisplayed()));
1301          onView(withIdFromRuntimeResource("content_preview_filename"))
1302                  .check(matches(withText("app.pdf + 1 file")));
1303          onView(withIdFromRuntimeResource("content_preview_file_icon"))
1304                  .check(matches(isDisplayed()));
1305      }
1306  
1307      @Test
testGetBaseScore()1308      public void testGetBaseScore() {
1309          final float testBaseScore = 0.89f;
1310  
1311          Intent sendIntent = createSendTextIntent();
1312          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1313  
1314          when(
1315                  ChooserActivityOverrideData
1316                          .getInstance()
1317                          .resolverListController
1318                          .getResolversForIntent(
1319                                  Mockito.anyBoolean(),
1320                                  Mockito.anyBoolean(),
1321                                  Mockito.anyBoolean(),
1322                                  Mockito.isA(List.class)))
1323                  .thenReturn(resolvedComponentInfos);
1324          when(
1325                  ChooserActivityOverrideData
1326                          .getInstance()
1327                          .resolverListController
1328                          .getScore(Mockito.isA(DisplayResolveInfo.class)))
1329                  .thenReturn(testBaseScore);
1330  
1331          final IChooserWrapper activity = (IChooserWrapper)
1332                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1333          waitForIdle();
1334  
1335          final DisplayResolveInfo testDri =
1336                  activity.createTestDisplayResolveInfo(sendIntent,
1337                  ResolverDataProvider.createResolveInfo(
1338                          3, 0, PERSONAL_USER_HANDLE),
1339                          "testLabel",
1340                          "testInfo",
1341                          sendIntent,
1342                  /* resolveInfoPresentationGetter */ null);
1343          final ChooserListAdapter adapter = activity.getAdapter();
1344  
1345          assertThat(adapter.getBaseScore(null, 0), is(CALLER_TARGET_SCORE_BOOST));
1346          assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_DEFAULT), is(testBaseScore));
1347          assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_CHOOSER_TARGET), is(testBaseScore));
1348          assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE),
1349                  is(testBaseScore * SHORTCUT_TARGET_SCORE_BOOST));
1350          assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER),
1351                  is(testBaseScore * SHORTCUT_TARGET_SCORE_BOOST));
1352      }
1353  
1354      @Test
testConvertToChooserTarget_predictionService()1355      public void testConvertToChooserTarget_predictionService() {
1356          Intent sendIntent = createSendTextIntent();
1357          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1358          when(
1359                  ChooserActivityOverrideData
1360                          .getInstance()
1361                          .resolverListController
1362                          .getResolversForIntent(
1363                                  Mockito.anyBoolean(),
1364                                  Mockito.anyBoolean(),
1365                                  Mockito.anyBoolean(),
1366                                  Mockito.isA(List.class)))
1367                  .thenReturn(resolvedComponentInfos);
1368  
1369          final ChooserActivity activity =
1370                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1371          waitForIdle();
1372  
1373          List<ShareShortcutInfo> shortcuts = createShortcuts(activity);
1374  
1375          int[] expectedOrderAllShortcuts = {0, 1, 2, 3};
1376          float[] expectedScoreAllShortcuts = {1.0f, 0.99f, 0.98f, 0.97f};
1377  
1378          List<ChooserTarget> chooserTargets = activity.convertToChooserTarget(shortcuts, shortcuts,
1379                  null, TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE);
1380          assertCorrectShortcutToChooserTargetConversion(shortcuts, chooserTargets,
1381                  expectedOrderAllShortcuts, expectedScoreAllShortcuts);
1382  
1383          List<ShareShortcutInfo> subset = new ArrayList<>();
1384          subset.add(shortcuts.get(1));
1385          subset.add(shortcuts.get(2));
1386          subset.add(shortcuts.get(3));
1387  
1388          int[] expectedOrderSubset = {1, 2, 3};
1389          float[] expectedScoreSubset = {0.99f, 0.98f, 0.97f};
1390  
1391          chooserTargets = activity.convertToChooserTarget(subset, shortcuts, null,
1392                  TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE);
1393          assertCorrectShortcutToChooserTargetConversion(shortcuts, chooserTargets,
1394                  expectedOrderSubset, expectedScoreSubset);
1395      }
1396  
1397      @Test
testConvertToChooserTarget_shortcutManager()1398      public void testConvertToChooserTarget_shortcutManager() {
1399          Intent sendIntent = createSendTextIntent();
1400          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1401          when(
1402                  ChooserActivityOverrideData
1403                          .getInstance()
1404                          .resolverListController
1405                          .getResolversForIntent(
1406                                  Mockito.anyBoolean(),
1407                                  Mockito.anyBoolean(),
1408                                  Mockito.anyBoolean(),
1409                                  Mockito.isA(List.class)))
1410                  .thenReturn(resolvedComponentInfos);
1411  
1412          final ChooserActivity activity =
1413                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1414          waitForIdle();
1415  
1416          List<ShareShortcutInfo> shortcuts = createShortcuts(activity);
1417  
1418          int[] expectedOrderAllShortcuts = {2, 0, 3, 1};
1419          float[] expectedScoreAllShortcuts = {1.0f, 0.99f, 0.99f, 0.98f};
1420  
1421          List<ChooserTarget> chooserTargets = activity.convertToChooserTarget(shortcuts, shortcuts,
1422                  null, TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER);
1423          assertCorrectShortcutToChooserTargetConversion(shortcuts, chooserTargets,
1424                  expectedOrderAllShortcuts, expectedScoreAllShortcuts);
1425  
1426          List<ShareShortcutInfo> subset = new ArrayList<>();
1427          subset.add(shortcuts.get(1));
1428          subset.add(shortcuts.get(2));
1429          subset.add(shortcuts.get(3));
1430  
1431          int[] expectedOrderSubset = {2, 3, 1};
1432          float[] expectedScoreSubset = {1.0f, 0.99f, 0.98f};
1433  
1434          chooserTargets = activity.convertToChooserTarget(subset, shortcuts, null,
1435                  TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER);
1436          assertCorrectShortcutToChooserTargetConversion(shortcuts, chooserTargets,
1437                  expectedOrderSubset, expectedScoreSubset);
1438      }
1439  
1440      // This test is too long and too slow and should not be taken as an example for future tests.
1441      @Test @Ignore
testDirectTargetSelectionLogging()1442      public void testDirectTargetSelectionLogging() throws InterruptedException {
1443          Intent sendIntent = createSendTextIntent();
1444          // We need app targets for direct targets to get displayed
1445          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1446          when(
1447                  ChooserActivityOverrideData
1448                          .getInstance()
1449                          .resolverListController
1450                          .getResolversForIntent(
1451                                  Mockito.anyBoolean(),
1452                                  Mockito.anyBoolean(),
1453                                  Mockito.anyBoolean(),
1454                                  Mockito.isA(List.class)))
1455                  .thenReturn(resolvedComponentInfos);
1456  
1457          // Set up resources
1458          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
1459          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1460          // Create direct share target
1461          List<ChooserTarget> serviceTargets = createDirectShareTargets(1, "");
1462          ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
1463                  PERSONAL_USER_HANDLE);
1464  
1465          // Start activity
1466          final IChooserWrapper activity = (IChooserWrapper)
1467                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1468  
1469          // Insert the direct share target
1470          Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1471          directShareToShortcutInfos.put(serviceTargets.get(0), null);
1472          InstrumentationRegistry.getInstrumentation().runOnMainSync(
1473                  () -> activity.getAdapter().addServiceResults(
1474                          activity.createTestDisplayResolveInfo(sendIntent,
1475                                  ri,
1476                                  "testLabel",
1477                                  "testInfo",
1478                                  sendIntent,
1479                                  /* resolveInfoPresentationGetter */ null),
1480                          serviceTargets,
1481                          TARGET_TYPE_CHOOSER_TARGET,
1482                          directShareToShortcutInfos)
1483          );
1484  
1485          // Thread.sleep shouldn't be a thing in an integration test but it's
1486          // necessary here because of the way the code is structured
1487          // TODO: restructure the tests b/129870719
1488          Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs);
1489  
1490          assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
1491                  activity.getAdapter().getCount(), is(3));
1492          assertThat("Chooser should have exactly one selectable direct target",
1493                  activity.getAdapter().getSelectableServiceTargetCount(), is(1));
1494          assertThat("The resolver info must match the resolver info used to create the target",
1495                  activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
1496  
1497          // Click on the direct target
1498          String name = serviceTargets.get(0).getTitle().toString();
1499          onView(withText(name))
1500                  .perform(click());
1501          waitForIdle();
1502  
1503          // Currently we're seeing 3 invocations
1504          //      1. ChooserActivity.onCreate()
1505          //      2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
1506          //      3. ChooserActivity.startSelected -- which is the one we're after
1507          verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
1508          assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
1509                  is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
1510          String hashedName = (String) logMakerCaptor
1511                  .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_HASHED_TARGET_NAME);
1512          assertThat("Hash is not predictable but must be obfuscated",
1513                  hashedName, is(not(name)));
1514          assertThat("The packages shouldn't match for app target and direct target", logMakerCaptor
1515                  .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
1516      }
1517  
1518      // This test is too long and too slow and should not be taken as an example for future tests.
1519      @Test @Ignore
testDirectTargetLoggingWithRankedAppTarget()1520      public void testDirectTargetLoggingWithRankedAppTarget() throws InterruptedException {
1521          Intent sendIntent = createSendTextIntent();
1522          // We need app targets for direct targets to get displayed
1523          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1524          when(
1525                  ChooserActivityOverrideData
1526                          .getInstance()
1527                          .resolverListController
1528                          .getResolversForIntent(
1529                                  Mockito.anyBoolean(),
1530                                  Mockito.anyBoolean(),
1531                                  Mockito.anyBoolean(),
1532                                  Mockito.isA(List.class)))
1533                  .thenReturn(resolvedComponentInfos);
1534  
1535          // Set up resources
1536          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
1537          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1538          // Create direct share target
1539          List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
1540                  resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
1541          ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
1542                  PERSONAL_USER_HANDLE);
1543  
1544          // Start activity
1545          final IChooserWrapper activity = (IChooserWrapper)
1546                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1547  
1548          // Insert the direct share target
1549          Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1550          directShareToShortcutInfos.put(serviceTargets.get(0), null);
1551          InstrumentationRegistry.getInstrumentation().runOnMainSync(
1552                  () -> activity.getAdapter().addServiceResults(
1553                          activity.createTestDisplayResolveInfo(sendIntent,
1554                                  ri,
1555                                  "testLabel",
1556                                  "testInfo",
1557                                  sendIntent,
1558                                  /* resolveInfoPresentationGetter */ null),
1559                          serviceTargets,
1560                          TARGET_TYPE_CHOOSER_TARGET,
1561                          directShareToShortcutInfos)
1562          );
1563          // Thread.sleep shouldn't be a thing in an integration test but it's
1564          // necessary here because of the way the code is structured
1565          // TODO: restructure the tests b/129870719
1566          Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs);
1567  
1568          assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
1569                  activity.getAdapter().getCount(), is(3));
1570          assertThat("Chooser should have exactly one selectable direct target",
1571                  activity.getAdapter().getSelectableServiceTargetCount(), is(1));
1572          assertThat("The resolver info must match the resolver info used to create the target",
1573                  activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
1574  
1575          // Click on the direct target
1576          String name = serviceTargets.get(0).getTitle().toString();
1577          onView(withText(name))
1578                  .perform(click());
1579          waitForIdle();
1580  
1581          // Currently we're seeing 3 invocations
1582          //      1. ChooserActivity.onCreate()
1583          //      2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
1584          //      3. ChooserActivity.startSelected -- which is the one we're after
1585          verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
1586          assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
1587                  is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
1588          assertThat("The packages should match for app target and direct target", logMakerCaptor
1589                  .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(0));
1590      }
1591  
1592      @Test @Ignore
testShortcutTargetWithApplyAppLimits()1593      public void testShortcutTargetWithApplyAppLimits() throws InterruptedException {
1594          // Set up resources
1595          ChooserActivityOverrideData.getInstance().resources = Mockito.spy(
1596                  InstrumentationRegistry.getInstrumentation().getContext().getResources());
1597          when(
1598                  ChooserActivityOverrideData
1599                          .getInstance()
1600                          .resources
1601                          .getInteger(
1602                                getRuntimeResourceId("config_maxShortcutTargetsPerApp", "integer")))
1603                  .thenReturn(1);
1604          Intent sendIntent = createSendTextIntent();
1605          // We need app targets for direct targets to get displayed
1606          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1607          when(
1608                  ChooserActivityOverrideData
1609                          .getInstance()
1610                          .resolverListController
1611                          .getResolversForIntent(
1612                                  Mockito.anyBoolean(),
1613                                  Mockito.anyBoolean(),
1614                                  Mockito.anyBoolean(),
1615                                  Mockito.isA(List.class)))
1616                  .thenReturn(resolvedComponentInfos);
1617          // Create direct share target
1618          List<ChooserTarget> serviceTargets = createDirectShareTargets(2,
1619                  resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
1620          ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
1621                  PERSONAL_USER_HANDLE);
1622  
1623          // Start activity
1624          final ChooserActivity activity =
1625                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1626          final IChooserWrapper wrapper = (IChooserWrapper) activity;
1627  
1628          // Insert the direct share target
1629          Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1630          List<ShareShortcutInfo> shortcutInfos = createShortcuts(activity);
1631          directShareToShortcutInfos.put(serviceTargets.get(0),
1632                  shortcutInfos.get(0).getShortcutInfo());
1633          directShareToShortcutInfos.put(serviceTargets.get(1),
1634                  shortcutInfos.get(1).getShortcutInfo());
1635          InstrumentationRegistry.getInstrumentation().runOnMainSync(
1636                  () -> wrapper.getAdapter().addServiceResults(
1637                          wrapper.createTestDisplayResolveInfo(sendIntent,
1638                                  ri,
1639                                  "testLabel",
1640                                  "testInfo",
1641                                  sendIntent,
1642                                  /* resolveInfoPresentationGetter */ null),
1643                          serviceTargets,
1644                          TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE,
1645                          directShareToShortcutInfos)
1646          );
1647          // Thread.sleep shouldn't be a thing in an integration test but it's
1648          // necessary here because of the way the code is structured
1649          // TODO: restructure the tests b/129870719
1650          Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs);
1651  
1652          assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
1653                  wrapper.getAdapter().getCount(), is(3));
1654          assertThat("Chooser should have exactly one selectable direct target",
1655                  wrapper.getAdapter().getSelectableServiceTargetCount(), is(1));
1656          assertThat("The resolver info must match the resolver info used to create the target",
1657                  wrapper.getAdapter().getItem(0).getResolveInfo(), is(ri));
1658          assertThat("The display label must match",
1659                  wrapper.getAdapter().getItem(0).getDisplayLabel(), is("testTitle0"));
1660      }
1661  
1662      @Test @Ignore
testShortcutTargetWithoutApplyAppLimits()1663      public void testShortcutTargetWithoutApplyAppLimits() throws InterruptedException {
1664          DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
1665                  SystemUiDeviceConfigFlags.APPLY_SHARING_APP_LIMITS_IN_SYSUI,
1666                  Boolean.toString(false),
1667                  true /* makeDefault*/);
1668          // Set up resources
1669          ChooserActivityOverrideData.getInstance().resources = Mockito.spy(
1670                  InstrumentationRegistry.getInstrumentation().getContext().getResources());
1671          when(
1672                  ChooserActivityOverrideData
1673                          .getInstance()
1674                          .resources
1675                          .getInteger(
1676                                getRuntimeResourceId("config_maxShortcutTargetsPerApp", "integer")))
1677                  .thenReturn(1);
1678          Intent sendIntent = createSendTextIntent();
1679          // We need app targets for direct targets to get displayed
1680          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1681          when(
1682                  ChooserActivityOverrideData
1683                          .getInstance()
1684                          .resolverListController
1685                          .getResolversForIntent(
1686                                  Mockito.anyBoolean(),
1687                                  Mockito.anyBoolean(),
1688                                  Mockito.anyBoolean(),
1689                                  Mockito.isA(List.class)))
1690                  .thenReturn(resolvedComponentInfos);
1691          // Create direct share target
1692          List<ChooserTarget> serviceTargets = createDirectShareTargets(2,
1693                  resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
1694          ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
1695                  PERSONAL_USER_HANDLE);
1696  
1697          // Start activity
1698          final ChooserActivity activity =
1699                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1700          final IChooserWrapper wrapper = (IChooserWrapper) activity;
1701  
1702          // Insert the direct share target
1703          Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1704          List<ShareShortcutInfo> shortcutInfos = createShortcuts(activity);
1705          directShareToShortcutInfos.put(serviceTargets.get(0),
1706                  shortcutInfos.get(0).getShortcutInfo());
1707          directShareToShortcutInfos.put(serviceTargets.get(1),
1708                  shortcutInfos.get(1).getShortcutInfo());
1709          InstrumentationRegistry.getInstrumentation().runOnMainSync(
1710                  () -> wrapper.getAdapter().addServiceResults(
1711                          wrapper.createTestDisplayResolveInfo(sendIntent,
1712                                  ri,
1713                                  "testLabel",
1714                                  "testInfo",
1715                                  sendIntent,
1716                                  /* resolveInfoPresentationGetter */ null),
1717                          serviceTargets,
1718                          TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE,
1719                          directShareToShortcutInfos)
1720          );
1721          // Thread.sleep shouldn't be a thing in an integration test but it's
1722          // necessary here because of the way the code is structured
1723          // TODO: restructure the tests b/129870719
1724          Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs);
1725  
1726          assertThat("Chooser should have 4 targets (2 apps, 2 direct)",
1727                  wrapper.getAdapter().getCount(), is(4));
1728          assertThat("Chooser should have exactly two selectable direct target",
1729                  wrapper.getAdapter().getSelectableServiceTargetCount(), is(2));
1730          assertThat("The resolver info must match the resolver info used to create the target",
1731                  wrapper.getAdapter().getItem(0).getResolveInfo(), is(ri));
1732          assertThat("The display label must match",
1733                  wrapper.getAdapter().getItem(0).getDisplayLabel(), is("testTitle0"));
1734          assertThat("The display label must match",
1735                  wrapper.getAdapter().getItem(1).getDisplayLabel(), is("testTitle1"));
1736      }
1737  
1738      @Test
testUpdateMaxTargetsPerRow_columnCountIsUpdated()1739      public void testUpdateMaxTargetsPerRow_columnCountIsUpdated() throws InterruptedException {
1740          updateMaxTargetsPerRowResource(/* targetsPerRow= */ 4);
1741          givenAppTargets(/* appCount= */ 16);
1742          Intent sendIntent = createSendTextIntent();
1743          final ChooserActivity activity =
1744                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1745  
1746          updateMaxTargetsPerRowResource(/* targetsPerRow= */ 6);
1747          InstrumentationRegistry.getInstrumentation()
1748                  .runOnMainSync(() -> activity.onConfigurationChanged(
1749                          InstrumentationRegistry.getInstrumentation()
1750                                  .getContext().getResources().getConfiguration()));
1751  
1752          waitForIdle();
1753          onView(withIdFromRuntimeResource("resolver_list"))
1754                  .check(matches(withGridColumnCount(6)));
1755      }
1756  
1757      // This test is too long and too slow and should not be taken as an example for future tests.
1758      @Test @Ignore
testDirectTargetLoggingWithAppTargetNotRankedPortrait()1759      public void testDirectTargetLoggingWithAppTargetNotRankedPortrait()
1760              throws InterruptedException {
1761          testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_PORTRAIT, 4);
1762      }
1763  
1764      @Test @Ignore
testDirectTargetLoggingWithAppTargetNotRankedLandscape()1765      public void testDirectTargetLoggingWithAppTargetNotRankedLandscape()
1766              throws InterruptedException {
1767          testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_LANDSCAPE, 8);
1768      }
1769  
testDirectTargetLoggingWithAppTargetNotRanked( int orientation, int appTargetsExpected )1770      private void testDirectTargetLoggingWithAppTargetNotRanked(
1771              int orientation, int appTargetsExpected
1772      ) throws InterruptedException {
1773          Configuration configuration =
1774                  new Configuration(InstrumentationRegistry.getInstrumentation().getContext()
1775                          .getResources().getConfiguration());
1776          configuration.orientation = orientation;
1777  
1778          ChooserActivityOverrideData.getInstance().resources = Mockito.spy(
1779                  InstrumentationRegistry.getInstrumentation().getContext().getResources());
1780          when(
1781                  ChooserActivityOverrideData
1782                          .getInstance()
1783                          .resources
1784                          .getConfiguration())
1785                  .thenReturn(configuration);
1786  
1787          Intent sendIntent = createSendTextIntent();
1788          // We need app targets for direct targets to get displayed
1789          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(15);
1790          when(
1791                  ChooserActivityOverrideData
1792                          .getInstance()
1793                          .resolverListController
1794                          .getResolversForIntent(
1795                                  Mockito.anyBoolean(),
1796                                  Mockito.anyBoolean(),
1797                                  Mockito.anyBoolean(),
1798                                  Mockito.isA(List.class)))
1799                  .thenReturn(resolvedComponentInfos);
1800  
1801          // Set up resources
1802          MetricsLogger mockLogger = ChooserActivityOverrideData.getInstance().metricsLogger;
1803          ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1804          // Create direct share target
1805          List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
1806                  resolvedComponentInfos.get(14).getResolveInfoAt(0).activityInfo.packageName);
1807          ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0,
1808                  PERSONAL_USER_HANDLE);
1809  
1810          // Start activity
1811          final IChooserWrapper activity = (IChooserWrapper)
1812                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
1813          final IChooserWrapper wrapper = (IChooserWrapper) activity;
1814          // Insert the direct share target
1815          Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1816          directShareToShortcutInfos.put(serviceTargets.get(0), null);
1817          InstrumentationRegistry.getInstrumentation().runOnMainSync(
1818                  () -> wrapper.getAdapter().addServiceResults(
1819                          wrapper.createTestDisplayResolveInfo(sendIntent,
1820                                  ri,
1821                                  "testLabel",
1822                                  "testInfo",
1823                                  sendIntent,
1824                                  /* resolveInfoPresentationGetter */ null),
1825                          serviceTargets,
1826                          TARGET_TYPE_CHOOSER_TARGET,
1827                          directShareToShortcutInfos)
1828          );
1829          // Thread.sleep shouldn't be a thing in an integration test but it's
1830          // necessary here because of the way the code is structured
1831          // TODO: restructure the tests b/129870719
1832          Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs);
1833  
1834          assertThat(
1835                  String.format("Chooser should have %d targets (%d apps, 1 direct, 15 A-Z)",
1836                          appTargetsExpected + 16, appTargetsExpected),
1837                  wrapper.getAdapter().getCount(), is(appTargetsExpected + 16));
1838          assertThat("Chooser should have exactly one selectable direct target",
1839                  wrapper.getAdapter().getSelectableServiceTargetCount(), is(1));
1840          assertThat("The resolver info must match the resolver info used to create the target",
1841                  wrapper.getAdapter().getItem(0).getResolveInfo(), is(ri));
1842  
1843          // Click on the direct target
1844          String name = serviceTargets.get(0).getTitle().toString();
1845          onView(withText(name))
1846                  .perform(click());
1847          waitForIdle();
1848  
1849          // Currently we're seeing 3 invocations
1850          //      1. ChooserActivity.onCreate()
1851          //      2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
1852          //      3. ChooserActivity.startSelected -- which is the one we're after
1853          verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
1854          assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
1855                  is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
1856          assertThat("The packages shouldn't match for app target and direct target", logMakerCaptor
1857                  .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
1858      }
1859  
1860      @Test
testWorkTab_displayedWhenWorkProfileUserAvailable()1861      public void testWorkTab_displayedWhenWorkProfileUserAvailable() {
1862          // enable the work tab feature flag
1863          ResolverActivity.ENABLE_TABBED_VIEW = true;
1864          Intent sendIntent = createSendTextIntent();
1865          sendIntent.setType(TEST_MIME_TYPE);
1866          markWorkProfileUserAvailable();
1867  
1868          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1869          waitForIdle();
1870  
1871          onView(withIdFromRuntimeResource("tabs")).check(matches(isDisplayed()));
1872      }
1873  
1874      @Test
testWorkTab_hiddenWhenWorkProfileUserNotAvailable()1875      public void testWorkTab_hiddenWhenWorkProfileUserNotAvailable() {
1876          // enable the work tab feature flag
1877          ResolverActivity.ENABLE_TABBED_VIEW = true;
1878          Intent sendIntent = createSendTextIntent();
1879          sendIntent.setType(TEST_MIME_TYPE);
1880  
1881          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1882          waitForIdle();
1883  
1884          onView(withIdFromRuntimeResource("tabs")).check(matches(not(isDisplayed())));
1885      }
1886  
1887      @Test
testWorkTab_eachTabUsesExpectedAdapter()1888      public void testWorkTab_eachTabUsesExpectedAdapter() {
1889          // enable the work tab feature flag
1890          ResolverActivity.ENABLE_TABBED_VIEW = true;
1891          int personalProfileTargets = 3;
1892          int otherProfileTargets = 1;
1893          List<ResolvedComponentInfo> personalResolvedComponentInfos =
1894                  createResolvedComponentsForTestWithOtherProfile(
1895                          personalProfileTargets + otherProfileTargets, /* userID */ 10);
1896          int workProfileTargets = 4;
1897          List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(
1898                  workProfileTargets);
1899          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1900          Intent sendIntent = createSendTextIntent();
1901          sendIntent.setType(TEST_MIME_TYPE);
1902          markWorkProfileUserAvailable();
1903  
1904          final IChooserWrapper activity = (IChooserWrapper)
1905                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1906          waitForIdle();
1907  
1908          assertThat(activity.getCurrentUserHandle().getIdentifier(), is(0));
1909          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
1910          assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
1911          assertThat(activity.getPersonalListAdapter().getCount(), is(personalProfileTargets));
1912          assertThat(activity.getWorkListAdapter().getCount(), is(workProfileTargets));
1913      }
1914  
1915      @Test
testWorkTab_workProfileHasExpectedNumberOfTargets()1916      public void testWorkTab_workProfileHasExpectedNumberOfTargets() throws InterruptedException {
1917          // enable the work tab feature flag
1918          ResolverActivity.ENABLE_TABBED_VIEW = true;
1919          markWorkProfileUserAvailable();
1920          int workProfileTargets = 4;
1921          List<ResolvedComponentInfo> personalResolvedComponentInfos =
1922                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
1923          List<ResolvedComponentInfo> workResolvedComponentInfos =
1924                  createResolvedComponentsForTest(workProfileTargets);
1925          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1926          Intent sendIntent = createSendTextIntent();
1927          sendIntent.setType(TEST_MIME_TYPE);
1928  
1929          final IChooserWrapper activity = (IChooserWrapper)
1930                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1931          waitForIdle();
1932          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
1933          waitForIdle();
1934  
1935          assertThat(activity.getWorkListAdapter().getCount(), is(workProfileTargets));
1936      }
1937  
1938      @Test @Ignore
testWorkTab_selectingWorkTabAppOpensAppInWorkProfile()1939      public void testWorkTab_selectingWorkTabAppOpensAppInWorkProfile() throws InterruptedException {
1940          // enable the work tab feature flag
1941          ResolverActivity.ENABLE_TABBED_VIEW = true;
1942          markWorkProfileUserAvailable();
1943          List<ResolvedComponentInfo> personalResolvedComponentInfos =
1944                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
1945          int workProfileTargets = 4;
1946          List<ResolvedComponentInfo> workResolvedComponentInfos =
1947                  createResolvedComponentsForTest(workProfileTargets);
1948          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1949          Intent sendIntent = createSendTextIntent();
1950          sendIntent.setType(TEST_MIME_TYPE);
1951          ResolveInfo[] chosen = new ResolveInfo[1];
1952          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
1953              chosen[0] = targetInfo.getResolveInfo();
1954              return true;
1955          };
1956  
1957          final IChooserWrapper activity = (IChooserWrapper)
1958                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1959          waitForIdle();
1960          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
1961          waitForIdle();
1962          // wait for the share sheet to expand
1963          Thread.sleep(((ChooserActivity) activity).mListViewUpdateDelayMs);
1964  
1965          onView(first(allOf(
1966                  withText(workResolvedComponentInfos.get(0)
1967                          .getResolveInfoAt(0).activityInfo.applicationInfo.name),
1968                  isDisplayed())))
1969                  .perform(click());
1970          waitForIdle();
1971          assertThat(chosen[0], is(workResolvedComponentInfos.get(0).getResolveInfoAt(0)));
1972      }
1973  
1974      @Test
testWorkTab_crossProfileIntentsDisabled_personalToWork_emptyStateShown()1975      public void testWorkTab_crossProfileIntentsDisabled_personalToWork_emptyStateShown() {
1976          // enable the work tab feature flag
1977          ResolverActivity.ENABLE_TABBED_VIEW = true;
1978          markWorkProfileUserAvailable();
1979          int workProfileTargets = 4;
1980          List<ResolvedComponentInfo> personalResolvedComponentInfos =
1981                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
1982          List<ResolvedComponentInfo> workResolvedComponentInfos =
1983                  createResolvedComponentsForTest(workProfileTargets);
1984          ChooserActivityOverrideData.getInstance().hasCrossProfileIntents = false;
1985          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1986          Intent sendIntent = createSendTextIntent();
1987          sendIntent.setType(TEST_MIME_TYPE);
1988  
1989          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1990          waitForIdle();
1991          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
1992          waitForIdle();
1993          onView(withIdFromRuntimeResource("contentPanel"))
1994                  .perform(swipeUp());
1995  
1996          onView(withTextFromRuntimeResource("resolver_cross_profile_blocked"))
1997                  .check(matches(isDisplayed()));
1998      }
1999  
2000      @Test
testWorkTab_workProfileDisabled_emptyStateShown()2001      public void testWorkTab_workProfileDisabled_emptyStateShown() {
2002          // enable the work tab feature flag
2003          markWorkProfileUserAvailable();
2004          int workProfileTargets = 4;
2005          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2006                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2007          List<ResolvedComponentInfo> workResolvedComponentInfos =
2008                  createResolvedComponentsForTest(workProfileTargets);
2009          ChooserActivityOverrideData.getInstance().isQuietModeEnabled = true;
2010          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2011          Intent sendIntent = createSendTextIntent();
2012          sendIntent.setType(TEST_MIME_TYPE);
2013  
2014          ResolverActivity.ENABLE_TABBED_VIEW = true;
2015          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2016          waitForIdle();
2017          onView(withIdFromRuntimeResource("contentPanel"))
2018                  .perform(swipeUp());
2019          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2020          waitForIdle();
2021  
2022          onView(withTextFromRuntimeResource("resolver_turn_on_work_apps"))
2023                  .check(matches(isDisplayed()));
2024      }
2025  
2026      @Test
testWorkTab_noWorkAppsAvailable_emptyStateShown()2027      public void testWorkTab_noWorkAppsAvailable_emptyStateShown() {
2028          // enable the work tab feature flag
2029          ResolverActivity.ENABLE_TABBED_VIEW = true;
2030          markWorkProfileUserAvailable();
2031          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2032                  createResolvedComponentsForTest(3);
2033          List<ResolvedComponentInfo> workResolvedComponentInfos =
2034                  createResolvedComponentsForTest(0);
2035          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2036          Intent sendIntent = createSendTextIntent();
2037          sendIntent.setType(TEST_MIME_TYPE);
2038  
2039          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2040          waitForIdle();
2041          onView(withIdFromRuntimeResource("contentPanel"))
2042                  .perform(swipeUp());
2043          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2044          waitForIdle();
2045  
2046          onView(withTextFromRuntimeResource("resolver_no_work_apps_available"))
2047                  .check(matches(isDisplayed()));
2048      }
2049  
2050      @Ignore // b/220067877
2051      @Test
testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown()2052      public void testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown() {
2053          // enable the work tab feature flag
2054          ResolverActivity.ENABLE_TABBED_VIEW = true;
2055          markWorkProfileUserAvailable();
2056          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2057                  createResolvedComponentsForTest(3);
2058          List<ResolvedComponentInfo> workResolvedComponentInfos =
2059                  createResolvedComponentsForTest(0);
2060          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2061          ChooserActivityOverrideData.getInstance().isQuietModeEnabled = true;
2062          ChooserActivityOverrideData.getInstance().hasCrossProfileIntents = false;
2063          Intent sendIntent = createSendTextIntent();
2064          sendIntent.setType(TEST_MIME_TYPE);
2065  
2066          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2067          waitForIdle();
2068          onView(withIdFromRuntimeResource("contentPanel"))
2069                  .perform(swipeUp());
2070          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2071          waitForIdle();
2072  
2073          onView(withTextFromRuntimeResource("resolver_cross_profile_blocked"))
2074                  .check(matches(isDisplayed()));
2075      }
2076  
2077      @Test
testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown()2078      public void testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown() {
2079          // enable the work tab feature flag
2080          ResolverActivity.ENABLE_TABBED_VIEW = true;
2081          markWorkProfileUserAvailable();
2082          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2083                  createResolvedComponentsForTest(3);
2084          List<ResolvedComponentInfo> workResolvedComponentInfos =
2085                  createResolvedComponentsForTest(0);
2086          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2087          ChooserActivityOverrideData.getInstance().isQuietModeEnabled = true;
2088          Intent sendIntent = createSendTextIntent();
2089          sendIntent.setType(TEST_MIME_TYPE);
2090  
2091          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2092          waitForIdle();
2093          onView(withIdFromRuntimeResource("contentPanel"))
2094                  .perform(swipeUp());
2095          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2096          waitForIdle();
2097  
2098          onView(withTextFromRuntimeResource("resolver_no_work_apps_available"))
2099                  .check(matches(isDisplayed()));
2100      }
2101  
2102      @Test @Ignore("b/222124533")
testAppTargetLogging()2103      public void testAppTargetLogging() throws InterruptedException {
2104          Intent sendIntent = createSendTextIntent();
2105          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
2106  
2107          when(
2108                  ChooserActivityOverrideData
2109                          .getInstance()
2110                          .resolverListController
2111                          .getResolversForIntent(
2112                                  Mockito.anyBoolean(),
2113                                  Mockito.anyBoolean(),
2114                                  Mockito.anyBoolean(),
2115                                  Mockito.isA(List.class)))
2116                  .thenReturn(resolvedComponentInfos);
2117  
2118          final IChooserWrapper activity = (IChooserWrapper)
2119                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
2120          waitForIdle();
2121  
2122          // TODO(b/222124533): other test cases use a timeout to make sure that the UI is fully
2123          // populated; without one, this test flakes. Ideally we should address the need for a
2124          // timeout everywhere instead of introducing one to fix this particular test.
2125  
2126          assertThat(activity.getAdapter().getCount(), is(2));
2127          onView(withIdFromRuntimeResource("profile_button")).check(doesNotExist());
2128  
2129          ResolveInfo[] chosen = new ResolveInfo[1];
2130          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
2131              chosen[0] = targetInfo.getResolveInfo();
2132              return true;
2133          };
2134  
2135          ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
2136          onView(withText(toChoose.activityInfo.name))
2137                  .perform(click());
2138          waitForIdle();
2139  
2140          ChooserActivityLoggerFake logger =
2141                  (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
2142  
2143          // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events.
2144          logger.removeCallsForUiEventsOfType(
2145                  ChooserActivityLogger.SharesheetStandardEvent
2146                          .SHARESHEET_DIRECT_LOAD_COMPLETE.getId());
2147  
2148          // SHARESHEET_TRIGGERED:
2149          assertThat(logger.event(0).getId(),
2150                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
2151  
2152          // SHARESHEET_STARTED:
2153          assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
2154          assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
2155          assertThat(logger.get(1).mimeType, is("text/plain"));
2156          assertThat(logger.get(1).packageName, is(
2157                  InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName()));
2158          assertThat(logger.get(1).appProvidedApp, is(0));
2159          assertThat(logger.get(1).appProvidedDirect, is(0));
2160          assertThat(logger.get(1).isWorkprofile, is(false));
2161          assertThat(logger.get(1).previewType, is(3));
2162  
2163          // SHARESHEET_APP_LOAD_COMPLETE:
2164          assertThat(logger.event(2).getId(),
2165                  is(ChooserActivityLogger
2166                          .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
2167  
2168          // Next are just artifacts of test set-up:
2169          assertThat(logger.event(3).getId(),
2170                  is(ChooserActivityLogger
2171                          .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
2172          assertThat(logger.event(4).getId(),
2173                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId()));
2174  
2175          // SHARESHEET_APP_TARGET_SELECTED:
2176          assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
2177          assertThat(logger.get(5).targetType,
2178                  is(ChooserActivityLogger
2179                          .SharesheetTargetSelectedEvent.SHARESHEET_APP_TARGET_SELECTED.getId()));
2180  
2181          // No more events.
2182          assertThat(logger.numCalls(), is(6));
2183      }
2184  
2185      @Test
testDirectTargetLogging()2186      public void testDirectTargetLogging() {
2187          Intent sendIntent = createSendTextIntent();
2188          // We need app targets for direct targets to get displayed
2189          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
2190          when(
2191                  ChooserActivityOverrideData
2192                          .getInstance()
2193                          .resolverListController
2194                          .getResolversForIntent(
2195                                  Mockito.anyBoolean(),
2196                                  Mockito.anyBoolean(),
2197                                  Mockito.anyBoolean(),
2198                                  Mockito.isA(List.class)))
2199                  .thenReturn(resolvedComponentInfos);
2200  
2201          // Create direct share target
2202          List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
2203                  resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
2204          ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
2205                  PERSONAL_USER_HANDLE);
2206  
2207          ChooserActivityOverrideData
2208                  .getInstance()
2209                  .directShareTargets = (activity, adapter) -> {
2210                      DisplayResolveInfo displayInfo = activity.createTestDisplayResolveInfo(
2211                              sendIntent,
2212                              ri,
2213                               "testLabel",
2214                               "testInfo",
2215                              sendIntent,
2216                              /* resolveInfoPresentationGetter */ null);
2217                      ServiceResultInfo[] results = {
2218                              new ServiceResultInfo(
2219                                      displayInfo,
2220                                      serviceTargets,
2221                                      adapter.getUserHandle())};
2222                      // TODO: consider covering the other type.
2223                      //  Only 2 types are expected out of the shortcut loading logic:
2224                      //  - TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER, if shortcuts were loaded from
2225                      //    the ShortcutManager, and;
2226                      //  - TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE, if shortcuts were loaded
2227                      //    from AppPredictor.
2228                      //  Ideally, our tests should cover all of them.
2229                      return new Pair<>(TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER, results);
2230                  };
2231  
2232          // Start activity
2233          final IChooserWrapper activity = (IChooserWrapper)
2234                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
2235  
2236          assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
2237                  activity.getAdapter().getCount(), is(3));
2238          assertThat("Chooser should have exactly one selectable direct target",
2239                  activity.getAdapter().getSelectableServiceTargetCount(), is(1));
2240          assertThat("The resolver info must match the resolver info used to create the target",
2241                  activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
2242  
2243          // Click on the direct target
2244          String name = serviceTargets.get(0).getTitle().toString();
2245          onView(withText(name))
2246                  .perform(click());
2247          waitForIdle();
2248  
2249          ChooserActivityLoggerFake logger =
2250                  (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
2251          assertThat(logger.numCalls(), is(6));
2252          // first one should be SHARESHEET_TRIGGERED uievent
2253          assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
2254          assertThat(logger.get(0).event.getId(),
2255                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
2256          // second one should be SHARESHEET_STARTED event
2257          assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
2258          assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
2259          assertThat(logger.get(1).mimeType, is("text/plain"));
2260          assertThat(logger.get(1).packageName, is(
2261                  InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName()));
2262          assertThat(logger.get(1).appProvidedApp, is(0));
2263          assertThat(logger.get(1).appProvidedDirect, is(0));
2264          assertThat(logger.get(1).isWorkprofile, is(false));
2265          assertThat(logger.get(1).previewType, is(3));
2266          // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
2267          assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
2268          assertThat(logger.get(2).event.getId(),
2269                  is(ChooserActivityLogger
2270                          .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
2271          // fourth and fifth are just artifacts of test set-up
2272          // sixth one should be ranking atom with SHARESHEET_COPY_TARGET_SELECTED event
2273          assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
2274          assertThat(logger.get(5).targetType,
2275                  is(ChooserActivityLogger
2276                          .SharesheetTargetSelectedEvent.SHARESHEET_SERVICE_TARGET_SELECTED.getId()));
2277      }
2278  
2279      @Test @Ignore
testEmptyDirectRowLogging()2280      public void testEmptyDirectRowLogging() throws InterruptedException {
2281          Intent sendIntent = createSendTextIntent();
2282          // We need app targets for direct targets to get displayed
2283          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
2284          when(
2285                  ChooserActivityOverrideData
2286                          .getInstance()
2287                          .resolverListController
2288                          .getResolversForIntent(
2289                                  Mockito.anyBoolean(),
2290                                  Mockito.anyBoolean(),
2291                                  Mockito.anyBoolean(),
2292                                  Mockito.isA(List.class)))
2293                  .thenReturn(resolvedComponentInfos);
2294  
2295          // Start activity
2296          final IChooserWrapper activity = (IChooserWrapper)
2297                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
2298  
2299          // Thread.sleep shouldn't be a thing in an integration test but it's
2300          // necessary here because of the way the code is structured
2301          Thread.sleep(3000);
2302  
2303          assertThat("Chooser should have 2 app targets",
2304                  activity.getAdapter().getCount(), is(2));
2305          assertThat("Chooser should have no direct targets",
2306                  activity.getAdapter().getSelectableServiceTargetCount(), is(0));
2307  
2308          ChooserActivityLoggerFake logger =
2309                  (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
2310  
2311          // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events.
2312          logger.removeCallsForUiEventsOfType(
2313                  ChooserActivityLogger.SharesheetStandardEvent
2314                          .SHARESHEET_DIRECT_LOAD_COMPLETE.getId());
2315  
2316          // SHARESHEET_TRIGGERED:
2317          assertThat(logger.event(0).getId(),
2318                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
2319  
2320          // SHARESHEET_STARTED:
2321          assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
2322          assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
2323          assertThat(logger.get(1).mimeType, is("text/plain"));
2324          assertThat(logger.get(1).packageName, is(
2325                  InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName()));
2326          assertThat(logger.get(1).appProvidedApp, is(0));
2327          assertThat(logger.get(1).appProvidedDirect, is(0));
2328          assertThat(logger.get(1).isWorkprofile, is(false));
2329          assertThat(logger.get(1).previewType, is(3));
2330  
2331          // SHARESHEET_APP_LOAD_COMPLETE:
2332          assertThat(logger.event(2).getId(),
2333                  is(ChooserActivityLogger
2334                          .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
2335  
2336          // SHARESHEET_EMPTY_DIRECT_SHARE_ROW:
2337          assertThat(logger.event(3).getId(),
2338                  is(ChooserActivityLogger
2339                          .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
2340  
2341          // Next is just an artifact of test set-up:
2342          assertThat(logger.event(4).getId(),
2343                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId()));
2344  
2345          assertThat(logger.numCalls(), is(5));
2346      }
2347  
2348      @Ignore // b/220067877
2349      @Test
testCopyTextToClipboardLogging()2350      public void testCopyTextToClipboardLogging() throws Exception {
2351          Intent sendIntent = createSendTextIntent();
2352          List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
2353  
2354          when(
2355                  ChooserActivityOverrideData
2356                          .getInstance()
2357                          .resolverListController
2358                          .getResolversForIntent(
2359                                  Mockito.anyBoolean(),
2360                                  Mockito.anyBoolean(),
2361                                  Mockito.anyBoolean(),
2362                                  Mockito.isA(List.class)))
2363                  .thenReturn(resolvedComponentInfos);
2364  
2365          final IChooserWrapper activity = (IChooserWrapper)
2366                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
2367          waitForIdle();
2368  
2369          onView(withIdFromRuntimeResource("chooser_copy_button")).check(matches(isDisplayed()));
2370          onView(withIdFromRuntimeResource("chooser_copy_button")).perform(click());
2371  
2372          ChooserActivityLoggerFake logger =
2373                  (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
2374  
2375          // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events.
2376          logger.removeCallsForUiEventsOfType(
2377                  ChooserActivityLogger.SharesheetStandardEvent
2378                          .SHARESHEET_DIRECT_LOAD_COMPLETE.getId());
2379  
2380          // SHARESHEET_TRIGGERED:
2381          assertThat(logger.event(0).getId(),
2382                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
2383  
2384          // SHARESHEET_STARTED:
2385          assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
2386          assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
2387          assertThat(logger.get(1).mimeType, is("text/plain"));
2388          assertThat(logger.get(1).packageName, is(
2389                  InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName()));
2390          assertThat(logger.get(1).appProvidedApp, is(0));
2391          assertThat(logger.get(1).appProvidedDirect, is(0));
2392          assertThat(logger.get(1).isWorkprofile, is(false));
2393          assertThat(logger.get(1).previewType, is(3));
2394  
2395          // SHARESHEET_APP_LOAD_COMPLETE:
2396          assertThat(logger.event(2).getId(),
2397                  is(ChooserActivityLogger
2398                          .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
2399  
2400          // Next are just artifacts of test set-up:
2401          assertThat(logger.event(3).getId(),
2402                  is(ChooserActivityLogger
2403                          .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
2404          assertThat(logger.event(4).getId(),
2405                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_EXPANDED.getId()));
2406  
2407          // SHARESHEET_COPY_TARGET_SELECTED:
2408          assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
2409          assertThat(logger.get(5).targetType,
2410                  is(ChooserActivityLogger
2411                          .SharesheetTargetSelectedEvent.SHARESHEET_COPY_TARGET_SELECTED.getId()));
2412  
2413          // No more events.
2414          assertThat(logger.numCalls(), is(6));
2415      }
2416  
2417      @Test @Ignore("b/222124533")
testSwitchProfileLogging()2418      public void testSwitchProfileLogging() throws InterruptedException {
2419          // enable the work tab feature flag
2420          ResolverActivity.ENABLE_TABBED_VIEW = true;
2421          markWorkProfileUserAvailable();
2422          int workProfileTargets = 4;
2423          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2424                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2425          List<ResolvedComponentInfo> workResolvedComponentInfos =
2426                  createResolvedComponentsForTest(workProfileTargets);
2427          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2428          Intent sendIntent = createSendTextIntent();
2429          sendIntent.setType(TEST_MIME_TYPE);
2430  
2431          final IChooserWrapper activity = (IChooserWrapper)
2432                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2433          waitForIdle();
2434          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2435          waitForIdle();
2436          onView(withTextFromRuntimeResource("resolver_personal_tab")).perform(click());
2437          waitForIdle();
2438  
2439          ChooserActivityLoggerFake logger =
2440                  (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
2441  
2442          // TODO(b/211669337): Determine the expected SHARESHEET_DIRECT_LOAD_COMPLETE events.
2443          logger.removeCallsForUiEventsOfType(
2444                  ChooserActivityLogger.SharesheetStandardEvent
2445                          .SHARESHEET_DIRECT_LOAD_COMPLETE.getId());
2446  
2447          // SHARESHEET_TRIGGERED:
2448          assertThat(logger.event(0).getId(),
2449                  is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
2450  
2451          // SHARESHEET_STARTED:
2452          assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
2453          assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
2454          assertThat(logger.get(1).mimeType, is(TEST_MIME_TYPE));
2455          assertThat(logger.get(1).packageName, is(
2456                  InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName()));
2457          assertThat(logger.get(1).appProvidedApp, is(0));
2458          assertThat(logger.get(1).appProvidedDirect, is(0));
2459          assertThat(logger.get(1).isWorkprofile, is(false));
2460          assertThat(logger.get(1).previewType, is(3));
2461  
2462          // SHARESHEET_APP_LOAD_COMPLETE:
2463          assertThat(logger.event(2).getId(),
2464                  is(ChooserActivityLogger
2465                          .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
2466  
2467          // Next is just an artifact of test set-up:
2468          assertThat(logger.event(3).getId(),
2469                  is(ChooserActivityLogger
2470                          .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
2471  
2472          // SHARESHEET_PROFILE_CHANGED:
2473          assertThat(logger.event(4).getId(),
2474                  is(ChooserActivityLogger.SharesheetStandardEvent
2475                          .SHARESHEET_PROFILE_CHANGED.getId()));
2476  
2477          // Repeat the loading steps in the new profile:
2478  
2479          // SHARESHEET_APP_LOAD_COMPLETE:
2480          assertThat(logger.event(5).getId(),
2481                  is(ChooserActivityLogger
2482                          .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
2483  
2484          // Next is again an artifact of test set-up:
2485          assertThat(logger.event(6).getId(),
2486                  is(ChooserActivityLogger
2487                          .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
2488  
2489          // SHARESHEET_PROFILE_CHANGED:
2490          assertThat(logger.event(7).getId(),
2491                  is(ChooserActivityLogger.SharesheetStandardEvent
2492                          .SHARESHEET_PROFILE_CHANGED.getId()));
2493  
2494          // No more events (this profile was already loaded).
2495          assertThat(logger.numCalls(), is(8));
2496      }
2497  
2498      @Test
testAutolaunch_singleTarget_wifthWorkProfileAndTabbedViewOff_noAutolaunch()2499      public void testAutolaunch_singleTarget_wifthWorkProfileAndTabbedViewOff_noAutolaunch() {
2500          ResolverActivity.ENABLE_TABBED_VIEW = false;
2501          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2502                  createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
2503          when(
2504                  ChooserActivityOverrideData
2505                          .getInstance()
2506                          .resolverListController
2507                          .getResolversForIntent(
2508                                  Mockito.anyBoolean(),
2509                                  Mockito.anyBoolean(),
2510                                  Mockito.anyBoolean(),
2511                                  Mockito.isA(List.class)))
2512                  .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2513          Intent sendIntent = createSendTextIntent();
2514          sendIntent.setType(TEST_MIME_TYPE);
2515          ResolveInfo[] chosen = new ResolveInfo[1];
2516          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
2517              chosen[0] = targetInfo.getResolveInfo();
2518              return true;
2519          };
2520          waitForIdle();
2521  
2522          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2523          waitForIdle();
2524  
2525          assertTrue(chosen[0] == null);
2526      }
2527  
2528      @Test
testAutolaunch_singleTarget_noWorkProfile_autolaunch()2529      public void testAutolaunch_singleTarget_noWorkProfile_autolaunch() {
2530          ResolverActivity.ENABLE_TABBED_VIEW = false;
2531          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2532                  createResolvedComponentsForTest(1);
2533          when(
2534                  ChooserActivityOverrideData
2535                          .getInstance()
2536                          .resolverListController
2537                          .getResolversForIntent(
2538                                  Mockito.anyBoolean(),
2539                                  Mockito.anyBoolean(),
2540                                  Mockito.anyBoolean(),
2541                                  Mockito.isA(List.class)))
2542                  .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2543          Intent sendIntent = createSendTextIntent();
2544          sendIntent.setType(TEST_MIME_TYPE);
2545          ResolveInfo[] chosen = new ResolveInfo[1];
2546          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
2547              chosen[0] = targetInfo.getResolveInfo();
2548              return true;
2549          };
2550          waitForIdle();
2551  
2552          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2553          waitForIdle();
2554  
2555          assertThat(chosen[0], is(personalResolvedComponentInfos.get(0).getResolveInfoAt(0)));
2556      }
2557  
2558      @Test
testWorkTab_onePersonalTarget_emptyStateOnWorkTarget_autolaunch()2559      public void testWorkTab_onePersonalTarget_emptyStateOnWorkTarget_autolaunch() {
2560          // enable the work tab feature flag
2561          ResolverActivity.ENABLE_TABBED_VIEW = true;
2562          markWorkProfileUserAvailable();
2563          int workProfileTargets = 4;
2564          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2565                  createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
2566          List<ResolvedComponentInfo> workResolvedComponentInfos =
2567                  createResolvedComponentsForTest(workProfileTargets);
2568          ChooserActivityOverrideData.getInstance().hasCrossProfileIntents = false;
2569          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2570          Intent sendIntent = createSendTextIntent();
2571          ResolveInfo[] chosen = new ResolveInfo[1];
2572          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
2573              chosen[0] = targetInfo.getResolveInfo();
2574              return true;
2575          };
2576  
2577          mActivityRule.launchActivity(sendIntent);
2578          waitForIdle();
2579  
2580          assertThat(chosen[0], is(personalResolvedComponentInfos.get(1).getResolveInfoAt(0)));
2581      }
2582  
2583      @Test
testOneInitialIntent_noAutolaunch()2584      public void testOneInitialIntent_noAutolaunch() {
2585          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2586                  createResolvedComponentsForTest(1);
2587          when(
2588                  ChooserActivityOverrideData
2589                          .getInstance()
2590                          .resolverListController
2591                          .getResolversForIntent(
2592                                  Mockito.anyBoolean(),
2593                                  Mockito.anyBoolean(),
2594                                  Mockito.anyBoolean(),
2595                                  Mockito.isA(List.class)))
2596                  .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2597          Intent chooserIntent = createChooserIntent(createSendTextIntent(),
2598                  new Intent[] {new Intent("action.fake")});
2599          ResolveInfo[] chosen = new ResolveInfo[1];
2600          ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
2601              chosen[0] = targetInfo.getResolveInfo();
2602              return true;
2603          };
2604          ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class);
2605          ResolveInfo ri = createFakeResolveInfo();
2606          when(
2607                  ChooserActivityOverrideData
2608                          .getInstance().packageManager
2609                          .resolveActivity(any(Intent.class), anyInt()))
2610                  .thenReturn(ri);
2611          waitForIdle();
2612  
2613          IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(chooserIntent);
2614          waitForIdle();
2615  
2616          assertNull(chosen[0]);
2617          assertThat(activity
2618                  .getPersonalListAdapter().getCallerTargetCount(), is(1));
2619      }
2620  
2621      @Test
testWorkTab_withInitialIntents_workTabDoesNotIncludePersonalInitialIntents()2622      public void testWorkTab_withInitialIntents_workTabDoesNotIncludePersonalInitialIntents() {
2623          // enable the work tab feature flag
2624          ResolverActivity.ENABLE_TABBED_VIEW = true;
2625          markWorkProfileUserAvailable();
2626          int workProfileTargets = 1;
2627          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2628                  createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
2629          List<ResolvedComponentInfo> workResolvedComponentInfos =
2630                  createResolvedComponentsForTest(workProfileTargets);
2631          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2632          Intent[] initialIntents = {
2633                  new Intent("action.fake1"),
2634                  new Intent("action.fake2")
2635          };
2636          Intent chooserIntent = createChooserIntent(createSendTextIntent(), initialIntents);
2637          ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class);
2638          when(
2639                  ChooserActivityOverrideData
2640                          .getInstance()
2641                          .packageManager
2642                          .resolveActivity(any(Intent.class), anyInt()))
2643                  .thenReturn(createFakeResolveInfo());
2644          waitForIdle();
2645  
2646          IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(chooserIntent);
2647          waitForIdle();
2648  
2649          assertThat(activity.getPersonalListAdapter().getCallerTargetCount(), is(2));
2650          assertThat(activity.getWorkListAdapter().getCallerTargetCount(), is(0));
2651      }
2652  
2653      @Test
testWorkTab_xProfileIntentsDisabled_personalToWork_nonSendIntent_emptyStateShown()2654      public void testWorkTab_xProfileIntentsDisabled_personalToWork_nonSendIntent_emptyStateShown() {
2655          // enable the work tab feature flag
2656          ResolverActivity.ENABLE_TABBED_VIEW = true;
2657          markWorkProfileUserAvailable();
2658          int workProfileTargets = 4;
2659          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2660                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2661          List<ResolvedComponentInfo> workResolvedComponentInfos =
2662                  createResolvedComponentsForTest(workProfileTargets);
2663          ChooserActivityOverrideData.getInstance().hasCrossProfileIntents = false;
2664          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2665          Intent[] initialIntents = {
2666                  new Intent("action.fake1"),
2667                  new Intent("action.fake2")
2668          };
2669          Intent chooserIntent = createChooserIntent(new Intent(), initialIntents);
2670          ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class);
2671          when(
2672                  ChooserActivityOverrideData
2673                          .getInstance()
2674                          .packageManager
2675                          .resolveActivity(any(Intent.class), anyInt()))
2676                  .thenReturn(createFakeResolveInfo());
2677  
2678          mActivityRule.launchActivity(chooserIntent);
2679          waitForIdle();
2680          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2681          waitForIdle();
2682          onView(withIdFromRuntimeResource("contentPanel"))
2683                  .perform(swipeUp());
2684  
2685          onView(withTextFromRuntimeResource("resolver_cross_profile_blocked"))
2686                  .check(matches(isDisplayed()));
2687      }
2688  
2689      @Test
testWorkTab_noWorkAppsAvailable_nonSendIntent_emptyStateShown()2690      public void testWorkTab_noWorkAppsAvailable_nonSendIntent_emptyStateShown() {
2691          // enable the work tab feature flag
2692          ResolverActivity.ENABLE_TABBED_VIEW = true;
2693          markWorkProfileUserAvailable();
2694          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2695                  createResolvedComponentsForTest(3);
2696          List<ResolvedComponentInfo> workResolvedComponentInfos =
2697                  createResolvedComponentsForTest(0);
2698          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2699          Intent[] initialIntents = {
2700                  new Intent("action.fake1"),
2701                  new Intent("action.fake2")
2702          };
2703          Intent chooserIntent = createChooserIntent(new Intent(), initialIntents);
2704          ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class);
2705          when(
2706                  ChooserActivityOverrideData
2707                          .getInstance()
2708                          .packageManager
2709                          .resolveActivity(any(Intent.class), anyInt()))
2710                  .thenReturn(createFakeResolveInfo());
2711  
2712          mActivityRule.launchActivity(chooserIntent);
2713          waitForIdle();
2714          onView(withIdFromRuntimeResource("contentPanel"))
2715                  .perform(swipeUp());
2716          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2717          waitForIdle();
2718  
2719          onView(withTextFromRuntimeResource("resolver_no_work_apps_available"))
2720                  .check(matches(isDisplayed()));
2721      }
2722  
2723      @Test
testDeduplicateCallerTargetRankedTarget()2724      public void testDeduplicateCallerTargetRankedTarget() {
2725          // Create 4 ranked app targets.
2726          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2727                  createResolvedComponentsForTest(4);
2728          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
2729                  Mockito.anyBoolean(),
2730                                  Mockito.anyBoolean(),
2731                                  Mockito.anyBoolean(),
2732                                  Mockito.isA(List.class)))
2733                  .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2734          // Create caller target which is duplicate with one of app targets
2735          Intent chooserIntent = createChooserIntent(createSendTextIntent(),
2736                  new Intent[] {new Intent("action.fake")});
2737          ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class);
2738          ResolveInfo ri = ResolverDataProvider.createResolveInfo(0,
2739                  UserHandle.USER_CURRENT, PERSONAL_USER_HANDLE);
2740          when(
2741                  ChooserActivityOverrideData
2742                          .getInstance()
2743                          .packageManager
2744                          .resolveActivity(any(Intent.class), anyInt()))
2745                  .thenReturn(ri);
2746          waitForIdle();
2747  
2748          IChooserWrapper activity = (IChooserWrapper) mActivityRule.launchActivity(chooserIntent);
2749          waitForIdle();
2750  
2751          // Total 4 targets (1 caller target, 3 ranked targets)
2752          assertThat(activity.getAdapter().getCount(), is(4));
2753          assertThat(activity.getAdapter().getCallerTargetCount(), is(1));
2754          assertThat(activity.getAdapter().getRankedTargetCount(), is(3));
2755      }
2756  
2757      @Test
testWorkTab_selectingWorkTabWithPausedWorkProfile_directShareTargetsNotQueried()2758      public void testWorkTab_selectingWorkTabWithPausedWorkProfile_directShareTargetsNotQueried() {
2759          // enable the work tab feature flag
2760          ResolverActivity.ENABLE_TABBED_VIEW = true;
2761          markWorkProfileUserAvailable();
2762          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2763                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2764          List<ResolvedComponentInfo> workResolvedComponentInfos =
2765                  createResolvedComponentsForTest(3);
2766          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2767          ChooserActivityOverrideData.getInstance().isQuietModeEnabled = true;
2768          boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false };
2769          ChooserActivityOverrideData.getInstance().onQueryDirectShareTargets =
2770                  chooserListAdapter -> {
2771                      isQueryDirectShareCalledOnWorkProfile[0] =
2772                              (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2773                      return null;
2774                  };
2775          Intent sendIntent = createSendTextIntent();
2776          sendIntent.setType(TEST_MIME_TYPE);
2777  
2778          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2779          waitForIdle();
2780          onView(withIdFromRuntimeResource("contentPanel"))
2781                  .perform(swipeUp());
2782          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2783          waitForIdle();
2784  
2785          assertFalse("Direct share targets were queried on a paused work profile",
2786                  isQueryDirectShareCalledOnWorkProfile[0]);
2787      }
2788  
2789      @Test
testWorkTab_selectingWorkTabWithNotRunningWorkUser_directShareTargetsNotQueried()2790      public void testWorkTab_selectingWorkTabWithNotRunningWorkUser_directShareTargetsNotQueried() {
2791          // enable the work tab feature flag
2792          ResolverActivity.ENABLE_TABBED_VIEW = true;
2793          markWorkProfileUserAvailable();
2794          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2795                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2796          List<ResolvedComponentInfo> workResolvedComponentInfos =
2797                  createResolvedComponentsForTest(3);
2798          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2799          ChooserActivityOverrideData.getInstance().isWorkProfileUserRunning = false;
2800          boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false };
2801          ChooserActivityOverrideData.getInstance().onQueryDirectShareTargets =
2802                  chooserListAdapter -> {
2803                      isQueryDirectShareCalledOnWorkProfile[0] =
2804                              (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2805                      return null;
2806                  };
2807          Intent sendIntent = createSendTextIntent();
2808          sendIntent.setType(TEST_MIME_TYPE);
2809  
2810          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2811          waitForIdle();
2812          onView(withIdFromRuntimeResource("contentPanel"))
2813                  .perform(swipeUp());
2814          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2815          waitForIdle();
2816  
2817          assertFalse("Direct share targets were queried on a locked work profile user",
2818                  isQueryDirectShareCalledOnWorkProfile[0]);
2819      }
2820  
2821      @Test
testWorkTab_workUserNotRunning_workTargetsShown()2822      public void testWorkTab_workUserNotRunning_workTargetsShown() {
2823          // enable the work tab feature flag
2824          ResolverActivity.ENABLE_TABBED_VIEW = true;
2825          markWorkProfileUserAvailable();
2826          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2827                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2828          List<ResolvedComponentInfo> workResolvedComponentInfos =
2829                  createResolvedComponentsForTest(3);
2830          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2831          Intent sendIntent = createSendTextIntent();
2832          sendIntent.setType(TEST_MIME_TYPE);
2833          ChooserActivityOverrideData.getInstance().isWorkProfileUserRunning = false;
2834  
2835          final ChooserActivity activity =
2836                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2837          final IChooserWrapper wrapper = (IChooserWrapper) activity;
2838          waitForIdle();
2839          onView(withIdFromRuntimeResource("contentPanel")).perform(swipeUp());
2840          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2841          waitForIdle();
2842  
2843          assertEquals(3, wrapper.getWorkListAdapter().getCount());
2844      }
2845  
2846      @Test
testWorkTab_selectingWorkTabWithLockedWorkUser_directShareTargetsNotQueried()2847      public void testWorkTab_selectingWorkTabWithLockedWorkUser_directShareTargetsNotQueried() {
2848          // enable the work tab feature flag
2849          ResolverActivity.ENABLE_TABBED_VIEW = true;
2850          markWorkProfileUserAvailable();
2851          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2852                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2853          List<ResolvedComponentInfo> workResolvedComponentInfos =
2854                  createResolvedComponentsForTest(3);
2855          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2856          ChooserActivityOverrideData.getInstance().isWorkProfileUserUnlocked = false;
2857          boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false };
2858          ChooserActivityOverrideData.getInstance().onQueryDirectShareTargets =
2859                  chooserListAdapter -> {
2860                      isQueryDirectShareCalledOnWorkProfile[0] =
2861                              (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2862                      return null;
2863                  };
2864          Intent sendIntent = createSendTextIntent();
2865          sendIntent.setType(TEST_MIME_TYPE);
2866  
2867          mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2868          waitForIdle();
2869          onView(withIdFromRuntimeResource("contentPanel"))
2870                  .perform(swipeUp());
2871          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2872          waitForIdle();
2873  
2874          assertFalse("Direct share targets were queried on a locked work profile user",
2875                  isQueryDirectShareCalledOnWorkProfile[0]);
2876      }
2877  
2878      @Test
testWorkTab_workUserLocked_workTargetsShown()2879      public void testWorkTab_workUserLocked_workTargetsShown() {
2880          // enable the work tab feature flag
2881          ResolverActivity.ENABLE_TABBED_VIEW = true;
2882          markWorkProfileUserAvailable();
2883          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2884                  createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2885          List<ResolvedComponentInfo> workResolvedComponentInfos =
2886                  createResolvedComponentsForTest(3);
2887          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2888          Intent sendIntent = createSendTextIntent();
2889          sendIntent.setType(TEST_MIME_TYPE);
2890          ChooserActivityOverrideData.getInstance().isWorkProfileUserUnlocked = false;
2891  
2892          final ChooserActivity activity =
2893                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2894          final IChooserWrapper wrapper = (IChooserWrapper) activity;
2895          waitForIdle();
2896          onView(withIdFromRuntimeResource("contentPanel"))
2897                  .perform(swipeUp());
2898          onView(withTextFromRuntimeResource("resolver_work_tab")).perform(click());
2899          waitForIdle();
2900  
2901          assertEquals(3, wrapper.getWorkListAdapter().getCount());
2902      }
2903  
2904      @Test
testClonedProfilePresent_personalAdapterIsSetWithPersonalProfile()2905      public void testClonedProfilePresent_personalAdapterIsSetWithPersonalProfile() {
2906          // enable cloneProfile
2907          markCloneProfileUserAvailable();
2908          List<ResolvedComponentInfo> resolvedComponentInfos =
2909                  createResolvedComponentsWithCloneProfileForTest(
2910                          3,
2911                          PERSONAL_USER_HANDLE,
2912                          ChooserActivityOverrideData.getInstance().cloneProfileUserHandle);
2913          when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
2914                  Mockito.anyBoolean(),
2915                  Mockito.anyBoolean(),
2916                  Mockito.anyBoolean(),
2917                  Mockito.isA(List.class)))
2918                  .thenReturn(new ArrayList<>(resolvedComponentInfos));
2919          Intent sendIntent = createSendTextIntent();
2920  
2921          final IChooserWrapper activity = (IChooserWrapper) mActivityRule
2922                  .launchActivity(Intent.createChooser(sendIntent, "personalProfileTest"));
2923          waitForIdle();
2924  
2925          assertThat(activity.getPersonalListAdapter().getUserHandle(), is(PERSONAL_USER_HANDLE));
2926          assertThat(activity.getAdapter().getCount(), is(3));
2927      }
2928  
2929      @Test
testClonedProfilePresent_personalTabUsesExpectedAdapter()2930      public void testClonedProfilePresent_personalTabUsesExpectedAdapter() {
2931          // enable the work tab feature flag
2932          ResolverActivity.ENABLE_TABBED_VIEW = true;
2933          markWorkProfileUserAvailable();
2934          markCloneProfileUserAvailable();
2935          List<ResolvedComponentInfo> personalResolvedComponentInfos =
2936                  createResolvedComponentsForTest(3);
2937          List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(
2938                  4);
2939          setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2940          Intent sendIntent = createSendTextIntent();
2941          sendIntent.setType(TEST_MIME_TYPE);
2942  
2943  
2944          final IChooserWrapper activity = (IChooserWrapper)
2945                  mActivityRule.launchActivity(Intent.createChooser(sendIntent, "multi tab test"));
2946          waitForIdle();
2947  
2948          assertThat(activity.getCurrentUserHandle(), is(PERSONAL_USER_HANDLE));
2949      }
2950  
createChooserIntent(Intent intent, Intent[] initialIntents)2951      private Intent createChooserIntent(Intent intent, Intent[] initialIntents) {
2952          Intent chooserIntent = new Intent();
2953          chooserIntent.setAction(Intent.ACTION_CHOOSER);
2954          chooserIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
2955          chooserIntent.putExtra(Intent.EXTRA_TITLE, "some title");
2956          chooserIntent.putExtra(Intent.EXTRA_INTENT, intent);
2957          chooserIntent.setType("text/plain");
2958          if (initialIntents != null) {
2959              chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, initialIntents);
2960          }
2961          return chooserIntent;
2962      }
2963  
createFakeResolveInfo()2964      private ResolveInfo createFakeResolveInfo() {
2965          ResolveInfo ri = new ResolveInfo();
2966          ri.activityInfo = new ActivityInfo();
2967          ri.activityInfo.name = "FakeActivityName";
2968          ri.activityInfo.packageName = "fake.package.name";
2969          ri.activityInfo.applicationInfo = new ApplicationInfo();
2970          ri.activityInfo.applicationInfo.packageName = "fake.package.name";
2971          ri.userHandle = UserHandle.CURRENT;
2972          return ri;
2973      }
2974  
createSendTextIntent()2975      private Intent createSendTextIntent() {
2976          Intent sendIntent = new Intent();
2977          sendIntent.setAction(Intent.ACTION_SEND);
2978          sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
2979          sendIntent.setType("text/plain");
2980          return sendIntent;
2981      }
2982  
createSendImageIntent(Uri imageThumbnail)2983      private Intent createSendImageIntent(Uri imageThumbnail) {
2984          Intent sendIntent = new Intent();
2985          sendIntent.setAction(Intent.ACTION_SEND);
2986          sendIntent.putExtra(Intent.EXTRA_STREAM, imageThumbnail);
2987          sendIntent.setType("image/png");
2988          if (imageThumbnail != null) {
2989              ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
2990              sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
2991          }
2992  
2993          return sendIntent;
2994      }
2995  
createSendTextIntentWithPreview(String title, Uri imageThumbnail)2996      private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
2997          Intent sendIntent = new Intent();
2998          sendIntent.setAction(Intent.ACTION_SEND);
2999          sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
3000          sendIntent.putExtra(Intent.EXTRA_TITLE, title);
3001          if (imageThumbnail != null) {
3002              ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
3003              sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
3004          }
3005  
3006          return sendIntent;
3007      }
3008  
createSendUriIntentWithPreview(ArrayList<Uri> uris)3009      private Intent createSendUriIntentWithPreview(ArrayList<Uri> uris) {
3010          Intent sendIntent = new Intent();
3011  
3012          if (uris.size() > 1) {
3013              sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
3014              sendIntent.putExtra(Intent.EXTRA_STREAM, uris);
3015          } else {
3016              sendIntent.setAction(Intent.ACTION_SEND);
3017              sendIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
3018          }
3019  
3020          return sendIntent;
3021      }
3022  
createViewTextIntent()3023      private Intent createViewTextIntent() {
3024          Intent viewIntent = new Intent();
3025          viewIntent.setAction(Intent.ACTION_VIEW);
3026          viewIntent.putExtra(Intent.EXTRA_TEXT, "testing intent viewing");
3027          return viewIntent;
3028      }
3029  
createResolvedComponentsForTest(int numberOfResults)3030      private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
3031          List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
3032          for (int i = 0; i < numberOfResults; i++) {
3033              infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, PERSONAL_USER_HANDLE));
3034          }
3035          return infoList;
3036      }
3037  
createResolvedComponentsWithCloneProfileForTest( int numberOfResults, UserHandle resolvedForPersonalUser, UserHandle resolvedForClonedUser)3038      private List<ResolvedComponentInfo> createResolvedComponentsWithCloneProfileForTest(
3039              int numberOfResults,
3040              UserHandle resolvedForPersonalUser,
3041              UserHandle resolvedForClonedUser) {
3042          List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
3043          for (int i = 0; i < 1; i++) {
3044              infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
3045                      resolvedForPersonalUser));
3046          }
3047          for (int i = 1; i < numberOfResults; i++) {
3048              infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
3049                      resolvedForClonedUser));
3050          }
3051          return infoList;
3052      }
3053  
createResolvedComponentsForTestWithOtherProfile( int numberOfResults)3054      private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
3055              int numberOfResults) {
3056          List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
3057          for (int i = 0; i < numberOfResults; i++) {
3058              if (i == 0) {
3059                  infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i,
3060                          PERSONAL_USER_HANDLE));
3061              } else {
3062                  infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
3063                          PERSONAL_USER_HANDLE));
3064              }
3065          }
3066          return infoList;
3067      }
3068  
createResolvedComponentsForTestWithOtherProfile( int numberOfResults, int userId)3069      private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
3070              int numberOfResults, int userId) {
3071          List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
3072          for (int i = 0; i < numberOfResults; i++) {
3073              if (i == 0) {
3074                  infoList.add(
3075                          ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
3076                                  PERSONAL_USER_HANDLE));
3077              } else {
3078                  infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
3079                          PERSONAL_USER_HANDLE));
3080              }
3081          }
3082          return infoList;
3083      }
3084  
createResolvedComponentsForTestWithUserId( int numberOfResults, int userId)3085      private List<ResolvedComponentInfo> createResolvedComponentsForTestWithUserId(
3086              int numberOfResults, int userId) {
3087          List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
3088          for (int i = 0; i < numberOfResults; i++) {
3089              infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
3090                      PERSONAL_USER_HANDLE));
3091          }
3092          return infoList;
3093      }
3094  
createDirectShareTargets(int numberOfResults, String packageName)3095      private List<ChooserTarget> createDirectShareTargets(int numberOfResults, String packageName) {
3096          Icon icon = Icon.createWithBitmap(createBitmap());
3097          String testTitle = "testTitle";
3098          List<ChooserTarget> targets = new ArrayList<>();
3099          for (int i = 0; i < numberOfResults; i++) {
3100              ComponentName componentName;
3101              if (packageName.isEmpty()) {
3102                  componentName = ResolverDataProvider.createComponentName(i);
3103              } else {
3104                  componentName = new ComponentName(packageName, packageName + ".class");
3105              }
3106              ChooserTarget tempTarget = new ChooserTarget(
3107                      testTitle + i,
3108                      icon,
3109                      (float) (1 - ((i + 1) / 10.0)),
3110                      componentName,
3111                      null);
3112              targets.add(tempTarget);
3113          }
3114          return targets;
3115      }
3116  
waitForIdle()3117      private void waitForIdle() {
3118          InstrumentationRegistry.getInstrumentation().waitForIdleSync();
3119      }
3120  
createBitmap()3121      private Bitmap createBitmap() {
3122          int width = 200;
3123          int height = 200;
3124          Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
3125          Canvas canvas = new Canvas(bitmap);
3126  
3127          Paint paint = new Paint();
3128          paint.setColor(Color.RED);
3129          paint.setStyle(Paint.Style.FILL);
3130          canvas.drawPaint(paint);
3131  
3132          paint.setColor(Color.WHITE);
3133          paint.setAntiAlias(true);
3134          paint.setTextSize(14.f);
3135          paint.setTextAlign(Paint.Align.CENTER);
3136          canvas.drawText("Hi!", (width / 2.f), (height / 2.f), paint);
3137  
3138          return bitmap;
3139      }
3140  
createShortcuts(Context context)3141      private List<ShareShortcutInfo> createShortcuts(Context context) {
3142          Intent testIntent = new Intent("TestIntent");
3143  
3144          List<ShareShortcutInfo> shortcuts = new ArrayList<>();
3145          shortcuts.add(new ShareShortcutInfo(
3146                  new ShortcutInfo.Builder(context, "shortcut1")
3147                          .setIntent(testIntent).setShortLabel("label1").setRank(3).build(), // 0  2
3148                  new ComponentName("package1", "class1")));
3149          shortcuts.add(new ShareShortcutInfo(
3150                  new ShortcutInfo.Builder(context, "shortcut2")
3151                          .setIntent(testIntent).setShortLabel("label2").setRank(7).build(), // 1  3
3152                  new ComponentName("package2", "class2")));
3153          shortcuts.add(new ShareShortcutInfo(
3154                  new ShortcutInfo.Builder(context, "shortcut3")
3155                          .setIntent(testIntent).setShortLabel("label3").setRank(1).build(), // 2  0
3156                  new ComponentName("package3", "class3")));
3157          shortcuts.add(new ShareShortcutInfo(
3158                  new ShortcutInfo.Builder(context, "shortcut4")
3159                          .setIntent(testIntent).setShortLabel("label4").setRank(3).build(), // 3  2
3160                  new ComponentName("package4", "class4")));
3161  
3162          return shortcuts;
3163      }
3164  
assertCorrectShortcutToChooserTargetConversion(List<ShareShortcutInfo> shortcuts, List<ChooserTarget> chooserTargets, int[] expectedOrder, float[] expectedScores)3165      private void assertCorrectShortcutToChooserTargetConversion(List<ShareShortcutInfo> shortcuts,
3166              List<ChooserTarget> chooserTargets, int[] expectedOrder, float[] expectedScores) {
3167          assertEquals(expectedOrder.length, chooserTargets.size());
3168          for (int i = 0; i < chooserTargets.size(); i++) {
3169              ChooserTarget ct = chooserTargets.get(i);
3170              ShortcutInfo si = shortcuts.get(expectedOrder[i]).getShortcutInfo();
3171              ComponentName cn = shortcuts.get(expectedOrder[i]).getTargetComponent();
3172  
3173              assertEquals(si.getId(), ct.getIntentExtras().getString(Intent.EXTRA_SHORTCUT_ID));
3174              assertEquals(si.getShortLabel(), ct.getTitle());
3175              assertThat(Math.abs(expectedScores[i] - ct.getScore()) < 0.000001, is(true));
3176              assertEquals(cn.flattenToString(), ct.getComponentName().flattenToString());
3177          }
3178      }
3179  
3180      private void markWorkProfileUserAvailable() {
3181          ChooserActivityOverrideData.getInstance().workProfileUserHandle = UserHandle.of(10);
3182      }
3183  
3184      private void markCloneProfileUserAvailable() {
3185          ChooserActivityOverrideData.getInstance().cloneProfileUserHandle = UserHandle.of(11);
3186      }
3187  
3188      private void setupResolverControllers(
3189              List<ResolvedComponentInfo> personalResolvedComponentInfos,
3190              List<ResolvedComponentInfo> workResolvedComponentInfos) {
3191          when(
3192                  ChooserActivityOverrideData
3193                          .getInstance()
3194                          .resolverListController
3195                          .getResolversForIntent(
3196                                  Mockito.anyBoolean(),
3197                                  Mockito.anyBoolean(),
3198                                  Mockito.anyBoolean(),
3199                                  Mockito.isA(List.class)))
3200                  .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
3201          when(
3202                  ChooserActivityOverrideData
3203                          .getInstance()
3204                          .workResolverListController
3205                          .getResolversForIntent(
3206                                  Mockito.anyBoolean(),
3207                                  Mockito.anyBoolean(),
3208                                  Mockito.anyBoolean(),
3209                                  Mockito.isA(List.class)))
3210                  .thenReturn(new ArrayList<>(workResolvedComponentInfos));
3211          when(
3212                  ChooserActivityOverrideData
3213                          .getInstance()
3214                          .workResolverListController
3215                          .getResolversForIntentAsUser(
3216                                  Mockito.anyBoolean(),
3217                                  Mockito.anyBoolean(),
3218                                  Mockito.anyBoolean(),
3219                                  Mockito.isA(List.class),
3220                                  eq(UserHandle.SYSTEM)))
3221                  .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
3222      }
3223  
3224      private Matcher<View> withIdFromRuntimeResource(String id) {
3225          return withId(getRuntimeResourceId(id, "id"));
3226      }
3227  
3228      private Matcher<View> withTextFromRuntimeResource(String id) {
3229          return withText(getRuntimeResourceId(id, "string"));
3230      }
3231  
3232      private static GridRecyclerSpanCountMatcher withGridColumnCount(int columnCount) {
3233          return new GridRecyclerSpanCountMatcher(Matchers.is(columnCount));
3234      }
3235  
3236      private static class GridRecyclerSpanCountMatcher extends
3237              BoundedDiagnosingMatcher<View, RecyclerView> {
3238  
3239          private final Matcher<Integer> mIntegerMatcher;
3240  
3241          private GridRecyclerSpanCountMatcher(Matcher<Integer> integerMatcher) {
3242              super(RecyclerView.class);
3243              this.mIntegerMatcher = integerMatcher;
3244          }
3245  
3246          @Override
3247          protected void describeMoreTo(Description description) {
3248              description.appendText("RecyclerView grid layout span count to match: ");
3249              this.mIntegerMatcher.describeTo(description);
3250          }
3251  
3252          @Override
3253          protected boolean matchesSafely(RecyclerView view, Description mismatchDescription) {
3254              int spanCount = ((GridLayoutManager) view.getLayoutManager()).getSpanCount();
3255              if (this.mIntegerMatcher.matches(spanCount)) {
3256                  return true;
3257              } else {
3258                  mismatchDescription.appendText("RecyclerView grid layout span count was ")
3259                          .appendValue(spanCount);
3260                  return false;
3261              }
3262          }
3263      }
3264  
3265      private void givenAppTargets(int appCount) {
3266          List<ResolvedComponentInfo> resolvedComponentInfos =
3267                  createResolvedComponentsForTest(appCount);
3268          when(
3269                  ChooserActivityOverrideData
3270                          .getInstance()
3271                          .resolverListController
3272                          .getResolversForIntent(
3273                                  Mockito.anyBoolean(),
3274                                  Mockito.anyBoolean(),
3275                                  Mockito.anyBoolean(),
3276                                  Mockito.isA(List.class)))
3277                  .thenReturn(resolvedComponentInfos);
3278      }
3279  
3280      private void updateMaxTargetsPerRowResource(int targetsPerRow) {
3281          ChooserActivityOverrideData.getInstance().resources = Mockito.spy(
3282                  InstrumentationRegistry.getInstrumentation().getContext().getResources());
3283          when(
3284                  ChooserActivityOverrideData
3285                          .getInstance()
3286                          .resources
3287                          .getInteger(R.integer.config_chooser_max_targets_per_row))
3288                  .thenReturn(targetsPerRow);
3289      }
3290  
3291      // ChooserWrapperActivity inherits from the framework ChooserActivity, so if the framework
3292      // resources have been updated since the framework was last built/pushed, the inherited behavior
3293      // (which is the focus of our testing) will still be implemented in terms of the old resource
3294      // IDs; then when we try to assert those IDs in tests (e.g. `onView(withText(R.string.foo))`),
3295      // the expected values won't match. The tests can instead call this method (with the same
3296      // general semantics as Resources#getIdentifier() e.g. `getRuntimeResourceId("foo", "string")`)
3297      // to refer to the resource by that name in the runtime chooser, regardless of whether the
3298      // framework code on the device is up-to-date.
3299      // TODO: is there a better way to do this? (Other than abandoning inheritance-based DI wrapper?)
3300      private int getRuntimeResourceId(String name, String defType) {
3301          int id = -1;
3302          if (ChooserActivityOverrideData.getInstance().resources != null) {
3303              id = ChooserActivityOverrideData.getInstance().resources.getIdentifier(
3304                    name, defType, "android");
3305          } else {
3306              id = mActivityRule.getActivity().getResources().getIdentifier(name, defType, "android");
3307          }
3308          assertThat(id, greaterThan(0));
3309  
3310          return id;
3311      }
3312  }
3313