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.ChooserWrapperActivity.sOverrides;
38 import static com.android.internal.app.MatcherUtils.first;
39 
40 import static junit.framework.Assert.assertFalse;
41 import static junit.framework.Assert.assertNull;
42 import static junit.framework.Assert.assertTrue;
43 
44 import static org.hamcrest.CoreMatchers.allOf;
45 import static org.hamcrest.CoreMatchers.is;
46 import static org.hamcrest.CoreMatchers.not;
47 import static org.hamcrest.CoreMatchers.notNullValue;
48 import static org.hamcrest.MatcherAssert.assertThat;
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 
85 import androidx.test.platform.app.InstrumentationRegistry;
86 import androidx.test.rule.ActivityTestRule;
87 
88 import com.android.internal.R;
89 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
90 import com.android.internal.app.chooser.DisplayResolveInfo;
91 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
92 import com.android.internal.logging.MetricsLogger;
93 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
94 import com.android.internal.util.FrameworkStatsLog;
95 
96 import org.junit.Before;
97 import org.junit.Ignore;
98 import org.junit.Rule;
99 import org.junit.Test;
100 import org.junit.runner.RunWith;
101 import org.junit.runners.Parameterized;
102 import org.mockito.ArgumentCaptor;
103 import org.mockito.Mockito;
104 
105 import java.util.ArrayList;
106 import java.util.Arrays;
107 import java.util.Collection;
108 import java.util.HashMap;
109 import java.util.List;
110 import java.util.Map;
111 import java.util.function.Function;
112 
113 /**
114  * Chooser activity instrumentation tests
115  */
116 @RunWith(Parameterized.class)
117 public class ChooserActivityTest {
118 
119     private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm;
120     private static final Function<PackageManager, PackageManager> NO_APP_PREDICTION_SERVICE_PM =
121             pm -> {
122                 PackageManager mock = Mockito.spy(pm);
123                 when(mock.getAppPredictionServicePackageName()).thenReturn(null);
124                 return mock;
125             };
126 
127     @Parameterized.Parameters
packageManagers()128     public static Collection packageManagers() {
129         return Arrays.asList(new Object[][] {
130                 {0, "Default PackageManager", DEFAULT_PM},
131                 {1, "No App Prediction Service", NO_APP_PREDICTION_SERVICE_PM}
132         });
133     }
134 
135     private static final int CONTENT_PREVIEW_IMAGE = 1;
136     private static final int CONTENT_PREVIEW_FILE = 2;
137     private static final int CONTENT_PREVIEW_TEXT = 3;
138     private Function<PackageManager, PackageManager> mPackageManagerOverride;
139     private int mTestNum;
140 
141     @Rule
142     public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
143             new ActivityTestRule<>(ChooserWrapperActivity.class, false,
144                     false);
145 
ChooserActivityTest( int testNum, String testName, Function<PackageManager, PackageManager> packageManagerOverride)146     public ChooserActivityTest(
147                 int testNum,
148                 String testName,
149                 Function<PackageManager, PackageManager> packageManagerOverride) {
150         mPackageManagerOverride = packageManagerOverride;
151         mTestNum = testNum;
152     }
153 
154     @Before
cleanOverrideData()155     public void cleanOverrideData() {
156         sOverrides.reset();
157         sOverrides.createPackageManager = mPackageManagerOverride;
158         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
159                 SystemUiDeviceConfigFlags.APPLY_SHARING_APP_LIMITS_IN_SYSUI,
160                 Boolean.toString(true),
161                 true /* makeDefault*/);
162     }
163 
164     @Test
customTitle()165     public void customTitle() throws InterruptedException {
166         Intent viewIntent = createViewTextIntent();
167         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
168 
169         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
170                 Mockito.anyBoolean(),
171                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
172         final ChooserWrapperActivity activity = mActivityRule.launchActivity(
173                 Intent.createChooser(viewIntent, "chooser test"));
174 
175         waitForIdle();
176         assertThat(activity.getAdapter().getCount(), is(2));
177         assertThat(activity.getAdapter().getServiceTargetCount(), is(0));
178         onView(withId(R.id.title)).check(matches(withText("chooser test")));
179     }
180 
181     @Test
customTitleIgnoredForSendIntents()182     public void customTitleIgnoredForSendIntents() throws InterruptedException {
183         Intent sendIntent = createSendTextIntent();
184         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
185 
186         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
187                 Mockito.anyBoolean(),
188                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
189         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test"));
190         waitForIdle();
191         onView(withId(R.id.title)).check(matches(withText(R.string.whichSendApplication)));
192     }
193 
194     @Test
emptyTitle()195     public void emptyTitle() throws InterruptedException {
196         Intent sendIntent = createSendTextIntent();
197         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
198 
199         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
200                 Mockito.anyBoolean(),
201                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
202         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
203         waitForIdle();
204         onView(withId(R.id.title))
205                 .check(matches(withText(R.string.whichSendApplication)));
206     }
207 
208     @Test
emptyPreviewTitleAndThumbnail()209     public void emptyPreviewTitleAndThumbnail() throws InterruptedException {
210         Intent sendIntent = createSendTextIntentWithPreview(null, null);
211         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
212 
213         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
214                 Mockito.anyBoolean(),
215                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
216         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
217         waitForIdle();
218         onView(withId(R.id.content_preview_title)).check(matches(not(isDisplayed())));
219         onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
220     }
221 
222     @Test
visiblePreviewTitleWithoutThumbnail()223     public void visiblePreviewTitleWithoutThumbnail() throws InterruptedException {
224         String previewTitle = "My Content Preview Title";
225         Intent sendIntent = createSendTextIntentWithPreview(previewTitle, null);
226         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
227 
228         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
229                 Mockito.anyBoolean(),
230                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
231         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
232         waitForIdle();
233         onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
234         onView(withId(R.id.content_preview_title)).check(matches(withText(previewTitle)));
235         onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
236     }
237 
238     @Test
visiblePreviewTitleWithInvalidThumbnail()239     public void visiblePreviewTitleWithInvalidThumbnail() throws InterruptedException {
240         String previewTitle = "My Content Preview Title";
241         Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
242                 Uri.parse("tel:(+49)12345789"));
243         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
244 
245         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
246                 Mockito.anyBoolean(),
247                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
248         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
249         waitForIdle();
250         onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
251         onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
252     }
253 
254     @Test
visiblePreviewTitleAndThumbnail()255     public void visiblePreviewTitleAndThumbnail() throws InterruptedException {
256         String previewTitle = "My Content Preview Title";
257         Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
258                 Uri.parse("android.resource://com.android.frameworks.coretests/"
259                         + com.android.frameworks.coretests.R.drawable.test320x240));
260         sOverrides.previewThumbnail = createBitmap();
261         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
262 
263         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
264                 Mockito.anyBoolean(),
265                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
266         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
267         waitForIdle();
268         onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
269         onView(withId(R.id.content_preview_thumbnail)).check(matches(isDisplayed()));
270     }
271 
272     @Test
twoOptionsAndUserSelectsOne()273     public void twoOptionsAndUserSelectsOne() throws InterruptedException {
274         Intent sendIntent = createSendTextIntent();
275         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
276 
277         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
278                 Mockito.anyBoolean(),
279                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
280 
281         final ChooserWrapperActivity activity = mActivityRule
282                 .launchActivity(Intent.createChooser(sendIntent, null));
283         waitForIdle();
284 
285         assertThat(activity.getAdapter().getCount(), is(2));
286         onView(withId(R.id.profile_button)).check(doesNotExist());
287 
288         ResolveInfo[] chosen = new ResolveInfo[1];
289         sOverrides.onSafelyStartCallback = targetInfo -> {
290             chosen[0] = targetInfo.getResolveInfo();
291             return true;
292         };
293 
294         ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
295         onView(withText(toChoose.activityInfo.name))
296                 .perform(click());
297         waitForIdle();
298         assertThat(chosen[0], is(toChoose));
299     }
300 
301     @Test
fourOptionsStackedIntoOneTarget()302     public void fourOptionsStackedIntoOneTarget() throws InterruptedException {
303         Intent sendIntent = createSendTextIntent();
304 
305         // create just enough targets to ensure the a-z list should be shown
306         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
307 
308         // next create 4 targets in a single app that should be stacked into a single target
309         String packageName = "xxx.yyy";
310         String appName = "aaa";
311         ComponentName cn = new ComponentName(packageName, appName);
312         Intent intent = new Intent("fakeIntent");
313         List<ResolvedComponentInfo> infosToStack = new ArrayList<>();
314         for (int i = 0; i < 4; i++) {
315             ResolveInfo resolveInfo = ResolverDataProvider.createResolveInfo(i,
316                     UserHandle.USER_CURRENT);
317             resolveInfo.activityInfo.applicationInfo.name = appName;
318             resolveInfo.activityInfo.applicationInfo.packageName = packageName;
319             resolveInfo.activityInfo.packageName = packageName;
320             resolveInfo.activityInfo.name = "ccc" + i;
321             infosToStack.add(new ResolvedComponentInfo(cn, intent, resolveInfo));
322         }
323         resolvedComponentInfos.addAll(infosToStack);
324 
325         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
326                 Mockito.anyBoolean(),
327                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
328 
329         final ChooserWrapperActivity activity = mActivityRule
330                 .launchActivity(Intent.createChooser(sendIntent, null));
331         waitForIdle();
332 
333         // expect 1 unique targets + 1 group + 4 ranked app targets
334         assertThat(activity.getAdapter().getCount(), is(6));
335 
336         ResolveInfo[] chosen = new ResolveInfo[1];
337         sOverrides.onSafelyStartCallback = targetInfo -> {
338             chosen[0] = targetInfo.getResolveInfo();
339             return true;
340         };
341 
342         onView(allOf(withText(appName), hasSibling(withText("")))).perform(click());
343         waitForIdle();
344 
345         // clicking will launch a dialog to choose the activity within the app
346         onView(withText(appName)).check(matches(isDisplayed()));
347         int i = 0;
348         for (ResolvedComponentInfo rci: infosToStack) {
349             onView(withText("ccc" + i)).check(matches(isDisplayed()));
350             ++i;
351         }
352     }
353 
354     @Test
updateChooserCountsAndModelAfterUserSelection()355     public void updateChooserCountsAndModelAfterUserSelection() throws InterruptedException {
356         Intent sendIntent = createSendTextIntent();
357         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
358 
359         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
360                 Mockito.anyBoolean(),
361                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
362 
363         final ChooserWrapperActivity activity = mActivityRule
364                 .launchActivity(Intent.createChooser(sendIntent, null));
365         waitForIdle();
366         UsageStatsManager usm = activity.getUsageStatsManager();
367         verify(sOverrides.resolverListController, times(1))
368                 .topK(any(List.class), anyInt());
369         assertThat(activity.getIsSelected(), is(false));
370         sOverrides.onSafelyStartCallback = targetInfo -> {
371             return true;
372         };
373         ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
374         onView(withText(toChoose.activityInfo.name))
375                 .perform(click());
376         waitForIdle();
377         verify(sOverrides.resolverListController, times(1))
378                 .updateChooserCounts(Mockito.anyString(), anyInt(), Mockito.anyString());
379         verify(sOverrides.resolverListController, times(1))
380                 .updateModel(toChoose.activityInfo.getComponentName());
381         assertThat(activity.getIsSelected(), is(true));
382     }
383 
384     @Ignore // b/148158199
385     @Test
noResultsFromPackageManager()386     public void noResultsFromPackageManager() {
387         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
388                 Mockito.anyBoolean(),
389                 Mockito.isA(List.class))).thenReturn(null);
390         Intent sendIntent = createSendTextIntent();
391         final ChooserWrapperActivity activity = mActivityRule
392                 .launchActivity(Intent.createChooser(sendIntent, null));
393         waitForIdle();
394         assertThat(activity.isFinishing(), is(false));
395 
396         onView(withId(R.id.empty)).check(matches(isDisplayed()));
397         onView(withId(R.id.profile_pager)).check(matches(not(isDisplayed())));
398         InstrumentationRegistry.getInstrumentation().runOnMainSync(
399                 () -> activity.getAdapter().handlePackagesChanged()
400         );
401         // backward compatibility. looks like we finish when data is empty after package change
402         assertThat(activity.isFinishing(), is(true));
403     }
404 
405     @Test
autoLaunchSingleResult()406     public void autoLaunchSingleResult() throws InterruptedException {
407         ResolveInfo[] chosen = new ResolveInfo[1];
408         sOverrides.onSafelyStartCallback = targetInfo -> {
409             chosen[0] = targetInfo.getResolveInfo();
410             return true;
411         };
412 
413         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
414         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
415                 Mockito.anyBoolean(),
416                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
417 
418         Intent sendIntent = createSendTextIntent();
419         final ChooserWrapperActivity activity = mActivityRule
420                 .launchActivity(Intent.createChooser(sendIntent, null));
421         waitForIdle();
422 
423         assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0)));
424         assertThat(activity.isFinishing(), is(true));
425     }
426 
427     @Test
hasOtherProfileOneOption()428     public void hasOtherProfileOneOption() throws Exception {
429         // enable the work tab feature flag
430         ResolverActivity.ENABLE_TABBED_VIEW = true;
431         List<ResolvedComponentInfo> personalResolvedComponentInfos =
432                 createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
433         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
434         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
435         markWorkProfileUserAvailable();
436 
437         ResolveInfo toChoose = personalResolvedComponentInfos.get(1).getResolveInfoAt(0);
438         Intent sendIntent = createSendTextIntent();
439         final ChooserWrapperActivity activity = mActivityRule
440                 .launchActivity(Intent.createChooser(sendIntent, null));
441         waitForIdle();
442 
443         // The other entry is filtered to the other profile slot
444         assertThat(activity.getAdapter().getCount(), is(1));
445 
446         ResolveInfo[] chosen = new ResolveInfo[1];
447         ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
448             chosen[0] = targetInfo.getResolveInfo();
449             return true;
450         };
451 
452         // Make a stable copy of the components as the original list may be modified
453         List<ResolvedComponentInfo> stableCopy =
454                 createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10);
455         waitForIdle();
456         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
457 
458         onView(first(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name)))
459                 .perform(click());
460         waitForIdle();
461         assertThat(chosen[0], is(toChoose));
462     }
463 
464     @Test
hasOtherProfileTwoOptionsAndUserSelectsOne()465     public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
466         // enable the work tab feature flag
467         ResolverActivity.ENABLE_TABBED_VIEW = true;
468 
469         Intent sendIntent = createSendTextIntent();
470         List<ResolvedComponentInfo> resolvedComponentInfos =
471                 createResolvedComponentsForTestWithOtherProfile(3);
472         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
473 
474         when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
475                 Mockito.anyBoolean(),
476                 Mockito.anyBoolean(),
477                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
478         when(ChooserWrapperActivity.sOverrides.resolverListController.getLastChosen())
479                 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
480 
481         final ChooserWrapperActivity activity = mActivityRule
482                 .launchActivity(Intent.createChooser(sendIntent, null));
483         waitForIdle();
484 
485         // The other entry is filtered to the other profile slot
486         assertThat(activity.getAdapter().getCount(), is(2));
487 
488         ResolveInfo[] chosen = new ResolveInfo[1];
489         ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
490             chosen[0] = targetInfo.getResolveInfo();
491             return true;
492         };
493 
494         // Make a stable copy of the components as the original list may be modified
495         List<ResolvedComponentInfo> stableCopy =
496                 createResolvedComponentsForTestWithOtherProfile(3);
497         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
498                 .perform(click());
499         waitForIdle();
500         assertThat(chosen[0], is(toChoose));
501     }
502 
503     @Test
hasLastChosenActivityAndOtherProfile()504     public void hasLastChosenActivityAndOtherProfile() throws Exception {
505         // enable the work tab feature flag
506         ResolverActivity.ENABLE_TABBED_VIEW = true;
507 
508         Intent sendIntent = createSendTextIntent();
509         List<ResolvedComponentInfo> resolvedComponentInfos =
510                 createResolvedComponentsForTestWithOtherProfile(3);
511         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
512 
513         when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
514                 Mockito.anyBoolean(),
515                 Mockito.anyBoolean(),
516                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
517 
518         final ChooserWrapperActivity activity = mActivityRule
519                 .launchActivity(Intent.createChooser(sendIntent, null));
520         waitForIdle();
521 
522         // The other entry is filtered to the last used slot
523         assertThat(activity.getAdapter().getCount(), is(2));
524 
525         ResolveInfo[] chosen = new ResolveInfo[1];
526         ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
527             chosen[0] = targetInfo.getResolveInfo();
528             return true;
529         };
530 
531         // Make a stable copy of the components as the original list may be modified
532         List<ResolvedComponentInfo> stableCopy =
533                 createResolvedComponentsForTestWithOtherProfile(3);
534         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
535                 .perform(click());
536         waitForIdle();
537         assertThat(chosen[0], is(toChoose));
538     }
539 
540     @Test
copyTextToClipboard()541     public void copyTextToClipboard() throws Exception {
542         Intent sendIntent = createSendTextIntent();
543         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
544 
545         when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
546             Mockito.anyBoolean(),
547             Mockito.anyBoolean(),
548             Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
549 
550         final ChooserWrapperActivity activity = mActivityRule
551                 .launchActivity(Intent.createChooser(sendIntent, null));
552         waitForIdle();
553 
554         onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed()));
555         onView(withId(R.id.chooser_copy_button)).perform(click());
556         ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(
557                 Context.CLIPBOARD_SERVICE);
558         ClipData clipData = clipboard.getPrimaryClip();
559         assertThat("testing intent sending", is(clipData.getItemAt(0).getText()));
560 
561         ClipDescription clipDescription = clipData.getDescription();
562         assertThat("text/plain", is(clipDescription.getMimeType(0)));
563 
564         assertEquals(mActivityRule.getActivityResult().getResultCode(), RESULT_OK);
565     }
566 
567     @Test
copyTextToClipboardLogging()568     public void copyTextToClipboardLogging() throws Exception {
569         Intent sendIntent = createSendTextIntent();
570         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
571 
572         when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
573             Mockito.anyBoolean(),
574             Mockito.anyBoolean(),
575             Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
576 
577         MetricsLogger mockLogger = sOverrides.metricsLogger;
578         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
579 
580         final ChooserWrapperActivity activity = mActivityRule
581                 .launchActivity(Intent.createChooser(sendIntent, null));
582         waitForIdle();
583 
584         onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed()));
585         onView(withId(R.id.chooser_copy_button)).perform(click());
586 
587         verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
588         // First is  Activity shown, Second is "with preview"
589         assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
590                 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SYSTEM_TARGET));
591         assertThat(logMakerCaptor
592                         .getAllValues().get(2)
593                         .getSubtype(),
594                 is(1));
595     }
596 
597 
598     @Test
testNearbyShareLogging()599     public void testNearbyShareLogging() throws Exception {
600         Intent sendIntent = createSendTextIntent();
601         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
602 
603         when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
604                 Mockito.anyBoolean(),
605                 Mockito.anyBoolean(),
606                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
607 
608         final ChooserWrapperActivity activity = mActivityRule
609                 .launchActivity(Intent.createChooser(sendIntent, null));
610         waitForIdle();
611 
612         onView(withId(R.id.chooser_nearby_button)).check(matches(isDisplayed()));
613         onView(withId(R.id.chooser_nearby_button)).perform(click());
614 
615         ChooserActivityLoggerFake logger =
616                 (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
617         assertThat(logger.numCalls(), is(6));
618         // first one should be SHARESHEET_TRIGGERED uievent
619         assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
620         assertThat(logger.get(0).event.getId(),
621                 is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
622         // second one should be SHARESHEET_STARTED event
623         assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
624         assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
625         assertThat(logger.get(1).mimeType, is("text/plain"));
626         assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
627         assertThat(logger.get(1).appProvidedApp, is(0));
628         assertThat(logger.get(1).appProvidedDirect, is(0));
629         assertThat(logger.get(1).isWorkprofile, is(false));
630         assertThat(logger.get(1).previewType, is(3));
631         // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
632         assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
633         assertThat(logger.get(2).event.getId(),
634                 is(ChooserActivityLogger
635                         .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
636         // fourth and fifth are just artifacts of test set-up
637         // sixth one should be ranking atom with SHARESHEET_NEARBY_TARGET_SELECTED event
638         assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
639         assertThat(logger.get(5).targetType,
640                 is(ChooserActivityLogger
641                         .SharesheetTargetSelectedEvent.SHARESHEET_NEARBY_TARGET_SELECTED.getId()));
642     }
643 
644 
645 
646     @Test
testEditImageLogs()647     public void testEditImageLogs() throws Exception {
648         Intent sendIntent = createSendImageIntent(
649                 Uri.parse("android.resource://com.android.frameworks.coretests/"
650                         + com.android.frameworks.coretests.R.drawable.test320x240));
651 
652         sOverrides.previewThumbnail = createBitmap();
653         sOverrides.isImageType = true;
654 
655         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
656 
657         when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
658                 Mockito.anyBoolean(),
659                 Mockito.anyBoolean(),
660                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
661 
662         final ChooserWrapperActivity activity = mActivityRule
663                 .launchActivity(Intent.createChooser(sendIntent, null));
664         waitForIdle();
665 
666         onView(withId(R.id.chooser_edit_button)).check(matches(isDisplayed()));
667         onView(withId(R.id.chooser_edit_button)).perform(click());
668 
669         ChooserActivityLoggerFake logger =
670                 (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
671         // first one should be SHARESHEET_TRIGGERED uievent
672         assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
673         assertThat(logger.get(0).event.getId(),
674                 is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
675         // second one should be SHARESHEET_STARTED event
676         assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
677         assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
678         assertThat(logger.get(1).mimeType, is("image/png"));
679         assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
680         assertThat(logger.get(1).appProvidedApp, is(0));
681         assertThat(logger.get(1).appProvidedDirect, is(0));
682         assertThat(logger.get(1).isWorkprofile, is(false));
683         assertThat(logger.get(1).previewType, is(1));
684         // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
685         assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
686         assertThat(logger.get(2).event.getId(),
687                 is(ChooserActivityLogger
688                         .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
689         // fourth and fifth are just artifacts of test set-up
690         // sixth one should be ranking atom with SHARESHEET_EDIT_TARGET_SELECTED event
691         assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
692         assertThat(logger.get(5).targetType,
693                 is(ChooserActivityLogger
694                         .SharesheetTargetSelectedEvent.SHARESHEET_EDIT_TARGET_SELECTED.getId()));
695     }
696 
697 
698     @Test
oneVisibleImagePreview()699     public void oneVisibleImagePreview() throws InterruptedException {
700         Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
701                 + com.android.frameworks.coretests.R.drawable.test320x240);
702 
703         ArrayList<Uri> uris = new ArrayList<>();
704         uris.add(uri);
705 
706         Intent sendIntent = createSendUriIntentWithPreview(uris);
707         sOverrides.previewThumbnail = createBitmap();
708         sOverrides.isImageType = true;
709 
710         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
711 
712         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
713                 Mockito.anyBoolean(),
714                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
715         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
716         waitForIdle();
717         onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
718         onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed())));
719         onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed())));
720         onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed())));
721     }
722 
723     @Test
twoVisibleImagePreview()724     public void twoVisibleImagePreview() throws InterruptedException {
725         Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
726                 + com.android.frameworks.coretests.R.drawable.test320x240);
727 
728         ArrayList<Uri> uris = new ArrayList<>();
729         uris.add(uri);
730         uris.add(uri);
731 
732         Intent sendIntent = createSendUriIntentWithPreview(uris);
733         sOverrides.previewThumbnail = createBitmap();
734         sOverrides.isImageType = true;
735 
736         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
737 
738         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
739                 Mockito.anyBoolean(),
740                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
741         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
742         waitForIdle();
743         onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
744         onView(withId(R.id.content_preview_image_2_large)).check(matches(isDisplayed()));
745         onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed())));
746         onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed())));
747     }
748 
749     @Test
threeOrMoreVisibleImagePreview()750     public void threeOrMoreVisibleImagePreview() throws InterruptedException {
751         Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
752                 + com.android.frameworks.coretests.R.drawable.test320x240);
753 
754         ArrayList<Uri> uris = new ArrayList<>();
755         uris.add(uri);
756         uris.add(uri);
757         uris.add(uri);
758         uris.add(uri);
759         uris.add(uri);
760 
761         Intent sendIntent = createSendUriIntentWithPreview(uris);
762         sOverrides.previewThumbnail = createBitmap();
763         sOverrides.isImageType = true;
764 
765         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
766 
767         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
768             Mockito.anyBoolean(),
769             Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
770         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
771         waitForIdle();
772         onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
773         onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed())));
774         onView(withId(R.id.content_preview_image_2_small)).check(matches(isDisplayed()));
775         onView(withId(R.id.content_preview_image_3_small)).check(matches(isDisplayed()));
776     }
777 
778     @Test
testOnCreateLogging()779     public void testOnCreateLogging() {
780         Intent sendIntent = createSendTextIntent();
781         sendIntent.setType("TestType");
782 
783         MetricsLogger mockLogger = sOverrides.metricsLogger;
784         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
785         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
786         waitForIdle();
787         verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
788         assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
789                 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
790         assertThat(logMakerCaptor
791                 .getAllValues().get(0)
792                 .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
793                 is(notNullValue()));
794         assertThat(logMakerCaptor
795                 .getAllValues().get(0)
796                 .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
797                 is("TestType"));
798         assertThat(logMakerCaptor
799                         .getAllValues().get(0)
800                         .getSubtype(),
801                 is(MetricsEvent.PARENT_PROFILE));
802     }
803 
804     @Test
testOnCreateLoggingFromWorkProfile()805     public void testOnCreateLoggingFromWorkProfile() {
806         Intent sendIntent = createSendTextIntent();
807         sendIntent.setType("TestType");
808         sOverrides.alternateProfileSetting = MetricsEvent.MANAGED_PROFILE;
809         MetricsLogger mockLogger = sOverrides.metricsLogger;
810         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
811         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
812         waitForIdle();
813         verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
814         assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
815                 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
816         assertThat(logMakerCaptor
817                         .getAllValues().get(0)
818                         .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
819                 is(notNullValue()));
820         assertThat(logMakerCaptor
821                         .getAllValues().get(0)
822                         .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
823                 is("TestType"));
824         assertThat(logMakerCaptor
825                         .getAllValues().get(0)
826                         .getSubtype(),
827                 is(MetricsEvent.MANAGED_PROFILE));
828     }
829 
830     @Test
testEmptyPreviewLogging()831     public void testEmptyPreviewLogging() {
832         Intent sendIntent = createSendTextIntentWithPreview(null, null);
833 
834         MetricsLogger mockLogger = sOverrides.metricsLogger;
835         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
836         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "empty preview logger test"));
837         waitForIdle();
838 
839         verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
840         // First invocation is from onCreate
841         assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
842                 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
843     }
844 
845     @Test
testTitlePreviewLogging()846     public void testTitlePreviewLogging() {
847         Intent sendIntent = createSendTextIntentWithPreview("TestTitle", null);
848 
849         MetricsLogger mockLogger = sOverrides.metricsLogger;
850         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
851 
852         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
853 
854         when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
855             Mockito.anyBoolean(),
856             Mockito.anyBoolean(),
857             Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
858 
859         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
860         waitForIdle();
861         // Second invocation is from onCreate
862         verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
863         assertThat(logMakerCaptor.getAllValues().get(0).getSubtype(),
864                 is(CONTENT_PREVIEW_TEXT));
865         assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
866                 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
867     }
868 
869     @Test
testImagePreviewLogging()870     public void testImagePreviewLogging() {
871         Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
872                 + com.android.frameworks.coretests.R.drawable.test320x240);
873 
874         ArrayList<Uri> uris = new ArrayList<>();
875         uris.add(uri);
876 
877         Intent sendIntent = createSendUriIntentWithPreview(uris);
878         sOverrides.previewThumbnail = createBitmap();
879         sOverrides.isImageType = true;
880 
881         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
882 
883         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
884             Mockito.anyBoolean(),
885             Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
886 
887         MetricsLogger mockLogger = sOverrides.metricsLogger;
888         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
889         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
890         waitForIdle();
891         verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
892         // First invocation is from onCreate
893         assertThat(logMakerCaptor.getAllValues().get(0).getSubtype(),
894                 is(CONTENT_PREVIEW_IMAGE));
895         assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
896                 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
897     }
898 
899     @Test
oneVisibleFilePreview()900     public void oneVisibleFilePreview() throws InterruptedException {
901         Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
902 
903         ArrayList<Uri> uris = new ArrayList<>();
904         uris.add(uri);
905 
906         Intent sendIntent = createSendUriIntentWithPreview(uris);
907 
908         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
909 
910         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
911                 Mockito.anyBoolean(),
912                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
913         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
914         waitForIdle();
915         onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
916         onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
917         onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
918     }
919 
920 
921     @Test
moreThanOneVisibleFilePreview()922     public void moreThanOneVisibleFilePreview() throws InterruptedException {
923         Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
924 
925         ArrayList<Uri> uris = new ArrayList<>();
926         uris.add(uri);
927         uris.add(uri);
928         uris.add(uri);
929 
930         Intent sendIntent = createSendUriIntentWithPreview(uris);
931 
932         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
933 
934         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
935                 Mockito.anyBoolean(),
936                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
937         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
938         waitForIdle();
939         onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
940         onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 2 files")));
941         onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
942     }
943 
944     @Test
contentProviderThrowSecurityException()945     public void contentProviderThrowSecurityException() throws InterruptedException {
946         Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
947 
948         ArrayList<Uri> uris = new ArrayList<>();
949         uris.add(uri);
950 
951         Intent sendIntent = createSendUriIntentWithPreview(uris);
952 
953         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
954         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
955                 Mockito.anyBoolean(),
956                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
957 
958         sOverrides.resolverForceException = true;
959 
960         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
961         waitForIdle();
962         onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
963         onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
964         onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
965     }
966 
967     @Test
contentProviderReturnsNoColumns()968     public void contentProviderReturnsNoColumns() throws InterruptedException {
969         Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
970 
971         ArrayList<Uri> uris = new ArrayList<>();
972         uris.add(uri);
973         uris.add(uri);
974 
975         Intent sendIntent = createSendUriIntentWithPreview(uris);
976 
977         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
978         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
979                 Mockito.anyBoolean(),
980                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
981 
982         Cursor cursor = mock(Cursor.class);
983         when(cursor.getCount()).thenReturn(1);
984         Mockito.doNothing().when(cursor).close();
985         when(cursor.moveToFirst()).thenReturn(true);
986         when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1);
987 
988         sOverrides.resolverCursor = cursor;
989 
990         mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
991         waitForIdle();
992         onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
993         onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 1 file")));
994         onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
995     }
996 
997     @Test
testGetBaseScore()998     public void testGetBaseScore() {
999         final float testBaseScore = 0.89f;
1000 
1001         Intent sendIntent = createSendTextIntent();
1002         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1003 
1004         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1005                 Mockito.anyBoolean(),
1006                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1007         when(sOverrides.resolverListController.getScore(Mockito.isA(DisplayResolveInfo.class)))
1008                 .thenReturn(testBaseScore);
1009 
1010         final ChooserWrapperActivity activity = mActivityRule
1011                 .launchActivity(Intent.createChooser(sendIntent, null));
1012         waitForIdle();
1013 
1014         final DisplayResolveInfo testDri =
1015                 activity.createTestDisplayResolveInfo(sendIntent,
1016                 ResolverDataProvider.createResolveInfo(3, 0), "testLabel", "testInfo", sendIntent,
1017                 /* resolveInfoPresentationGetter */ null);
1018         final ChooserListAdapter adapter = activity.getAdapter();
1019 
1020         assertThat(adapter.getBaseScore(null, 0), is(CALLER_TARGET_SCORE_BOOST));
1021         assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_DEFAULT), is(testBaseScore));
1022         assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_CHOOSER_TARGET), is(testBaseScore));
1023         assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE),
1024                 is(testBaseScore * SHORTCUT_TARGET_SCORE_BOOST));
1025         assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER),
1026                 is(testBaseScore * SHORTCUT_TARGET_SCORE_BOOST));
1027     }
1028 
1029     /**
1030      * The case when AppPrediction service is not defined in PackageManager is already covered
1031      * as a test parameter {@link ChooserActivityTest#packageManagers}. This test is checking the
1032      * case when the prediction service is defined but the component is not available on the device.
1033      */
1034     @Test
testIsAppPredictionServiceAvailable()1035     public void testIsAppPredictionServiceAvailable() {
1036         Intent sendIntent = createSendTextIntent();
1037         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1038         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1039                 Mockito.anyBoolean(),
1040                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1041 
1042         final ChooserWrapperActivity activity = mActivityRule
1043                 .launchActivity(Intent.createChooser(sendIntent, null));
1044         waitForIdle();
1045 
1046         if (activity.getPackageManager().getAppPredictionServicePackageName() == null) {
1047             assertThat(activity.isAppPredictionServiceAvailable(), is(false));
1048         } else {
1049             assertThat(activity.isAppPredictionServiceAvailable(), is(true));
1050 
1051             sOverrides.resources = Mockito.spy(activity.getResources());
1052             when(sOverrides.resources.getString(R.string.config_defaultAppPredictionService))
1053                     .thenReturn("ComponentNameThatDoesNotExist");
1054 
1055             assertThat(activity.isAppPredictionServiceAvailable(), is(false));
1056         }
1057     }
1058 
1059     @Test
testConvertToChooserTarget_predictionService()1060     public void testConvertToChooserTarget_predictionService() {
1061         Intent sendIntent = createSendTextIntent();
1062         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1063         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1064                 Mockito.anyBoolean(),
1065                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1066 
1067         final ChooserWrapperActivity activity = mActivityRule
1068                 .launchActivity(Intent.createChooser(sendIntent, null));
1069         waitForIdle();
1070 
1071         List<ShareShortcutInfo> shortcuts = createShortcuts(activity);
1072 
1073         int[] expectedOrderAllShortcuts = {0, 1, 2, 3};
1074         float[] expectedScoreAllShortcuts = {1.0f, 0.99f, 0.98f, 0.97f};
1075 
1076         List<ChooserTarget> chooserTargets = activity.convertToChooserTarget(shortcuts, shortcuts,
1077                 null, TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE);
1078         assertCorrectShortcutToChooserTargetConversion(shortcuts, chooserTargets,
1079                 expectedOrderAllShortcuts, expectedScoreAllShortcuts);
1080 
1081         List<ShareShortcutInfo> subset = new ArrayList<>();
1082         subset.add(shortcuts.get(1));
1083         subset.add(shortcuts.get(2));
1084         subset.add(shortcuts.get(3));
1085 
1086         int[] expectedOrderSubset = {1, 2, 3};
1087         float[] expectedScoreSubset = {0.99f, 0.98f, 0.97f};
1088 
1089         chooserTargets = activity.convertToChooserTarget(subset, shortcuts, null,
1090                 TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE);
1091         assertCorrectShortcutToChooserTargetConversion(shortcuts, chooserTargets,
1092                 expectedOrderSubset, expectedScoreSubset);
1093     }
1094 
1095     @Test
testConvertToChooserTarget_shortcutManager()1096     public void testConvertToChooserTarget_shortcutManager() {
1097         Intent sendIntent = createSendTextIntent();
1098         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1099         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1100                 Mockito.anyBoolean(),
1101                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1102 
1103         final ChooserWrapperActivity activity = mActivityRule
1104                 .launchActivity(Intent.createChooser(sendIntent, null));
1105         waitForIdle();
1106 
1107         List<ShareShortcutInfo> shortcuts = createShortcuts(activity);
1108 
1109         int[] expectedOrderAllShortcuts = {2, 0, 3, 1};
1110         float[] expectedScoreAllShortcuts = {1.0f, 0.99f, 0.99f, 0.98f};
1111 
1112         List<ChooserTarget> chooserTargets = activity.convertToChooserTarget(shortcuts, shortcuts,
1113                 null, TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER);
1114         assertCorrectShortcutToChooserTargetConversion(shortcuts, chooserTargets,
1115                 expectedOrderAllShortcuts, expectedScoreAllShortcuts);
1116 
1117         List<ShareShortcutInfo> subset = new ArrayList<>();
1118         subset.add(shortcuts.get(1));
1119         subset.add(shortcuts.get(2));
1120         subset.add(shortcuts.get(3));
1121 
1122         int[] expectedOrderSubset = {2, 3, 1};
1123         float[] expectedScoreSubset = {1.0f, 0.99f, 0.98f};
1124 
1125         chooserTargets = activity.convertToChooserTarget(subset, shortcuts, null,
1126                 TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER);
1127         assertCorrectShortcutToChooserTargetConversion(shortcuts, chooserTargets,
1128                 expectedOrderSubset, expectedScoreSubset);
1129     }
1130 
1131     // This test is too long and too slow and should not be taken as an example for future tests.
1132     @Test
testDirectTargetSelectionLogging()1133     public void testDirectTargetSelectionLogging() throws InterruptedException {
1134         Intent sendIntent = createSendTextIntent();
1135         // We need app targets for direct targets to get displayed
1136         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1137         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1138                 Mockito.anyBoolean(),
1139                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1140 
1141         // Set up resources
1142         MetricsLogger mockLogger = sOverrides.metricsLogger;
1143         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1144         // Create direct share target
1145         List<ChooserTarget> serviceTargets = createDirectShareTargets(1, "");
1146         ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
1147 
1148         // Start activity
1149         final ChooserWrapperActivity activity = mActivityRule
1150                 .launchActivity(Intent.createChooser(sendIntent, null));
1151 
1152         // Insert the direct share target
1153         Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1154         directShareToShortcutInfos.put(serviceTargets.get(0), null);
1155         InstrumentationRegistry.getInstrumentation().runOnMainSync(
1156                 () -> activity.getAdapter().addServiceResults(
1157                         activity.createTestDisplayResolveInfo(sendIntent,
1158                                 ri,
1159                                 "testLabel",
1160                                 "testInfo",
1161                                 sendIntent,
1162                                 /* resolveInfoPresentationGetter */ null),
1163                         serviceTargets,
1164                         TARGET_TYPE_CHOOSER_TARGET,
1165                         directShareToShortcutInfos,
1166                         List.of())
1167         );
1168 
1169         // Thread.sleep shouldn't be a thing in an integration test but it's
1170         // necessary here because of the way the code is structured
1171         // TODO: restructure the tests b/129870719
1172         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
1173 
1174         assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
1175                 activity.getAdapter().getCount(), is(3));
1176         assertThat("Chooser should have exactly one selectable direct target",
1177                 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
1178         assertThat("The resolver info must match the resolver info used to create the target",
1179                 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
1180 
1181         // Click on the direct target
1182         String name = serviceTargets.get(0).getTitle().toString();
1183         onView(withText(name))
1184                 .perform(click());
1185         waitForIdle();
1186 
1187         // Currently we're seeing 3 invocations
1188         //      1. ChooserActivity.onCreate()
1189         //      2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
1190         //      3. ChooserActivity.startSelected -- which is the one we're after
1191         verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
1192         assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
1193                 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
1194         String hashedName = (String) logMakerCaptor
1195                 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_HASHED_TARGET_NAME);
1196         assertThat("Hash is not predictable but must be obfuscated",
1197                 hashedName, is(not(name)));
1198         assertThat("The packages shouldn't match for app target and direct target", logMakerCaptor
1199                 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
1200     }
1201 
1202     // This test is too long and too slow and should not be taken as an example for future tests.
1203     @Test
testDirectTargetLoggingWithRankedAppTarget()1204     public void testDirectTargetLoggingWithRankedAppTarget() throws InterruptedException {
1205         Intent sendIntent = createSendTextIntent();
1206         // We need app targets for direct targets to get displayed
1207         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1208         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1209                 Mockito.anyBoolean(),
1210                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1211 
1212         // Set up resources
1213         MetricsLogger mockLogger = sOverrides.metricsLogger;
1214         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1215         // Create direct share target
1216         List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
1217                 resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
1218         ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
1219 
1220         // Start activity
1221         final ChooserWrapperActivity activity = mActivityRule
1222                 .launchActivity(Intent.createChooser(sendIntent, null));
1223 
1224         // Insert the direct share target
1225         Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1226         directShareToShortcutInfos.put(serviceTargets.get(0), null);
1227         InstrumentationRegistry.getInstrumentation().runOnMainSync(
1228                 () -> activity.getAdapter().addServiceResults(
1229                         activity.createTestDisplayResolveInfo(sendIntent,
1230                                 ri,
1231                                 "testLabel",
1232                                 "testInfo",
1233                                 sendIntent,
1234                                 /* resolveInfoPresentationGetter */ null),
1235                         serviceTargets,
1236                         TARGET_TYPE_CHOOSER_TARGET,
1237                         directShareToShortcutInfos,
1238                         List.of())
1239         );
1240         // Thread.sleep shouldn't be a thing in an integration test but it's
1241         // necessary here because of the way the code is structured
1242         // TODO: restructure the tests b/129870719
1243         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
1244 
1245         assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
1246                 activity.getAdapter().getCount(), is(3));
1247         assertThat("Chooser should have exactly one selectable direct target",
1248                 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
1249         assertThat("The resolver info must match the resolver info used to create the target",
1250                 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
1251 
1252         // Click on the direct target
1253         String name = serviceTargets.get(0).getTitle().toString();
1254         onView(withText(name))
1255                 .perform(click());
1256         waitForIdle();
1257 
1258         // Currently we're seeing 3 invocations
1259         //      1. ChooserActivity.onCreate()
1260         //      2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
1261         //      3. ChooserActivity.startSelected -- which is the one we're after
1262         verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
1263         assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
1264                 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
1265         assertThat("The packages should match for app target and direct target", logMakerCaptor
1266                 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(0));
1267     }
1268 
1269     @Test
testShortcutTargetWithApplyAppLimits()1270     public void testShortcutTargetWithApplyAppLimits() throws InterruptedException {
1271         // Set up resources
1272         sOverrides.resources = Mockito.spy(
1273                 InstrumentationRegistry.getInstrumentation().getContext().getResources());
1274         when(sOverrides.resources.getInteger(R.integer.config_maxShortcutTargetsPerApp))
1275                 .thenReturn(1);
1276         Intent sendIntent = createSendTextIntent();
1277         // We need app targets for direct targets to get displayed
1278         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1279         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1280                 Mockito.anyBoolean(),
1281                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1282         // Create direct share target
1283         List<ChooserTarget> serviceTargets = createDirectShareTargets(2,
1284                 resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
1285         ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
1286 
1287         // Start activity
1288         final ChooserWrapperActivity activity = mActivityRule
1289                 .launchActivity(Intent.createChooser(sendIntent, null));
1290 
1291         // Insert the direct share target
1292         Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1293         List<ShareShortcutInfo> shortcutInfos = createShortcuts(activity);
1294         directShareToShortcutInfos.put(serviceTargets.get(0),
1295                 shortcutInfos.get(0).getShortcutInfo());
1296         directShareToShortcutInfos.put(serviceTargets.get(1),
1297                 shortcutInfos.get(1).getShortcutInfo());
1298         InstrumentationRegistry.getInstrumentation().runOnMainSync(
1299                 () -> activity.getAdapter().addServiceResults(
1300                         activity.createTestDisplayResolveInfo(sendIntent,
1301                                 ri,
1302                                 "testLabel",
1303                                 "testInfo",
1304                                 sendIntent,
1305                                 /* resolveInfoPresentationGetter */ null),
1306                         serviceTargets,
1307                         TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE,
1308                         directShareToShortcutInfos,
1309                         List.of())
1310         );
1311         // Thread.sleep shouldn't be a thing in an integration test but it's
1312         // necessary here because of the way the code is structured
1313         // TODO: restructure the tests b/129870719
1314         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
1315 
1316         assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
1317                 activity.getAdapter().getCount(), is(3));
1318         assertThat("Chooser should have exactly one selectable direct target",
1319                 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
1320         assertThat("The resolver info must match the resolver info used to create the target",
1321                 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
1322         assertThat("The display label must match",
1323                 activity.getAdapter().getItem(0).getDisplayLabel(), is("testTitle0"));
1324     }
1325 
1326     @Test
testShortcutTargetWithoutApplyAppLimits()1327     public void testShortcutTargetWithoutApplyAppLimits() throws InterruptedException {
1328         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
1329                 SystemUiDeviceConfigFlags.APPLY_SHARING_APP_LIMITS_IN_SYSUI,
1330                 Boolean.toString(false),
1331                 true /* makeDefault*/);
1332         // Set up resources
1333         sOverrides.resources = Mockito.spy(
1334                 InstrumentationRegistry.getInstrumentation().getContext().getResources());
1335         when(sOverrides.resources.getInteger(R.integer.config_maxShortcutTargetsPerApp))
1336                 .thenReturn(1);
1337         Intent sendIntent = createSendTextIntent();
1338         // We need app targets for direct targets to get displayed
1339         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1340         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1341                 Mockito.anyBoolean(),
1342                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1343         // Create direct share target
1344         List<ChooserTarget> serviceTargets = createDirectShareTargets(2,
1345                 resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
1346         ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
1347 
1348         // Start activity
1349         final ChooserWrapperActivity activity = mActivityRule
1350                 .launchActivity(Intent.createChooser(sendIntent, null));
1351 
1352         // Insert the direct share target
1353         Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1354         List<ShareShortcutInfo> shortcutInfos = createShortcuts(activity);
1355         directShareToShortcutInfos.put(serviceTargets.get(0),
1356                 shortcutInfos.get(0).getShortcutInfo());
1357         directShareToShortcutInfos.put(serviceTargets.get(1),
1358                 shortcutInfos.get(1).getShortcutInfo());
1359         InstrumentationRegistry.getInstrumentation().runOnMainSync(
1360                 () -> activity.getAdapter().addServiceResults(
1361                         activity.createTestDisplayResolveInfo(sendIntent,
1362                                 ri,
1363                                 "testLabel",
1364                                 "testInfo",
1365                                 sendIntent,
1366                                 /* resolveInfoPresentationGetter */ null),
1367                         serviceTargets,
1368                         TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE,
1369                         directShareToShortcutInfos,
1370                         List.of())
1371         );
1372         // Thread.sleep shouldn't be a thing in an integration test but it's
1373         // necessary here because of the way the code is structured
1374         // TODO: restructure the tests b/129870719
1375         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
1376 
1377         assertThat("Chooser should have 4 targets (2 apps, 2 direct)",
1378                 activity.getAdapter().getCount(), is(4));
1379         assertThat("Chooser should have exactly two selectable direct target",
1380                 activity.getAdapter().getSelectableServiceTargetCount(), is(2));
1381         assertThat("The resolver info must match the resolver info used to create the target",
1382                 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
1383         assertThat("The display label must match",
1384                 activity.getAdapter().getItem(0).getDisplayLabel(), is("testTitle0"));
1385         assertThat("The display label must match",
1386                 activity.getAdapter().getItem(1).getDisplayLabel(), is("testTitle1"));
1387     }
1388 
1389     // This test is too long and too slow and should not be taken as an example for future tests.
1390     @Test
testDirectTargetLoggingWithAppTargetNotRankedPortrait()1391     public void testDirectTargetLoggingWithAppTargetNotRankedPortrait()
1392             throws InterruptedException {
1393         testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_PORTRAIT, 4);
1394     }
1395 
1396     @Test
testDirectTargetLoggingWithAppTargetNotRankedLandscape()1397     public void testDirectTargetLoggingWithAppTargetNotRankedLandscape()
1398             throws InterruptedException {
1399         testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_LANDSCAPE, 8);
1400     }
1401 
testDirectTargetLoggingWithAppTargetNotRanked( int orientation, int appTargetsExpected )1402     private void testDirectTargetLoggingWithAppTargetNotRanked(
1403             int orientation, int appTargetsExpected
1404     ) throws InterruptedException {
1405         Configuration configuration =
1406                 new Configuration(InstrumentationRegistry.getInstrumentation().getContext()
1407                         .getResources().getConfiguration());
1408         configuration.orientation = orientation;
1409 
1410         sOverrides.resources = Mockito.spy(
1411                 InstrumentationRegistry.getInstrumentation().getContext().getResources());
1412         when(sOverrides.resources.getConfiguration()).thenReturn(configuration);
1413 
1414         Intent sendIntent = createSendTextIntent();
1415         // We need app targets for direct targets to get displayed
1416         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(15);
1417         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1418                 Mockito.anyBoolean(),
1419                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1420 
1421         // Set up resources
1422         MetricsLogger mockLogger = sOverrides.metricsLogger;
1423         ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
1424         // Create direct share target
1425         List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
1426                 resolvedComponentInfos.get(14).getResolveInfoAt(0).activityInfo.packageName);
1427         ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0);
1428 
1429         // Start activity
1430         final ChooserWrapperActivity activity = mActivityRule
1431                 .launchActivity(Intent.createChooser(sendIntent, null));
1432         // Insert the direct share target
1433         Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1434         directShareToShortcutInfos.put(serviceTargets.get(0), null);
1435         InstrumentationRegistry.getInstrumentation().runOnMainSync(
1436                 () -> activity.getAdapter().addServiceResults(
1437                         activity.createTestDisplayResolveInfo(sendIntent,
1438                                 ri,
1439                                 "testLabel",
1440                                 "testInfo",
1441                                 sendIntent,
1442                                 /* resolveInfoPresentationGetter */ null),
1443                         serviceTargets,
1444                         TARGET_TYPE_CHOOSER_TARGET,
1445                         directShareToShortcutInfos,
1446                         List.of())
1447         );
1448         // Thread.sleep shouldn't be a thing in an integration test but it's
1449         // necessary here because of the way the code is structured
1450         // TODO: restructure the tests b/129870719
1451         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
1452 
1453         assertThat(
1454                 String.format("Chooser should have %d targets (%d apps, 1 direct, 15 A-Z)",
1455                         appTargetsExpected + 16, appTargetsExpected),
1456                 activity.getAdapter().getCount(), is(appTargetsExpected + 16));
1457         assertThat("Chooser should have exactly one selectable direct target",
1458                 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
1459         assertThat("The resolver info must match the resolver info used to create the target",
1460                 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
1461 
1462         // Click on the direct target
1463         String name = serviceTargets.get(0).getTitle().toString();
1464         onView(withText(name))
1465                 .perform(click());
1466         waitForIdle();
1467 
1468         // Currently we're seeing 3 invocations
1469         //      1. ChooserActivity.onCreate()
1470         //      2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
1471         //      3. ChooserActivity.startSelected -- which is the one we're after
1472         verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
1473         assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
1474                 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
1475         assertThat("The packages shouldn't match for app target and direct target", logMakerCaptor
1476                 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
1477     }
1478 
1479     @Test
testWorkTab_displayedWhenWorkProfileUserAvailable()1480     public void testWorkTab_displayedWhenWorkProfileUserAvailable() {
1481         // enable the work tab feature flag
1482         ResolverActivity.ENABLE_TABBED_VIEW = true;
1483         Intent sendIntent = createSendTextIntent();
1484         sendIntent.setType("TestType");
1485         markWorkProfileUserAvailable();
1486 
1487         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1488         waitForIdle();
1489 
1490         onView(withId(R.id.tabs)).check(matches(isDisplayed()));
1491     }
1492 
1493     @Test
testWorkTab_hiddenWhenWorkProfileUserNotAvailable()1494     public void testWorkTab_hiddenWhenWorkProfileUserNotAvailable() {
1495         // enable the work tab feature flag
1496         ResolverActivity.ENABLE_TABBED_VIEW = true;
1497         Intent sendIntent = createSendTextIntent();
1498         sendIntent.setType("TestType");
1499 
1500         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1501         waitForIdle();
1502 
1503         onView(withId(R.id.tabs)).check(matches(not(isDisplayed())));
1504     }
1505 
1506     @Test
testWorkTab_eachTabUsesExpectedAdapter()1507     public void testWorkTab_eachTabUsesExpectedAdapter() {
1508         // enable the work tab feature flag
1509         ResolverActivity.ENABLE_TABBED_VIEW = true;
1510         int personalProfileTargets = 3;
1511         int otherProfileTargets = 1;
1512         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1513                 createResolvedComponentsForTestWithOtherProfile(
1514                         personalProfileTargets + otherProfileTargets, /* userID */ 10);
1515         int workProfileTargets = 4;
1516         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(
1517                 workProfileTargets);
1518         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1519         Intent sendIntent = createSendTextIntent();
1520         sendIntent.setType("TestType");
1521         markWorkProfileUserAvailable();
1522 
1523         final ChooserWrapperActivity activity =
1524                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1525         waitForIdle();
1526 
1527         assertThat(activity.getCurrentUserHandle().getIdentifier(), is(0));
1528         onView(withText(R.string.resolver_work_tab)).perform(click());
1529         assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
1530         assertThat(activity.getPersonalListAdapter().getCount(), is(personalProfileTargets));
1531         assertThat(activity.getWorkListAdapter().getCount(), is(workProfileTargets));
1532     }
1533 
1534     @Test
testWorkTab_workProfileHasExpectedNumberOfTargets()1535     public void testWorkTab_workProfileHasExpectedNumberOfTargets() throws InterruptedException {
1536         // enable the work tab feature flag
1537         ResolverActivity.ENABLE_TABBED_VIEW = true;
1538         markWorkProfileUserAvailable();
1539         int workProfileTargets = 4;
1540         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1541                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
1542         List<ResolvedComponentInfo> workResolvedComponentInfos =
1543                 createResolvedComponentsForTest(workProfileTargets);
1544         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1545         Intent sendIntent = createSendTextIntent();
1546         sendIntent.setType("TestType");
1547 
1548         final ChooserWrapperActivity activity =
1549                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1550         waitForIdle();
1551         onView(withText(R.string.resolver_work_tab)).perform(click());
1552         waitForIdle();
1553 
1554         assertThat(activity.getWorkListAdapter().getCount(), is(workProfileTargets));
1555     }
1556 
1557     @Test
testWorkTab_selectingWorkTabAppOpensAppInWorkProfile()1558     public void testWorkTab_selectingWorkTabAppOpensAppInWorkProfile() throws InterruptedException {
1559         // enable the work tab feature flag
1560         ResolverActivity.ENABLE_TABBED_VIEW = true;
1561         markWorkProfileUserAvailable();
1562         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1563                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
1564         int workProfileTargets = 4;
1565         List<ResolvedComponentInfo> workResolvedComponentInfos =
1566                 createResolvedComponentsForTest(workProfileTargets);
1567         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1568         Intent sendIntent = createSendTextIntent();
1569         sendIntent.setType("TestType");
1570         ResolveInfo[] chosen = new ResolveInfo[1];
1571         sOverrides.onSafelyStartCallback = targetInfo -> {
1572             chosen[0] = targetInfo.getResolveInfo();
1573             return true;
1574         };
1575 
1576         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1577         waitForIdle();
1578         onView(withText(R.string.resolver_work_tab)).perform(click());
1579         waitForIdle();
1580         // wait for the share sheet to expand
1581         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
1582 
1583         onView(first(allOf(
1584                 withText(workResolvedComponentInfos.get(0)
1585                         .getResolveInfoAt(0).activityInfo.applicationInfo.name),
1586                 isDisplayed())))
1587                 .perform(click());
1588         waitForIdle();
1589         assertThat(chosen[0], is(workResolvedComponentInfos.get(0).getResolveInfoAt(0)));
1590     }
1591 
1592     @Test
testWorkTab_crossProfileIntentsDisabled_personalToWork_emptyStateShown()1593     public void testWorkTab_crossProfileIntentsDisabled_personalToWork_emptyStateShown() {
1594         // enable the work tab feature flag
1595         ResolverActivity.ENABLE_TABBED_VIEW = true;
1596         markWorkProfileUserAvailable();
1597         int workProfileTargets = 4;
1598         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1599                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
1600         List<ResolvedComponentInfo> workResolvedComponentInfos =
1601                 createResolvedComponentsForTest(workProfileTargets);
1602         sOverrides.hasCrossProfileIntents = false;
1603         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1604         Intent sendIntent = createSendTextIntent();
1605         sendIntent.setType("TestType");
1606 
1607         final ChooserWrapperActivity activity =
1608                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1609         waitForIdle();
1610         onView(withText(R.string.resolver_work_tab)).perform(click());
1611         waitForIdle();
1612         onView(withId(R.id.contentPanel))
1613                 .perform(swipeUp());
1614 
1615         onView(withText(R.string.resolver_cross_profile_blocked))
1616                 .check(matches(isDisplayed()));
1617     }
1618 
1619     @Test
testWorkTab_workProfileDisabled_emptyStateShown()1620     public void testWorkTab_workProfileDisabled_emptyStateShown() {
1621         // enable the work tab feature flag
1622         markWorkProfileUserAvailable();
1623         int workProfileTargets = 4;
1624         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1625                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
1626         List<ResolvedComponentInfo> workResolvedComponentInfos =
1627                 createResolvedComponentsForTest(workProfileTargets);
1628         sOverrides.isQuietModeEnabled = true;
1629         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1630         Intent sendIntent = createSendTextIntent();
1631         sendIntent.setType("TestType");
1632 
1633         ResolverActivity.ENABLE_TABBED_VIEW = true;
1634         final ChooserWrapperActivity activity =
1635                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1636         waitForIdle();
1637         onView(withId(R.id.contentPanel))
1638                 .perform(swipeUp());
1639         onView(withText(R.string.resolver_work_tab)).perform(click());
1640         waitForIdle();
1641 
1642         onView(withText(R.string.resolver_turn_on_work_apps))
1643                 .check(matches(isDisplayed()));
1644     }
1645 
1646     @Test
testWorkTab_noWorkAppsAvailable_emptyStateShown()1647     public void testWorkTab_noWorkAppsAvailable_emptyStateShown() {
1648         // enable the work tab feature flag
1649         ResolverActivity.ENABLE_TABBED_VIEW = true;
1650         markWorkProfileUserAvailable();
1651         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1652                 createResolvedComponentsForTest(3);
1653         List<ResolvedComponentInfo> workResolvedComponentInfos =
1654                 createResolvedComponentsForTest(0);
1655         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1656         Intent sendIntent = createSendTextIntent();
1657         sendIntent.setType("TestType");
1658 
1659         final ChooserWrapperActivity activity =
1660                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1661         waitForIdle();
1662         onView(withId(R.id.contentPanel))
1663                 .perform(swipeUp());
1664         onView(withText(R.string.resolver_work_tab)).perform(click());
1665         waitForIdle();
1666 
1667         onView(withText(R.string.resolver_no_work_apps_available))
1668                 .check(matches(isDisplayed()));
1669     }
1670 
1671     @Test
testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown()1672     public void testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown() {
1673         // enable the work tab feature flag
1674         ResolverActivity.ENABLE_TABBED_VIEW = true;
1675         markWorkProfileUserAvailable();
1676         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1677                 createResolvedComponentsForTest(3);
1678         List<ResolvedComponentInfo> workResolvedComponentInfos =
1679                 createResolvedComponentsForTest(0);
1680         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1681         sOverrides.isQuietModeEnabled = true;
1682         sOverrides.hasCrossProfileIntents = false;
1683         Intent sendIntent = createSendTextIntent();
1684         sendIntent.setType("TestType");
1685 
1686         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1687         waitForIdle();
1688         onView(withId(R.id.contentPanel))
1689                 .perform(swipeUp());
1690         onView(withText(R.string.resolver_work_tab)).perform(click());
1691         waitForIdle();
1692 
1693         onView(withText(R.string.resolver_cross_profile_blocked))
1694                 .check(matches(isDisplayed()));
1695     }
1696 
1697     @Test
testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown()1698     public void testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown() {
1699         // enable the work tab feature flag
1700         ResolverActivity.ENABLE_TABBED_VIEW = true;
1701         markWorkProfileUserAvailable();
1702         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1703                 createResolvedComponentsForTest(3);
1704         List<ResolvedComponentInfo> workResolvedComponentInfos =
1705                 createResolvedComponentsForTest(0);
1706         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1707         sOverrides.isQuietModeEnabled = true;
1708         Intent sendIntent = createSendTextIntent();
1709         sendIntent.setType("TestType");
1710 
1711         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1712         waitForIdle();
1713         onView(withId(R.id.contentPanel))
1714                 .perform(swipeUp());
1715         onView(withText(R.string.resolver_work_tab)).perform(click());
1716         waitForIdle();
1717 
1718         onView(withText(R.string.resolver_no_work_apps_available))
1719                 .check(matches(isDisplayed()));
1720     }
1721 
1722     @Test
testAppTargetLogging()1723     public void testAppTargetLogging() throws InterruptedException {
1724         Intent sendIntent = createSendTextIntent();
1725         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1726 
1727         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1728                 Mockito.anyBoolean(),
1729                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1730 
1731         final ChooserWrapperActivity activity = mActivityRule
1732                 .launchActivity(Intent.createChooser(sendIntent, null));
1733         waitForIdle();
1734 
1735         assertThat(activity.getAdapter().getCount(), is(2));
1736         onView(withId(R.id.profile_button)).check(doesNotExist());
1737 
1738         ResolveInfo[] chosen = new ResolveInfo[1];
1739         sOverrides.onSafelyStartCallback = targetInfo -> {
1740             chosen[0] = targetInfo.getResolveInfo();
1741             return true;
1742         };
1743 
1744         ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
1745         onView(withText(toChoose.activityInfo.name))
1746                 .perform(click());
1747         waitForIdle();
1748 
1749         ChooserActivityLoggerFake logger =
1750                 (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
1751         assertThat(logger.numCalls(), is(6));
1752         // first one should be SHARESHEET_TRIGGERED uievent
1753         assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1754         assertThat(logger.get(0).event.getId(),
1755                 is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
1756         // second one should be SHARESHEET_STARTED event
1757         assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
1758         assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
1759         assertThat(logger.get(1).mimeType, is("text/plain"));
1760         assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
1761         assertThat(logger.get(1).appProvidedApp, is(0));
1762         assertThat(logger.get(1).appProvidedDirect, is(0));
1763         assertThat(logger.get(1).isWorkprofile, is(false));
1764         assertThat(logger.get(1).previewType, is(3));
1765         // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
1766         assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1767         assertThat(logger.get(2).event.getId(),
1768                 is(ChooserActivityLogger
1769                         .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
1770         // fourth and fifth are just artifacts of test set-up
1771         // sixth one should be ranking atom with SHARESHEET_APP_TARGET_SELECTED event
1772         assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
1773         assertThat(logger.get(5).targetType,
1774                 is(ChooserActivityLogger
1775                         .SharesheetTargetSelectedEvent.SHARESHEET_APP_TARGET_SELECTED.getId()));
1776     }
1777 
1778     @Test
testDirectTargetLogging()1779     public void testDirectTargetLogging() throws InterruptedException {
1780         Intent sendIntent = createSendTextIntent();
1781         // We need app targets for direct targets to get displayed
1782         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1783         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1784                 Mockito.anyBoolean(),
1785                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1786 
1787         // Create direct share target
1788         List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
1789                 resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
1790         ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
1791 
1792         // Start activity
1793         final ChooserWrapperActivity activity = mActivityRule
1794                 .launchActivity(Intent.createChooser(sendIntent, null));
1795 
1796         // Insert the direct share target
1797         Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
1798         directShareToShortcutInfos.put(serviceTargets.get(0), null);
1799         InstrumentationRegistry.getInstrumentation().runOnMainSync(
1800                 () -> activity.getAdapter().addServiceResults(
1801                         activity.createTestDisplayResolveInfo(sendIntent,
1802                                 ri,
1803                                 "testLabel",
1804                                 "testInfo",
1805                                 sendIntent,
1806                                 /* resolveInfoPresentationGetter */ null),
1807                         serviceTargets,
1808                         TARGET_TYPE_CHOOSER_TARGET,
1809                         directShareToShortcutInfos,
1810                         null)
1811         );
1812         // Thread.sleep shouldn't be a thing in an integration test but it's
1813         // necessary here because of the way the code is structured
1814         // TODO: restructure the tests b/129870719
1815         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
1816 
1817         assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
1818                 activity.getAdapter().getCount(), is(3));
1819         assertThat("Chooser should have exactly one selectable direct target",
1820                 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
1821         assertThat("The resolver info must match the resolver info used to create the target",
1822                 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
1823 
1824         // Click on the direct target
1825         String name = serviceTargets.get(0).getTitle().toString();
1826         onView(withText(name))
1827                 .perform(click());
1828         waitForIdle();
1829 
1830         ChooserActivityLoggerFake logger =
1831                 (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
1832         assertThat(logger.numCalls(), is(6));
1833         // first one should be SHARESHEET_TRIGGERED uievent
1834         assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1835         assertThat(logger.get(0).event.getId(),
1836                 is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
1837         // second one should be SHARESHEET_STARTED event
1838         assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
1839         assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
1840         assertThat(logger.get(1).mimeType, is("text/plain"));
1841         assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
1842         assertThat(logger.get(1).appProvidedApp, is(0));
1843         assertThat(logger.get(1).appProvidedDirect, is(0));
1844         assertThat(logger.get(1).isWorkprofile, is(false));
1845         assertThat(logger.get(1).previewType, is(3));
1846         // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
1847         assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1848         assertThat(logger.get(2).event.getId(),
1849                 is(ChooserActivityLogger
1850                         .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
1851         // fourth and fifth are just artifacts of test set-up
1852         // sixth one should be ranking atom with SHARESHEET_COPY_TARGET_SELECTED event
1853         assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
1854         assertThat(logger.get(5).targetType,
1855                 is(ChooserActivityLogger
1856                         .SharesheetTargetSelectedEvent.SHARESHEET_SERVICE_TARGET_SELECTED.getId()));
1857     }
1858 
1859     @Test
testEmptyDirectRowLogging()1860     public void testEmptyDirectRowLogging() throws InterruptedException {
1861         Intent sendIntent = createSendTextIntent();
1862         // We need app targets for direct targets to get displayed
1863         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1864         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1865                 Mockito.anyBoolean(),
1866                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1867 
1868         // Start activity
1869         final ChooserWrapperActivity activity = mActivityRule
1870                 .launchActivity(Intent.createChooser(sendIntent, null));
1871 
1872         // Thread.sleep shouldn't be a thing in an integration test but it's
1873         // necessary here because of the way the code is structured
1874         Thread.sleep(3000);
1875 
1876         assertThat("Chooser should have 2 app targets",
1877                 activity.getAdapter().getCount(), is(2));
1878         assertThat("Chooser should have no direct targets",
1879                 activity.getAdapter().getSelectableServiceTargetCount(), is(0));
1880 
1881         ChooserActivityLoggerFake logger =
1882                 (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
1883         assertThat(logger.numCalls(), is(6));
1884         // first one should be SHARESHEET_TRIGGERED uievent
1885         assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1886         assertThat(logger.get(0).event.getId(),
1887                 is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
1888         // second one should be SHARESHEET_STARTED event
1889         assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
1890         assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
1891         assertThat(logger.get(1).mimeType, is("text/plain"));
1892         assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
1893         assertThat(logger.get(1).appProvidedApp, is(0));
1894         assertThat(logger.get(1).appProvidedDirect, is(0));
1895         assertThat(logger.get(1).isWorkprofile, is(false));
1896         assertThat(logger.get(1).previewType, is(3));
1897         // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
1898         assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1899         assertThat(logger.get(2).event.getId(),
1900                 is(ChooserActivityLogger
1901                         .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
1902         // fourth and fifth are just artifacts of test set-up
1903         // sixth one should be ranking atom with SHARESHEET_EMPTY_DIRECT_SHARE_ROW event
1904         assertThat(logger.get(5).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1905         assertThat(logger.get(5).event.getId(),
1906                 is(ChooserActivityLogger
1907                         .SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW.getId()));
1908     }
1909 
1910     @Test
testCopyTextToClipboardLogging()1911     public void testCopyTextToClipboardLogging() throws Exception {
1912         Intent sendIntent = createSendTextIntent();
1913         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
1914 
1915         when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
1916                 Mockito.anyBoolean(),
1917                 Mockito.anyBoolean(),
1918                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1919 
1920         final ChooserWrapperActivity activity = mActivityRule
1921                 .launchActivity(Intent.createChooser(sendIntent, null));
1922         waitForIdle();
1923 
1924         onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed()));
1925         onView(withId(R.id.chooser_copy_button)).perform(click());
1926 
1927         ChooserActivityLoggerFake logger =
1928                 (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
1929         assertThat(logger.numCalls(), is(6));
1930         // first one should be SHARESHEET_TRIGGERED uievent
1931         assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1932         assertThat(logger.get(0).event.getId(),
1933                 is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
1934         // second one should be SHARESHEET_STARTED event
1935         assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
1936         assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
1937         assertThat(logger.get(1).mimeType, is("text/plain"));
1938         assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
1939         assertThat(logger.get(1).appProvidedApp, is(0));
1940         assertThat(logger.get(1).appProvidedDirect, is(0));
1941         assertThat(logger.get(1).isWorkprofile, is(false));
1942         assertThat(logger.get(1).previewType, is(3));
1943         // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
1944         assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1945         assertThat(logger.get(2).event.getId(),
1946                 is(ChooserActivityLogger
1947                         .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
1948         // fourth and fifth are just artifacts of test set-up
1949         // sixth one should be ranking atom with SHARESHEET_COPY_TARGET_SELECTED event
1950         assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
1951         assertThat(logger.get(5).targetType,
1952                 is(ChooserActivityLogger
1953                         .SharesheetTargetSelectedEvent.SHARESHEET_COPY_TARGET_SELECTED.getId()));
1954     }
1955 
1956     @Test
testSwitchProfileLogging()1957     public void testSwitchProfileLogging() throws InterruptedException {
1958         // enable the work tab feature flag
1959         ResolverActivity.ENABLE_TABBED_VIEW = true;
1960         markWorkProfileUserAvailable();
1961         int workProfileTargets = 4;
1962         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1963                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
1964         List<ResolvedComponentInfo> workResolvedComponentInfos =
1965                 createResolvedComponentsForTest(workProfileTargets);
1966         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1967         Intent sendIntent = createSendTextIntent();
1968         sendIntent.setType("TestType");
1969 
1970         final ChooserWrapperActivity activity =
1971                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
1972         waitForIdle();
1973         onView(withText(R.string.resolver_work_tab)).perform(click());
1974         waitForIdle();
1975         onView(withText(R.string.resolver_personal_tab)).perform(click());
1976         waitForIdle();
1977 
1978         ChooserActivityLoggerFake logger =
1979                 (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
1980         assertThat(logger.numCalls(), is(8));
1981         // first one should be SHARESHEET_TRIGGERED uievent
1982         assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1983         assertThat(logger.get(0).event.getId(),
1984                 is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
1985         // second one should be SHARESHEET_STARTED event
1986         assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
1987         assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
1988         assertThat(logger.get(1).mimeType, is("TestType"));
1989         assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
1990         assertThat(logger.get(1).appProvidedApp, is(0));
1991         assertThat(logger.get(1).appProvidedDirect, is(0));
1992         assertThat(logger.get(1).isWorkprofile, is(false));
1993         assertThat(logger.get(1).previewType, is(3));
1994         // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
1995         assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
1996         assertThat(logger.get(2).event.getId(),
1997                 is(ChooserActivityLogger
1998                         .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
1999         // fourth one is artifact of test setup
2000         // fifth one is switch to work profile
2001         assertThat(logger.get(4).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
2002         assertThat(logger.get(4).event.getId(),
2003                 is(ChooserActivityLogger
2004                         .SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED.getId()));
2005         // sixth one should be SHARESHEET_APP_LOAD_COMPLETE uievent
2006         assertThat(logger.get(5).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
2007         assertThat(logger.get(5).event.getId(),
2008                 is(ChooserActivityLogger
2009                         .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
2010         // seventh one is artifact of test setup
2011         // eigth one is switch to work profile
2012         assertThat(logger.get(7).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
2013         assertThat(logger.get(7).event.getId(),
2014                 is(ChooserActivityLogger
2015                         .SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED.getId()));
2016     }
2017 
2018     @Test
testAutolaunch_singleTarget_wifthWorkProfileAndTabbedViewOff_noAutolaunch()2019     public void testAutolaunch_singleTarget_wifthWorkProfileAndTabbedViewOff_noAutolaunch() {
2020         ResolverActivity.ENABLE_TABBED_VIEW = false;
2021         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2022                 createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
2023         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
2024                 Mockito.anyBoolean(),
2025                 Mockito.isA(List.class)))
2026                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2027         Intent sendIntent = createSendTextIntent();
2028         sendIntent.setType("TestType");
2029         ResolveInfo[] chosen = new ResolveInfo[1];
2030         sOverrides.onSafelyStartCallback = targetInfo -> {
2031             chosen[0] = targetInfo.getResolveInfo();
2032             return true;
2033         };
2034         waitForIdle();
2035 
2036         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2037         waitForIdle();
2038 
2039         assertTrue(chosen[0] == null);
2040     }
2041 
2042     @Test
testAutolaunch_singleTarget_noWorkProfile_autolaunch()2043     public void testAutolaunch_singleTarget_noWorkProfile_autolaunch() {
2044         ResolverActivity.ENABLE_TABBED_VIEW = false;
2045         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2046                 createResolvedComponentsForTest(1);
2047         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
2048                 Mockito.anyBoolean(),
2049                 Mockito.isA(List.class)))
2050                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2051         Intent sendIntent = createSendTextIntent();
2052         sendIntent.setType("TestType");
2053         ResolveInfo[] chosen = new ResolveInfo[1];
2054         sOverrides.onSafelyStartCallback = targetInfo -> {
2055             chosen[0] = targetInfo.getResolveInfo();
2056             return true;
2057         };
2058         waitForIdle();
2059 
2060         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2061         waitForIdle();
2062 
2063         assertThat(chosen[0], is(personalResolvedComponentInfos.get(0).getResolveInfoAt(0)));
2064     }
2065 
2066     @Test
testWorkTab_onePersonalTarget_emptyStateOnWorkTarget_autolaunch()2067     public void testWorkTab_onePersonalTarget_emptyStateOnWorkTarget_autolaunch() {
2068         // enable the work tab feature flag
2069         ResolverActivity.ENABLE_TABBED_VIEW = true;
2070         markWorkProfileUserAvailable();
2071         int workProfileTargets = 4;
2072         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2073                 createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
2074         List<ResolvedComponentInfo> workResolvedComponentInfos =
2075                 createResolvedComponentsForTest(workProfileTargets);
2076         sOverrides.hasCrossProfileIntents = false;
2077         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2078         Intent sendIntent = createSendTextIntent();
2079         ResolveInfo[] chosen = new ResolveInfo[1];
2080         sOverrides.onSafelyStartCallback = targetInfo -> {
2081             chosen[0] = targetInfo.getResolveInfo();
2082             return true;
2083         };
2084 
2085         mActivityRule.launchActivity(sendIntent);
2086         waitForIdle();
2087 
2088         assertThat(chosen[0], is(personalResolvedComponentInfos.get(1).getResolveInfoAt(0)));
2089     }
2090 
2091     @Test
testOneInitialIntent_noAutolaunch()2092     public void testOneInitialIntent_noAutolaunch() {
2093         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2094                 createResolvedComponentsForTest(1);
2095         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
2096                 Mockito.anyBoolean(),
2097                 Mockito.isA(List.class)))
2098                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2099         Intent chooserIntent = createChooserIntent(createSendTextIntent(),
2100                 new Intent[] {new Intent("action.fake")});
2101         ResolveInfo[] chosen = new ResolveInfo[1];
2102         sOverrides.onSafelyStartCallback = targetInfo -> {
2103             chosen[0] = targetInfo.getResolveInfo();
2104             return true;
2105         };
2106         sOverrides.packageManager = mock(PackageManager.class);
2107         ResolveInfo ri = createFakeResolveInfo();
2108         when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(ri);
2109         waitForIdle();
2110 
2111         ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent);
2112         waitForIdle();
2113 
2114         assertNull(chosen[0]);
2115         assertThat(activity.getPersonalListAdapter().getCallerTargetCount(), is(1));
2116     }
2117 
2118     @Test
testWorkTab_withInitialIntents_workTabDoesNotIncludePersonalInitialIntents()2119     public void testWorkTab_withInitialIntents_workTabDoesNotIncludePersonalInitialIntents() {
2120         // enable the work tab feature flag
2121         ResolverActivity.ENABLE_TABBED_VIEW = true;
2122         markWorkProfileUserAvailable();
2123         int workProfileTargets = 1;
2124         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2125                 createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
2126         List<ResolvedComponentInfo> workResolvedComponentInfos =
2127                 createResolvedComponentsForTest(workProfileTargets);
2128         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2129         Intent[] initialIntents = {
2130                 new Intent("action.fake1"),
2131                 new Intent("action.fake2")
2132         };
2133         Intent chooserIntent = createChooserIntent(createSendTextIntent(), initialIntents);
2134         sOverrides.packageManager = mock(PackageManager.class);
2135         when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt()))
2136                 .thenReturn(createFakeResolveInfo());
2137         waitForIdle();
2138 
2139         ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent);
2140         waitForIdle();
2141 
2142         assertThat(activity.getPersonalListAdapter().getCallerTargetCount(), is(2));
2143         assertThat(activity.getWorkListAdapter().getCallerTargetCount(), is(0));
2144     }
2145 
2146     @Test
testWorkTab_xProfileIntentsDisabled_personalToWork_nonSendIntent_emptyStateShown()2147     public void testWorkTab_xProfileIntentsDisabled_personalToWork_nonSendIntent_emptyStateShown() {
2148         // enable the work tab feature flag
2149         ResolverActivity.ENABLE_TABBED_VIEW = true;
2150         markWorkProfileUserAvailable();
2151         int workProfileTargets = 4;
2152         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2153                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2154         List<ResolvedComponentInfo> workResolvedComponentInfos =
2155                 createResolvedComponentsForTest(workProfileTargets);
2156         sOverrides.hasCrossProfileIntents = false;
2157         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2158         Intent[] initialIntents = {
2159                 new Intent("action.fake1"),
2160                 new Intent("action.fake2")
2161         };
2162         Intent chooserIntent = createChooserIntent(new Intent(), initialIntents);
2163         sOverrides.packageManager = mock(PackageManager.class);
2164         when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt()))
2165                 .thenReturn(createFakeResolveInfo());
2166 
2167         final ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent);
2168         waitForIdle();
2169         onView(withText(R.string.resolver_work_tab)).perform(click());
2170         waitForIdle();
2171         onView(withId(R.id.contentPanel))
2172                 .perform(swipeUp());
2173 
2174         onView(withText(R.string.resolver_cross_profile_blocked))
2175                 .check(matches(isDisplayed()));
2176     }
2177 
2178     @Test
testWorkTab_noWorkAppsAvailable_nonSendIntent_emptyStateShown()2179     public void testWorkTab_noWorkAppsAvailable_nonSendIntent_emptyStateShown() {
2180         // enable the work tab feature flag
2181         ResolverActivity.ENABLE_TABBED_VIEW = true;
2182         markWorkProfileUserAvailable();
2183         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2184                 createResolvedComponentsForTest(3);
2185         List<ResolvedComponentInfo> workResolvedComponentInfos =
2186                 createResolvedComponentsForTest(0);
2187         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2188         Intent[] initialIntents = {
2189                 new Intent("action.fake1"),
2190                 new Intent("action.fake2")
2191         };
2192         Intent chooserIntent = createChooserIntent(new Intent(), initialIntents);
2193         sOverrides.packageManager = mock(PackageManager.class);
2194         when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt()))
2195                 .thenReturn(createFakeResolveInfo());
2196 
2197         mActivityRule.launchActivity(chooserIntent);
2198         waitForIdle();
2199         onView(withId(R.id.contentPanel))
2200                 .perform(swipeUp());
2201         onView(withText(R.string.resolver_work_tab)).perform(click());
2202         waitForIdle();
2203 
2204         onView(withText(R.string.resolver_no_work_apps_available))
2205                 .check(matches(isDisplayed()));
2206     }
2207 
2208     @Test
testDeduplicateCallerTargetRankedTarget()2209     public void testDeduplicateCallerTargetRankedTarget() {
2210         // Create 4 ranked app targets.
2211         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2212                 createResolvedComponentsForTest(4);
2213         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
2214                 Mockito.anyBoolean(),
2215                 Mockito.isA(List.class)))
2216                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2217         // Create caller target which is duplicate with one of app targets
2218         Intent chooserIntent = createChooserIntent(createSendTextIntent(),
2219                 new Intent[] {new Intent("action.fake")});
2220         sOverrides.packageManager = mock(PackageManager.class);
2221         ResolveInfo ri = ResolverDataProvider.createResolveInfo(0,
2222                 UserHandle.USER_CURRENT);
2223         when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(ri);
2224         waitForIdle();
2225 
2226         ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent);
2227         waitForIdle();
2228 
2229         // Total 4 targets (1 caller target, 3 ranked targets)
2230         assertThat(activity.getAdapter().getCount(), is(4));
2231         assertThat(activity.getAdapter().getCallerTargetCount(), is(1));
2232         assertThat(activity.getAdapter().getRankedTargetCount(), is(3));
2233     }
2234 
2235     @Test
testWorkTab_selectingWorkTabWithPausedWorkProfile_directShareTargetsNotQueried()2236     public void testWorkTab_selectingWorkTabWithPausedWorkProfile_directShareTargetsNotQueried() {
2237         // enable the work tab feature flag
2238         ResolverActivity.ENABLE_TABBED_VIEW = true;
2239         markWorkProfileUserAvailable();
2240         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2241                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2242         List<ResolvedComponentInfo> workResolvedComponentInfos =
2243                 createResolvedComponentsForTest(3);
2244         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2245         sOverrides.isQuietModeEnabled = true;
2246         boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false };
2247         sOverrides.onQueryDirectShareTargets = chooserListAdapter -> {
2248             isQueryDirectShareCalledOnWorkProfile[0] =
2249                     (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2250             return null;
2251         };
2252         boolean[] isQueryTargetServicesCalledOnWorkProfile = new boolean[] { false };
2253         sOverrides.onQueryTargetServices = chooserListAdapter -> {
2254             isQueryTargetServicesCalledOnWorkProfile[0] =
2255                     (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2256             return null;
2257         };
2258         Intent sendIntent = createSendTextIntent();
2259         sendIntent.setType("TestType");
2260 
2261         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2262         waitForIdle();
2263         onView(withId(R.id.contentPanel))
2264                 .perform(swipeUp());
2265         onView(withText(R.string.resolver_work_tab)).perform(click());
2266         waitForIdle();
2267 
2268         assertFalse("Direct share targets were queried on a paused work profile",
2269                 isQueryDirectShareCalledOnWorkProfile[0]);
2270         assertFalse("Target services were queried on a paused work profile",
2271                 isQueryTargetServicesCalledOnWorkProfile[0]);
2272     }
2273 
2274     @Test
testWorkTab_selectingWorkTabWithNotRunningWorkUser_directShareTargetsNotQueried()2275     public void testWorkTab_selectingWorkTabWithNotRunningWorkUser_directShareTargetsNotQueried() {
2276         // enable the work tab feature flag
2277         ResolverActivity.ENABLE_TABBED_VIEW = true;
2278         markWorkProfileUserAvailable();
2279         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2280                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2281         List<ResolvedComponentInfo> workResolvedComponentInfos =
2282                 createResolvedComponentsForTest(3);
2283         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2284         sOverrides.isWorkProfileUserRunning = false;
2285         boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false };
2286         sOverrides.onQueryDirectShareTargets = chooserListAdapter -> {
2287             isQueryDirectShareCalledOnWorkProfile[0] =
2288                     (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2289             return null;
2290         };
2291         boolean[] isQueryTargetServicesCalledOnWorkProfile = new boolean[] { false };
2292         sOverrides.onQueryTargetServices = chooserListAdapter -> {
2293             isQueryTargetServicesCalledOnWorkProfile[0] =
2294                     (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2295             return null;
2296         };
2297         Intent sendIntent = createSendTextIntent();
2298         sendIntent.setType("TestType");
2299 
2300         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2301         waitForIdle();
2302         onView(withId(R.id.contentPanel))
2303                 .perform(swipeUp());
2304         onView(withText(R.string.resolver_work_tab)).perform(click());
2305         waitForIdle();
2306 
2307         assertFalse("Direct share targets were queried on a locked work profile user",
2308                 isQueryDirectShareCalledOnWorkProfile[0]);
2309         assertFalse("Target services were queried on a locked work profile user",
2310                 isQueryTargetServicesCalledOnWorkProfile[0]);
2311     }
2312 
2313     @Test
testWorkTab_workUserNotRunning_workTargetsShown()2314     public void testWorkTab_workUserNotRunning_workTargetsShown() {
2315         // enable the work tab feature flag
2316         ResolverActivity.ENABLE_TABBED_VIEW = true;
2317         markWorkProfileUserAvailable();
2318         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2319                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2320         List<ResolvedComponentInfo> workResolvedComponentInfos =
2321                 createResolvedComponentsForTest(3);
2322         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2323         Intent sendIntent = createSendTextIntent();
2324         sendIntent.setType("TestType");
2325         sOverrides.isWorkProfileUserRunning = false;
2326 
2327         final ChooserWrapperActivity activity =
2328                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2329         waitForIdle();
2330         onView(withId(R.id.contentPanel))
2331                 .perform(swipeUp());
2332         onView(withText(R.string.resolver_work_tab)).perform(click());
2333         waitForIdle();
2334 
2335         assertEquals(3, activity.getWorkListAdapter().getCount());
2336     }
2337 
2338     @Test
testWorkTab_selectingWorkTabWithLockedWorkUser_directShareTargetsNotQueried()2339     public void testWorkTab_selectingWorkTabWithLockedWorkUser_directShareTargetsNotQueried() {
2340         // enable the work tab feature flag
2341         ResolverActivity.ENABLE_TABBED_VIEW = true;
2342         markWorkProfileUserAvailable();
2343         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2344                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2345         List<ResolvedComponentInfo> workResolvedComponentInfos =
2346                 createResolvedComponentsForTest(3);
2347         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2348         sOverrides.isWorkProfileUserUnlocked = false;
2349         boolean[] isQueryDirectShareCalledOnWorkProfile = new boolean[] { false };
2350         sOverrides.onQueryDirectShareTargets = chooserListAdapter -> {
2351             isQueryDirectShareCalledOnWorkProfile[0] =
2352                     (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2353             return null;
2354         };
2355         boolean[] isQueryTargetServicesCalledOnWorkProfile = new boolean[] { false };
2356         sOverrides.onQueryTargetServices = chooserListAdapter -> {
2357             isQueryTargetServicesCalledOnWorkProfile[0] =
2358                     (chooserListAdapter.getUserHandle().getIdentifier() == 10);
2359             return null;
2360         };
2361         Intent sendIntent = createSendTextIntent();
2362         sendIntent.setType("TestType");
2363 
2364         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2365         waitForIdle();
2366         onView(withId(R.id.contentPanel))
2367                 .perform(swipeUp());
2368         onView(withText(R.string.resolver_work_tab)).perform(click());
2369         waitForIdle();
2370 
2371         assertFalse("Direct share targets were queried on a locked work profile user",
2372                 isQueryDirectShareCalledOnWorkProfile[0]);
2373         assertFalse("Target services were queried on a locked work profile user",
2374                 isQueryTargetServicesCalledOnWorkProfile[0]);
2375     }
2376 
2377     @Test
testWorkTab_workUserLocked_workTargetsShown()2378     public void testWorkTab_workUserLocked_workTargetsShown() {
2379         // enable the work tab feature flag
2380         ResolverActivity.ENABLE_TABBED_VIEW = true;
2381         markWorkProfileUserAvailable();
2382         List<ResolvedComponentInfo> personalResolvedComponentInfos =
2383                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
2384         List<ResolvedComponentInfo> workResolvedComponentInfos =
2385                 createResolvedComponentsForTest(3);
2386         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
2387         Intent sendIntent = createSendTextIntent();
2388         sendIntent.setType("TestType");
2389         sOverrides.isWorkProfileUserUnlocked = false;
2390 
2391         final ChooserWrapperActivity activity =
2392                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
2393         waitForIdle();
2394         onView(withId(R.id.contentPanel))
2395                 .perform(swipeUp());
2396         onView(withText(R.string.resolver_work_tab)).perform(click());
2397         waitForIdle();
2398 
2399         assertEquals(3, activity.getWorkListAdapter().getCount());
2400     }
2401 
createChooserIntent(Intent intent, Intent[] initialIntents)2402     private Intent createChooserIntent(Intent intent, Intent[] initialIntents) {
2403         Intent chooserIntent = new Intent();
2404         chooserIntent.setAction(Intent.ACTION_CHOOSER);
2405         chooserIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
2406         chooserIntent.putExtra(Intent.EXTRA_TITLE, "some title");
2407         chooserIntent.putExtra(Intent.EXTRA_INTENT, intent);
2408         chooserIntent.setType("text/plain");
2409         if (initialIntents != null) {
2410             chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, initialIntents);
2411         }
2412         return chooserIntent;
2413     }
2414 
createFakeResolveInfo()2415     private ResolveInfo createFakeResolveInfo() {
2416         ResolveInfo ri = new ResolveInfo();
2417         ri.activityInfo = new ActivityInfo();
2418         ri.activityInfo.name = "FakeActivityName";
2419         ri.activityInfo.packageName = "fake.package.name";
2420         ri.activityInfo.applicationInfo = new ApplicationInfo();
2421         ri.activityInfo.applicationInfo.packageName = "fake.package.name";
2422         return ri;
2423     }
2424 
createSendTextIntent()2425     private Intent createSendTextIntent() {
2426         Intent sendIntent = new Intent();
2427         sendIntent.setAction(Intent.ACTION_SEND);
2428         sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
2429         sendIntent.setType("text/plain");
2430         return sendIntent;
2431     }
2432 
createSendImageIntent(Uri imageThumbnail)2433     private Intent createSendImageIntent(Uri imageThumbnail) {
2434         Intent sendIntent = new Intent();
2435         sendIntent.setAction(Intent.ACTION_SEND);
2436         sendIntent.putExtra(Intent.EXTRA_STREAM, imageThumbnail);
2437         sendIntent.setType("image/png");
2438         if (imageThumbnail != null) {
2439             ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
2440             sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
2441         }
2442 
2443         return sendIntent;
2444     }
2445 
createSendTextIntentWithPreview(String title, Uri imageThumbnail)2446     private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
2447         Intent sendIntent = new Intent();
2448         sendIntent.setAction(Intent.ACTION_SEND);
2449         sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
2450         sendIntent.putExtra(Intent.EXTRA_TITLE, title);
2451         if (imageThumbnail != null) {
2452             ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
2453             sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
2454         }
2455 
2456         return sendIntent;
2457     }
2458 
createSendUriIntentWithPreview(ArrayList<Uri> uris)2459     private Intent createSendUriIntentWithPreview(ArrayList<Uri> uris) {
2460         Intent sendIntent = new Intent();
2461 
2462         if (uris.size() > 1) {
2463             sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
2464             sendIntent.putExtra(Intent.EXTRA_STREAM, uris);
2465         } else {
2466             sendIntent.setAction(Intent.ACTION_SEND);
2467             sendIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
2468         }
2469 
2470         return sendIntent;
2471     }
2472 
createViewTextIntent()2473     private Intent createViewTextIntent() {
2474         Intent viewIntent = new Intent();
2475         viewIntent.setAction(Intent.ACTION_VIEW);
2476         viewIntent.putExtra(Intent.EXTRA_TEXT, "testing intent viewing");
2477         return viewIntent;
2478     }
2479 
createResolvedComponentsForTest(int numberOfResults)2480     private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
2481         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
2482         for (int i = 0; i < numberOfResults; i++) {
2483             infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
2484         }
2485         return infoList;
2486     }
2487 
createResolvedComponentsForTestWithOtherProfile( int numberOfResults)2488     private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
2489             int numberOfResults) {
2490         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
2491         for (int i = 0; i < numberOfResults; i++) {
2492             if (i == 0) {
2493                 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
2494             } else {
2495                 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
2496             }
2497         }
2498         return infoList;
2499     }
2500 
createResolvedComponentsForTestWithOtherProfile( int numberOfResults, int userId)2501     private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
2502             int numberOfResults, int userId) {
2503         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
2504         for (int i = 0; i < numberOfResults; i++) {
2505             if (i == 0) {
2506                 infoList.add(
2507                         ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
2508             } else {
2509                 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
2510             }
2511         }
2512         return infoList;
2513     }
2514 
createResolvedComponentsForTestWithUserId( int numberOfResults, int userId)2515     private List<ResolvedComponentInfo> createResolvedComponentsForTestWithUserId(
2516             int numberOfResults, int userId) {
2517         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
2518         for (int i = 0; i < numberOfResults; i++) {
2519             infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
2520         }
2521         return infoList;
2522     }
2523 
createDirectShareTargets(int numberOfResults, String packageName)2524     private List<ChooserTarget> createDirectShareTargets(int numberOfResults, String packageName) {
2525         Icon icon = Icon.createWithBitmap(createBitmap());
2526         String testTitle = "testTitle";
2527         List<ChooserTarget> targets = new ArrayList<>();
2528         for (int i = 0; i < numberOfResults; i++) {
2529             ComponentName componentName;
2530             if (packageName.isEmpty()) {
2531                 componentName = ResolverDataProvider.createComponentName(i);
2532             } else {
2533                 componentName = new ComponentName(packageName, packageName + ".class");
2534             }
2535             ChooserTarget tempTarget = new ChooserTarget(
2536                     testTitle + i,
2537                     icon,
2538                     (float) (1 - ((i + 1) / 10.0)),
2539                     componentName,
2540                     null);
2541             targets.add(tempTarget);
2542         }
2543         return targets;
2544     }
2545 
waitForIdle()2546     private void waitForIdle() {
2547         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
2548     }
2549 
createBitmap()2550     private Bitmap createBitmap() {
2551         int width = 200;
2552         int height = 200;
2553         Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
2554         Canvas canvas = new Canvas(bitmap);
2555 
2556         Paint paint = new Paint();
2557         paint.setColor(Color.RED);
2558         paint.setStyle(Paint.Style.FILL);
2559         canvas.drawPaint(paint);
2560 
2561         paint.setColor(Color.WHITE);
2562         paint.setAntiAlias(true);
2563         paint.setTextSize(14.f);
2564         paint.setTextAlign(Paint.Align.CENTER);
2565         canvas.drawText("Hi!", (width / 2.f), (height / 2.f), paint);
2566 
2567         return bitmap;
2568     }
2569 
createShortcuts(Context context)2570     private List<ShareShortcutInfo> createShortcuts(Context context) {
2571         Intent testIntent = new Intent("TestIntent");
2572 
2573         List<ShareShortcutInfo> shortcuts = new ArrayList<>();
2574         shortcuts.add(new ShareShortcutInfo(
2575                 new ShortcutInfo.Builder(context, "shortcut1")
2576                         .setIntent(testIntent).setShortLabel("label1").setRank(3).build(), // 0  2
2577                 new ComponentName("package1", "class1")));
2578         shortcuts.add(new ShareShortcutInfo(
2579                 new ShortcutInfo.Builder(context, "shortcut2")
2580                         .setIntent(testIntent).setShortLabel("label2").setRank(7).build(), // 1  3
2581                 new ComponentName("package2", "class2")));
2582         shortcuts.add(new ShareShortcutInfo(
2583                 new ShortcutInfo.Builder(context, "shortcut3")
2584                         .setIntent(testIntent).setShortLabel("label3").setRank(1).build(), // 2  0
2585                 new ComponentName("package3", "class3")));
2586         shortcuts.add(new ShareShortcutInfo(
2587                 new ShortcutInfo.Builder(context, "shortcut4")
2588                         .setIntent(testIntent).setShortLabel("label4").setRank(3).build(), // 3  2
2589                 new ComponentName("package4", "class4")));
2590 
2591         return shortcuts;
2592     }
2593 
assertCorrectShortcutToChooserTargetConversion(List<ShareShortcutInfo> shortcuts, List<ChooserTarget> chooserTargets, int[] expectedOrder, float[] expectedScores)2594     private void assertCorrectShortcutToChooserTargetConversion(List<ShareShortcutInfo> shortcuts,
2595             List<ChooserTarget> chooserTargets, int[] expectedOrder, float[] expectedScores) {
2596         assertEquals(expectedOrder.length, chooserTargets.size());
2597         for (int i = 0; i < chooserTargets.size(); i++) {
2598             ChooserTarget ct = chooserTargets.get(i);
2599             ShortcutInfo si = shortcuts.get(expectedOrder[i]).getShortcutInfo();
2600             ComponentName cn = shortcuts.get(expectedOrder[i]).getTargetComponent();
2601 
2602             assertEquals(si.getId(), ct.getIntentExtras().getString(Intent.EXTRA_SHORTCUT_ID));
2603             assertEquals(si.getShortLabel(), ct.getTitle());
2604             assertThat(Math.abs(expectedScores[i] - ct.getScore()) < 0.000001, is(true));
2605             assertEquals(cn.flattenToString(), ct.getComponentName().flattenToString());
2606         }
2607     }
2608 
2609     private void markWorkProfileUserAvailable() {
2610         sOverrides.workProfileUserHandle = UserHandle.of(10);
2611     }
2612 
2613     private void setupResolverControllers(
2614             List<ResolvedComponentInfo> personalResolvedComponentInfos,
2615             List<ResolvedComponentInfo> workResolvedComponentInfos) {
2616         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
2617                 Mockito.anyBoolean(),
2618                 Mockito.isA(List.class)))
2619                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2620         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
2621                 Mockito.anyBoolean(),
2622                 Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
2623         when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
2624                 Mockito.anyBoolean(),
2625                 Mockito.isA(List.class),
2626                 eq(UserHandle.SYSTEM)))
2627                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
2628     }
2629 }
2630