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 androidx.test.espresso.Espresso.onView;
20 import static androidx.test.espresso.action.ViewActions.click;
21 import static androidx.test.espresso.action.ViewActions.swipeUp;
22 import static androidx.test.espresso.assertion.ViewAssertions.matches;
23 import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
24 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
25 import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
26 import static androidx.test.espresso.matcher.ViewMatchers.withId;
27 import static androidx.test.espresso.matcher.ViewMatchers.withText;
28 
29 import static com.android.internal.app.MatcherUtils.first;
30 import static com.android.internal.app.ResolverDataProvider.createPackageManagerMockedInfo;
31 import static com.android.internal.app.ResolverWrapperActivity.sOverrides;
32 
33 import static junit.framework.Assert.assertTrue;
34 
35 import static org.hamcrest.CoreMatchers.allOf;
36 import static org.hamcrest.CoreMatchers.is;
37 import static org.hamcrest.CoreMatchers.not;
38 import static org.hamcrest.MatcherAssert.assertThat;
39 import static org.mockito.ArgumentMatchers.eq;
40 import static org.mockito.Mockito.when;
41 import static org.testng.Assert.assertFalse;
42 import static org.testng.Assert.fail;
43 
44 import android.content.Intent;
45 import android.content.pm.ResolveInfo;
46 import android.net.Uri;
47 import android.os.RemoteException;
48 import android.os.UserHandle;
49 import android.text.TextUtils;
50 import android.view.View;
51 import android.widget.RelativeLayout;
52 import android.widget.TextView;
53 
54 import androidx.test.InstrumentationRegistry;
55 import androidx.test.espresso.Espresso;
56 import androidx.test.espresso.NoMatchingViewException;
57 import androidx.test.rule.ActivityTestRule;
58 import androidx.test.runner.AndroidJUnit4;
59 
60 import com.android.internal.R;
61 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
62 import com.android.internal.app.ResolverDataProvider.PackageManagerMockedInfo;
63 import com.android.internal.app.ResolverListAdapter.ActivityInfoPresentationGetter;
64 import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
65 import com.android.internal.widget.ResolverDrawerLayout;
66 
67 import com.google.android.collect.Lists;
68 
69 import org.junit.Before;
70 import org.junit.Ignore;
71 import org.junit.Rule;
72 import org.junit.Test;
73 import org.junit.runner.RunWith;
74 import org.mockito.Mockito;
75 
76 import java.util.ArrayList;
77 import java.util.List;
78 
79 /**
80  * Resolver activity instrumentation tests
81  */
82 @RunWith(AndroidJUnit4.class)
83 public class ResolverActivityTest {
84 
85     private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
86             .getInstrumentation().getTargetContext().getUser();
87     @Rule
88     public ActivityTestRule<ResolverWrapperActivity> mActivityRule =
89             new ActivityTestRule<>(ResolverWrapperActivity.class, false,
90                     false);
91 
92     @Before
cleanOverrideData()93     public void cleanOverrideData() {
94         sOverrides.reset();
95     }
96 
97     @Test
twoOptionsAndUserSelectsOne()98     public void twoOptionsAndUserSelectsOne() throws InterruptedException {
99         Intent sendIntent = createSendImageIntent();
100         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
101                 PERSONAL_USER_HANDLE);
102 
103         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
104                 Mockito.anyBoolean(),
105                 Mockito.anyBoolean(),
106                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
107 
108         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
109         Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
110         waitForIdle();
111 
112         assertThat(activity.getAdapter().getCount(), is(2));
113 
114         ResolveInfo[] chosen = new ResolveInfo[1];
115         sOverrides.onSafelyStartInternalCallback = result -> {
116             chosen[0] = result.first.getResolveInfo();
117             return true;
118         };
119 
120         ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
121         onView(withText(toChoose.activityInfo.name))
122                 .perform(click());
123         onView(withId(R.id.button_once))
124                 .perform(click());
125         waitForIdle();
126         assertThat(chosen[0], is(toChoose));
127     }
128 
129     @Ignore // Failing - b/144929805
130     @Test
setMaxHeight()131     public void setMaxHeight() throws Exception {
132         Intent sendIntent = createSendImageIntent();
133         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
134                 PERSONAL_USER_HANDLE);
135 
136         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
137                 Mockito.anyBoolean(),
138                 Mockito.anyBoolean(),
139                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
140         waitForIdle();
141 
142         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
143         final View viewPager = activity.findViewById(R.id.profile_pager);
144         final int initialResolverHeight = viewPager.getHeight();
145 
146         activity.runOnUiThread(() -> {
147             ResolverDrawerLayout layout = (ResolverDrawerLayout)
148                     activity.findViewById(
149                             R.id.contentPanel);
150             ((ResolverDrawerLayout.LayoutParams) viewPager.getLayoutParams()).maxHeight
151                 = initialResolverHeight - 1;
152             // Force a relayout
153             layout.invalidate();
154             layout.requestLayout();
155         });
156         waitForIdle();
157         assertThat("Drawer should be capped at maxHeight",
158                 viewPager.getHeight() == (initialResolverHeight - 1));
159 
160         activity.runOnUiThread(() -> {
161             ResolverDrawerLayout layout = (ResolverDrawerLayout)
162                     activity.findViewById(
163                             R.id.contentPanel);
164             ((ResolverDrawerLayout.LayoutParams) viewPager.getLayoutParams()).maxHeight
165                 = initialResolverHeight + 1;
166             // Force a relayout
167             layout.invalidate();
168             layout.requestLayout();
169         });
170         waitForIdle();
171         assertThat("Drawer should not change height if its height is less than maxHeight",
172                 viewPager.getHeight() == initialResolverHeight);
173     }
174 
175     @Ignore // Failing - b/144929805
176     @Test
setShowAtTopToTrue()177     public void setShowAtTopToTrue() throws Exception {
178         Intent sendIntent = createSendImageIntent();
179         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
180                 PERSONAL_USER_HANDLE);
181 
182         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
183                 Mockito.anyBoolean(),
184                 Mockito.anyBoolean(),
185                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
186         waitForIdle();
187 
188         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
189         final View viewPager = activity.findViewById(R.id.profile_pager);
190         final View divider = activity.findViewById(R.id.divider);
191         final RelativeLayout profileView =
192             (RelativeLayout) activity.findViewById(R.id.profile_button).getParent();
193         assertThat("Drawer should show at bottom by default",
194                 profileView.getBottom() + divider.getHeight() == viewPager.getTop()
195                         && profileView.getTop() > 0);
196 
197         activity.runOnUiThread(() -> {
198             ResolverDrawerLayout layout = (ResolverDrawerLayout)
199                     activity.findViewById(
200                             R.id.contentPanel);
201             layout.setShowAtTop(true);
202         });
203         waitForIdle();
204         assertThat("Drawer should show at top with new attribute",
205             profileView.getBottom() + divider.getHeight() == viewPager.getTop()
206                     && profileView.getTop() == 0);
207     }
208 
209     @Test
hasLastChosenActivity()210     public void hasLastChosenActivity() throws Exception {
211         Intent sendIntent = createSendImageIntent();
212         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
213                 PERSONAL_USER_HANDLE);
214         ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
215 
216         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
217                 Mockito.anyBoolean(),
218                 Mockito.anyBoolean(),
219                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
220         when(sOverrides.resolverListController.getLastChosen())
221                 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
222 
223         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
224         waitForIdle();
225 
226         // The other entry is filtered to the last used slot
227         assertThat(activity.getAdapter().getCount(), is(1));
228         assertThat(activity.getAdapter().getPlaceholderCount(), is(1));
229 
230         ResolveInfo[] chosen = new ResolveInfo[1];
231         sOverrides.onSafelyStartInternalCallback = result -> {
232             chosen[0] = result.first.getResolveInfo();
233             return true;
234         };
235 
236         onView(withId(R.id.button_once)).perform(click());
237         waitForIdle();
238         assertThat(chosen[0], is(toChoose));
239     }
240 
241     @Test
hasOtherProfileOneOption()242     public void hasOtherProfileOneOption() throws Exception {
243         // enable the work tab feature flag
244         ResolverActivity.ENABLE_TABBED_VIEW = true;
245         List<ResolvedComponentInfo> personalResolvedComponentInfos =
246                 createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
247                         PERSONAL_USER_HANDLE);
248         markWorkProfileUserAvailable();
249         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
250                 sOverrides.workProfileUserHandle);
251         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
252 
253         ResolveInfo toChoose = personalResolvedComponentInfos.get(1).getResolveInfoAt(0);
254         Intent sendIntent = createSendImageIntent();
255         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
256         Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
257         waitForIdle();
258 
259         // The other entry is filtered to the last used slot
260         assertThat(activity.getAdapter().getCount(), is(1));
261 
262         ResolveInfo[] chosen = new ResolveInfo[1];
263         sOverrides.onSafelyStartInternalCallback = result -> {
264             chosen[0] = result.first.getResolveInfo();
265             return true;
266         };
267         // Make a stable copy of the components as the original list may be modified
268         List<ResolvedComponentInfo> stableCopy =
269                 createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10,
270                         PERSONAL_USER_HANDLE);
271         // We pick the first one as there is another one in the work profile side
272         onView(first(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name)))
273                 .perform(click());
274         onView(withId(R.id.button_once))
275                 .perform(click());
276         waitForIdle();
277         assertThat(chosen[0], is(toChoose));
278     }
279 
280     @Test
hasOtherProfileTwoOptionsAndUserSelectsOne()281     public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
282         // enable the work tab feature flag
283         ResolverActivity.ENABLE_TABBED_VIEW = true;
284 
285         Intent sendIntent = createSendImageIntent();
286         List<ResolvedComponentInfo> resolvedComponentInfos =
287                 createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
288         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
289 
290         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
291                 Mockito.anyBoolean(),
292                 Mockito.anyBoolean(),
293                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
294 
295         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
296         Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
297         waitForIdle();
298 
299         // The other entry is filtered to the other profile slot
300         assertThat(activity.getAdapter().getCount(), is(2));
301 
302         ResolveInfo[] chosen = new ResolveInfo[1];
303         sOverrides.onSafelyStartInternalCallback = result -> {
304             chosen[0] = result.first.getResolveInfo();
305             return true;
306         };
307 
308         // Confirm that the button bar is disabled by default
309         onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
310 
311         // Make a stable copy of the components as the original list may be modified
312         List<ResolvedComponentInfo> stableCopy =
313                 createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
314 
315         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
316                 .perform(click());
317         onView(withId(R.id.button_once)).perform(click());
318         waitForIdle();
319         assertThat(chosen[0], is(toChoose));
320     }
321 
322 
323     @Test
hasLastChosenActivityAndOtherProfile()324     public void hasLastChosenActivityAndOtherProfile() throws Exception {
325         // enable the work tab feature flag
326         ResolverActivity.ENABLE_TABBED_VIEW = true;
327 
328         // In this case we prefer the other profile and don't display anything about the last
329         // chosen activity.
330         Intent sendIntent = createSendImageIntent();
331         List<ResolvedComponentInfo> resolvedComponentInfos =
332                 createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
333         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
334 
335         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
336                 Mockito.anyBoolean(),
337                 Mockito.anyBoolean(),
338                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
339         when(sOverrides.resolverListController.getLastChosen())
340                 .thenReturn(resolvedComponentInfos.get(1).getResolveInfoAt(0));
341 
342         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
343         Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
344         waitForIdle();
345 
346         // The other entry is filtered to the other profile slot
347         assertThat(activity.getAdapter().getCount(), is(2));
348 
349         ResolveInfo[] chosen = new ResolveInfo[1];
350         sOverrides.onSafelyStartInternalCallback = result -> {
351             chosen[0] = result.first.getResolveInfo();
352             return true;
353         };
354 
355         // Confirm that the button bar is disabled by default
356         onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
357 
358         // Make a stable copy of the components as the original list may be modified
359         List<ResolvedComponentInfo> stableCopy =
360                 createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
361 
362         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
363                 .perform(click());
364         onView(withId(R.id.button_once)).perform(click());
365         waitForIdle();
366         assertThat(chosen[0], is(toChoose));
367     }
368 
369     @Test
getActivityLabelAndSubLabel()370     public void getActivityLabelAndSubLabel() throws Exception {
371         ActivityInfoPresentationGetter pg;
372         PackageManagerMockedInfo info;
373 
374         info = createPackageManagerMockedInfo(false);
375         pg = new ActivityInfoPresentationGetter(
376                 info.ctx, 0, info.activityInfo);
377         assertThat("Label should match app label", pg.getLabel().equals(
378                 info.setAppLabel));
379         assertThat("Sublabel should match activity label if set",
380                 pg.getSubLabel().equals(info.setActivityLabel));
381 
382         info = createPackageManagerMockedInfo(true);
383         pg = new ActivityInfoPresentationGetter(
384                 info.ctx, 0, info.activityInfo);
385         assertThat("With override permission label should match activity label if set",
386                 pg.getLabel().equals(info.setActivityLabel));
387         assertThat("With override permission sublabel should be empty",
388                 TextUtils.isEmpty(pg.getSubLabel()));
389     }
390 
391     @Test
getResolveInfoLabelAndSubLabel()392     public void getResolveInfoLabelAndSubLabel() throws Exception {
393         ResolveInfoPresentationGetter pg;
394         PackageManagerMockedInfo info;
395 
396         info = createPackageManagerMockedInfo(false);
397         pg = new ResolveInfoPresentationGetter(
398                 info.ctx, 0, info.resolveInfo);
399         assertThat("Label should match app label", pg.getLabel().equals(
400                 info.setAppLabel));
401         assertThat("Sublabel should match resolve info label if set",
402                 pg.getSubLabel().equals(info.setResolveInfoLabel));
403 
404         info = createPackageManagerMockedInfo(true);
405         pg = new ResolveInfoPresentationGetter(
406                 info.ctx, 0, info.resolveInfo);
407         assertThat("With override permission label should match activity label if set",
408                 pg.getLabel().equals(info.setActivityLabel));
409         assertThat("With override permission the sublabel should be the resolve info label",
410                 pg.getSubLabel().equals(info.setResolveInfoLabel));
411     }
412 
413     @Test
testWorkTab_displayedWhenWorkProfileUserAvailable()414     public void testWorkTab_displayedWhenWorkProfileUserAvailable() {
415         // enable the work tab feature flag
416         ResolverActivity.ENABLE_TABBED_VIEW = true;
417         Intent sendIntent = createSendImageIntent();
418         markWorkProfileUserAvailable();
419 
420         mActivityRule.launchActivity(sendIntent);
421         waitForIdle();
422 
423         onView(withId(R.id.tabs)).check(matches(isDisplayed()));
424     }
425 
426     @Test
testWorkTab_hiddenWhenWorkProfileUserNotAvailable()427     public void testWorkTab_hiddenWhenWorkProfileUserNotAvailable() {
428         // enable the work tab feature flag
429         ResolverActivity.ENABLE_TABBED_VIEW = true;
430         Intent sendIntent = createSendImageIntent();
431 
432         mActivityRule.launchActivity(sendIntent);
433         waitForIdle();
434 
435         onView(withId(R.id.tabs)).check(matches(not(isDisplayed())));
436     }
437 
438     @Test
testWorkTab_workTabListPopulatedBeforeGoingToTab()439     public void testWorkTab_workTabListPopulatedBeforeGoingToTab() throws InterruptedException {
440         // enable the work tab feature flag
441         ResolverActivity.ENABLE_TABBED_VIEW = true;
442         List<ResolvedComponentInfo> personalResolvedComponentInfos =
443                 createResolvedComponentsForTestWithOtherProfile(3, /* userId = */ 10,
444                         PERSONAL_USER_HANDLE);
445         markWorkProfileUserAvailable();
446         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
447                 sOverrides.workProfileUserHandle);
448         setupResolverControllers(personalResolvedComponentInfos,
449                 new ArrayList<>(workResolvedComponentInfos));
450         Intent sendIntent = createSendImageIntent();
451 
452         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
453         waitForIdle();
454 
455         assertThat(activity.getCurrentUserHandle().getIdentifier(), is(0));
456         // The work list adapter must be populated in advance before tapping the other tab
457         assertThat(activity.getWorkListAdapter().getCount(), is(4));
458     }
459 
460     @Test
testWorkTab_workTabUsesExpectedAdapter()461     public void testWorkTab_workTabUsesExpectedAdapter() {
462         // enable the work tab feature flag
463         ResolverActivity.ENABLE_TABBED_VIEW = true;
464         List<ResolvedComponentInfo> personalResolvedComponentInfos =
465                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
466                         PERSONAL_USER_HANDLE);
467         markWorkProfileUserAvailable();
468         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
469                 sOverrides.workProfileUserHandle);
470         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
471         Intent sendIntent = createSendImageIntent();
472 
473         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
474         waitForIdle();
475         onView(withText(R.string.resolver_work_tab)).perform(click());
476 
477         assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
478         assertThat(activity.getWorkListAdapter().getCount(), is(4));
479     }
480 
481     @Test
testWorkTab_personalTabUsesExpectedAdapter()482     public void testWorkTab_personalTabUsesExpectedAdapter() {
483         // enable the work tab feature flag
484         ResolverActivity.ENABLE_TABBED_VIEW = true;
485         List<ResolvedComponentInfo> personalResolvedComponentInfos =
486                 createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
487         markWorkProfileUserAvailable();
488         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
489                 sOverrides.workProfileUserHandle);
490         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
491         Intent sendIntent = createSendImageIntent();
492 
493         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
494         waitForIdle();
495         onView(withText(R.string.resolver_work_tab)).perform(click());
496 
497         assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
498         assertThat(activity.getPersonalListAdapter().getCount(), is(2));
499     }
500 
501     @Test
testWorkTab_workProfileHasExpectedNumberOfTargets()502     public void testWorkTab_workProfileHasExpectedNumberOfTargets() throws InterruptedException {
503         // enable the work tab feature flag
504         ResolverActivity.ENABLE_TABBED_VIEW = true;
505         markWorkProfileUserAvailable();
506         List<ResolvedComponentInfo> personalResolvedComponentInfos =
507                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
508                         PERSONAL_USER_HANDLE);
509         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
510                 sOverrides.workProfileUserHandle);
511         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
512         Intent sendIntent = createSendImageIntent();
513 
514         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
515         waitForIdle();
516 
517         onView(withText(R.string.resolver_work_tab))
518                 .perform(click());
519         waitForIdle();
520         assertThat(activity.getWorkListAdapter().getCount(), is(4));
521     }
522 
523     @Test
testWorkTab_selectingWorkTabAppOpensAppInWorkProfile()524     public void testWorkTab_selectingWorkTabAppOpensAppInWorkProfile() throws InterruptedException {
525         // enable the work tab feature flag
526         ResolverActivity.ENABLE_TABBED_VIEW = true;
527         markWorkProfileUserAvailable();
528         List<ResolvedComponentInfo> personalResolvedComponentInfos =
529                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
530                         PERSONAL_USER_HANDLE);
531         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
532                 sOverrides.workProfileUserHandle);
533         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
534         Intent sendIntent = createSendImageIntent();
535         ResolveInfo[] chosen = new ResolveInfo[1];
536         sOverrides.onSafelyStartInternalCallback = result -> {
537             chosen[0] = result.first.getResolveInfo();
538             return true;
539         };
540 
541         mActivityRule.launchActivity(sendIntent);
542         waitForIdle();
543         onView(withText(R.string.resolver_work_tab))
544                 .perform(click());
545         waitForIdle();
546         onView(first(allOf(withText(workResolvedComponentInfos.get(0)
547                 .getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
548                 .perform(click());
549         onView(withId(R.id.button_once))
550                 .perform(click());
551 
552         waitForIdle();
553         assertThat(chosen[0], is(workResolvedComponentInfos.get(0).getResolveInfoAt(0)));
554     }
555 
556     @Test
testWorkTab_noPersonalApps_workTabHasExpectedNumberOfTargets()557     public void testWorkTab_noPersonalApps_workTabHasExpectedNumberOfTargets()
558             throws InterruptedException {
559         // enable the work tab feature flag
560         ResolverActivity.ENABLE_TABBED_VIEW = true;
561         markWorkProfileUserAvailable();
562         List<ResolvedComponentInfo> personalResolvedComponentInfos =
563                 createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
564         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
565                 sOverrides.workProfileUserHandle);
566         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
567         Intent sendIntent = createSendImageIntent();
568 
569         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
570         waitForIdle();
571         onView(withText(R.string.resolver_work_tab))
572                 .perform(click());
573 
574         waitForIdle();
575         assertThat(activity.getWorkListAdapter().getCount(), is(4));
576     }
577 
578     @Test
testWorkTab_headerIsVisibleInPersonalTab()579     public void testWorkTab_headerIsVisibleInPersonalTab() {
580         // enable the work tab feature flag
581         ResolverActivity.ENABLE_TABBED_VIEW = true;
582         markWorkProfileUserAvailable();
583         List<ResolvedComponentInfo> personalResolvedComponentInfos =
584                 createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
585         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
586                 sOverrides.workProfileUserHandle);
587         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
588         Intent sendIntent = createOpenWebsiteIntent();
589 
590         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
591         waitForIdle();
592         TextView headerText = activity.findViewById(R.id.title);
593         String initialText = headerText.getText().toString();
594         assertFalse(initialText.isEmpty(), "Header text is empty.");
595         assertThat(headerText.getVisibility(), is(View.VISIBLE));
596     }
597 
598     @Test
testWorkTab_switchTabs_headerStaysSame()599     public void testWorkTab_switchTabs_headerStaysSame() {
600         // enable the work tab feature flag
601         ResolverActivity.ENABLE_TABBED_VIEW = true;
602         markWorkProfileUserAvailable();
603         List<ResolvedComponentInfo> personalResolvedComponentInfos =
604                 createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
605         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
606                 sOverrides.workProfileUserHandle);
607         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
608         Intent sendIntent = createOpenWebsiteIntent();
609 
610         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
611         waitForIdle();
612         TextView headerText = activity.findViewById(R.id.title);
613         String initialText = headerText.getText().toString();
614         onView(withText(R.string.resolver_work_tab))
615                 .perform(click());
616 
617         waitForIdle();
618         String currentText = headerText.getText().toString();
619         assertThat(headerText.getVisibility(), is(View.VISIBLE));
620         assertThat(String.format("Header text is not the same when switching tabs, personal profile"
621                         + " header was %s but work profile header is %s", initialText, currentText),
622                 TextUtils.equals(initialText, currentText));
623     }
624 
625     @Test
testWorkTab_noPersonalApps_canStartWorkApps()626     public void testWorkTab_noPersonalApps_canStartWorkApps()
627             throws InterruptedException {
628         // enable the work tab feature flag
629         ResolverActivity.ENABLE_TABBED_VIEW = true;
630         markWorkProfileUserAvailable();
631         List<ResolvedComponentInfo> personalResolvedComponentInfos =
632                 createResolvedComponentsForTestWithOtherProfile(3, /* userId= */ 10,
633                         PERSONAL_USER_HANDLE);
634         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
635                 sOverrides.workProfileUserHandle);
636         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
637         Intent sendIntent = createSendImageIntent();
638         ResolveInfo[] chosen = new ResolveInfo[1];
639         sOverrides.onSafelyStartInternalCallback = result -> {
640             chosen[0] = result.first.getResolveInfo();
641             return true;
642         };
643 
644         mActivityRule.launchActivity(sendIntent);
645         waitForIdle();
646         onView(withText(R.string.resolver_work_tab))
647                 .perform(click());
648         waitForIdle();
649         onView(first(allOf(
650                 withText(workResolvedComponentInfos.get(0)
651                         .getResolveInfoAt(0).activityInfo.applicationInfo.name),
652                 isDisplayed())))
653                 .perform(click());
654         onView(withId(R.id.button_once))
655                 .perform(click());
656         waitForIdle();
657 
658         assertThat(chosen[0], is(workResolvedComponentInfos.get(0).getResolveInfoAt(0)));
659     }
660 
661     @Test
testWorkTab_crossProfileIntentsDisabled_personalToWork_emptyStateShown()662     public void testWorkTab_crossProfileIntentsDisabled_personalToWork_emptyStateShown() {
663         // enable the work tab feature flag
664         ResolverActivity.ENABLE_TABBED_VIEW = true;
665         markWorkProfileUserAvailable();
666         int workProfileTargets = 4;
667         List<ResolvedComponentInfo> personalResolvedComponentInfos =
668                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
669                         PERSONAL_USER_HANDLE);
670         List<ResolvedComponentInfo> workResolvedComponentInfos =
671                 createResolvedComponentsForTest(workProfileTargets,
672                         sOverrides.workProfileUserHandle);
673         sOverrides.hasCrossProfileIntents = false;
674         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
675         Intent sendIntent = createSendImageIntent();
676         sendIntent.setType("TestType");
677 
678         mActivityRule.launchActivity(sendIntent);
679         waitForIdle();
680         onView(withText(R.string.resolver_work_tab)).perform(click());
681         waitForIdle();
682         onView(withId(R.id.contentPanel))
683                 .perform(swipeUp());
684 
685         onView(withText(R.string.resolver_cross_profile_blocked))
686                 .check(matches(isDisplayed()));
687     }
688 
689     @Test
testWorkTab_workProfileDisabled_emptyStateShown()690     public void testWorkTab_workProfileDisabled_emptyStateShown() {
691         // enable the work tab feature flag
692         ResolverActivity.ENABLE_TABBED_VIEW = true;
693         markWorkProfileUserAvailable();
694         int workProfileTargets = 4;
695         List<ResolvedComponentInfo> personalResolvedComponentInfos =
696                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
697                         PERSONAL_USER_HANDLE);
698         List<ResolvedComponentInfo> workResolvedComponentInfos =
699                 createResolvedComponentsForTest(workProfileTargets,
700                         sOverrides.workProfileUserHandle);
701         sOverrides.isQuietModeEnabled = true;
702         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
703         Intent sendIntent = createSendImageIntent();
704         sendIntent.setType("TestType");
705 
706         mActivityRule.launchActivity(sendIntent);
707         waitForIdle();
708         onView(withId(R.id.contentPanel))
709                 .perform(swipeUp());
710         onView(withText(R.string.resolver_work_tab)).perform(click());
711         waitForIdle();
712 
713         onView(withText(R.string.resolver_turn_on_work_apps))
714                 .check(matches(isDisplayed()));
715     }
716 
717     @Test
testWorkTab_noWorkAppsAvailable_emptyStateShown()718     public void testWorkTab_noWorkAppsAvailable_emptyStateShown() {
719         // enable the work tab feature flag
720         ResolverActivity.ENABLE_TABBED_VIEW = true;
721         markWorkProfileUserAvailable();
722         List<ResolvedComponentInfo> personalResolvedComponentInfos =
723                 createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
724         List<ResolvedComponentInfo> workResolvedComponentInfos =
725                 createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
726         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
727         Intent sendIntent = createSendImageIntent();
728         sendIntent.setType("TestType");
729 
730         mActivityRule.launchActivity(sendIntent);
731         waitForIdle();
732         onView(withId(R.id.contentPanel))
733                 .perform(swipeUp());
734         onView(withText(R.string.resolver_work_tab)).perform(click());
735         waitForIdle();
736 
737         onView(withText(R.string.resolver_no_work_apps_available))
738                 .check(matches(isDisplayed()));
739     }
740 
741     @Test
testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown()742     public void testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown() {
743         // enable the work tab feature flag
744         ResolverActivity.ENABLE_TABBED_VIEW = true;
745         markWorkProfileUserAvailable();
746         List<ResolvedComponentInfo> personalResolvedComponentInfos =
747                 createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
748         List<ResolvedComponentInfo> workResolvedComponentInfos =
749                 createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
750         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
751         Intent sendIntent = createSendImageIntent();
752         sendIntent.setType("TestType");
753         sOverrides.isQuietModeEnabled = true;
754         sOverrides.hasCrossProfileIntents = false;
755 
756         mActivityRule.launchActivity(sendIntent);
757         waitForIdle();
758         onView(withId(R.id.contentPanel))
759                 .perform(swipeUp());
760         onView(withText(R.string.resolver_work_tab)).perform(click());
761         waitForIdle();
762 
763         onView(withText(R.string.resolver_cross_profile_blocked))
764                 .check(matches(isDisplayed()));
765     }
766 
767     @Test
testMiniResolver()768     public void testMiniResolver() {
769         ResolverActivity.ENABLE_TABBED_VIEW = true;
770         markWorkProfileUserAvailable();
771         List<ResolvedComponentInfo> personalResolvedComponentInfos =
772                 createResolvedComponentsForTest(1, PERSONAL_USER_HANDLE);
773         List<ResolvedComponentInfo> workResolvedComponentInfos =
774                 createResolvedComponentsForTest(1, sOverrides.workProfileUserHandle);
775         // Personal profile only has a browser
776         personalResolvedComponentInfos.get(0).getResolveInfoAt(0).handleAllWebDataURI = true;
777         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
778         Intent sendIntent = createSendImageIntent();
779         sendIntent.setType("TestType");
780 
781         mActivityRule.launchActivity(sendIntent);
782         waitForIdle();
783         onView(withId(R.id.open_cross_profile)).check(matches(isDisplayed()));
784     }
785 
786     @Test
testMiniResolver_noCurrentProfileTarget()787     public void testMiniResolver_noCurrentProfileTarget() {
788         ResolverActivity.ENABLE_TABBED_VIEW = true;
789         markWorkProfileUserAvailable();
790         List<ResolvedComponentInfo> personalResolvedComponentInfos =
791                 createResolvedComponentsForTest(0, PERSONAL_USER_HANDLE);
792         List<ResolvedComponentInfo> workResolvedComponentInfos =
793                 createResolvedComponentsForTest(1, sOverrides.workProfileUserHandle);
794         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
795         Intent sendIntent = createSendImageIntent();
796         sendIntent.setType("TestType");
797 
798         mActivityRule.launchActivity(sendIntent);
799         waitForIdle();
800 
801         // Need to ensure mini resolver doesn't trigger here.
802         assertNotMiniResolver();
803     }
804 
assertNotMiniResolver()805     private void assertNotMiniResolver() {
806         try {
807             onView(withId(R.id.open_cross_profile)).check(matches(isDisplayed()));
808         } catch (NoMatchingViewException e) {
809             return;
810         }
811         fail("Mini resolver present but shouldn't be");
812     }
813 
814     @Test
testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown()815     public void testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown() {
816         // enable the work tab feature flag
817         ResolverActivity.ENABLE_TABBED_VIEW = true;
818         markWorkProfileUserAvailable();
819         List<ResolvedComponentInfo> personalResolvedComponentInfos =
820                 createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
821         List<ResolvedComponentInfo> workResolvedComponentInfos =
822                 createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
823         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
824         Intent sendIntent = createSendImageIntent();
825         sendIntent.setType("TestType");
826         sOverrides.isQuietModeEnabled = true;
827 
828         mActivityRule.launchActivity(sendIntent);
829         waitForIdle();
830         onView(withId(R.id.contentPanel))
831                 .perform(swipeUp());
832         onView(withText(R.string.resolver_work_tab)).perform(click());
833         waitForIdle();
834 
835         onView(withText(R.string.resolver_no_work_apps_available))
836                 .check(matches(isDisplayed()));
837     }
838 
839     @Test
testAutolaunch_singleTarget_withWorkProfileAndTabbedViewOff_noAutolaunch()840     public void testAutolaunch_singleTarget_withWorkProfileAndTabbedViewOff_noAutolaunch() {
841         ResolverActivity.ENABLE_TABBED_VIEW = false;
842         List<ResolvedComponentInfo> personalResolvedComponentInfos =
843                 createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
844                         PERSONAL_USER_HANDLE);
845         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
846                 Mockito.anyBoolean(),
847                 Mockito.anyBoolean(),
848                 Mockito.isA(List.class)))
849                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
850         Intent sendIntent = createSendImageIntent();
851         sendIntent.setType("TestType");
852         ResolveInfo[] chosen = new ResolveInfo[1];
853         sOverrides.onSafelyStartInternalCallback = result -> {
854             chosen[0] = result.first.getResolveInfo();
855             return true;
856         };
857         waitForIdle();
858 
859         mActivityRule.launchActivity(sendIntent);
860         waitForIdle();
861 
862         assertTrue(chosen[0] == null);
863     }
864 
865     @Test
testAutolaunch_singleTarget_noWorkProfile_autolaunch()866     public void testAutolaunch_singleTarget_noWorkProfile_autolaunch() {
867         ResolverActivity.ENABLE_TABBED_VIEW = false;
868         List<ResolvedComponentInfo> personalResolvedComponentInfos =
869                 createResolvedComponentsForTest(1, PERSONAL_USER_HANDLE);
870         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
871                 Mockito.anyBoolean(),
872                 Mockito.anyBoolean(),
873                 Mockito.isA(List.class)))
874                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
875         Intent sendIntent = createSendImageIntent();
876         sendIntent.setType("TestType");
877         ResolveInfo[] chosen = new ResolveInfo[1];
878         sOverrides.onSafelyStartInternalCallback = result -> {
879             chosen[0] = result.first.getResolveInfo();
880             return true;
881         };
882         waitForIdle();
883 
884         mActivityRule.launchActivity(sendIntent);
885         waitForIdle();
886 
887         assertThat(chosen[0], is(personalResolvedComponentInfos.get(0).getResolveInfoAt(0)));
888     }
889 
890     @Test
testWorkTab_onePersonalTarget_emptyStateOnWorkTarget_autolaunch()891     public void testWorkTab_onePersonalTarget_emptyStateOnWorkTarget_autolaunch() {
892         // enable the work tab feature flag
893         ResolverActivity.ENABLE_TABBED_VIEW = true;
894         markWorkProfileUserAvailable();
895         int workProfileTargets = 4;
896         List<ResolvedComponentInfo> personalResolvedComponentInfos =
897                 createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
898                         PERSONAL_USER_HANDLE);
899         List<ResolvedComponentInfo> workResolvedComponentInfos =
900                 createResolvedComponentsForTest(workProfileTargets,
901                         sOverrides.workProfileUserHandle);
902         sOverrides.hasCrossProfileIntents = false;
903         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
904         Intent sendIntent = createSendImageIntent();
905         sendIntent.setType("TestType");
906         ResolveInfo[] chosen = new ResolveInfo[1];
907         sOverrides.onSafelyStartInternalCallback = result -> {
908             chosen[0] = result.first.getResolveInfo();
909             return true;
910         };
911 
912         mActivityRule.launchActivity(sendIntent);
913         waitForIdle();
914 
915         assertThat(chosen[0], is(personalResolvedComponentInfos.get(1).getResolveInfoAt(0)));
916     }
917 
918     @Test
testLayoutWithDefault_withWorkTab_neverShown()919     public void testLayoutWithDefault_withWorkTab_neverShown() throws RemoteException {
920         // enable the work tab feature flag
921         ResolverActivity.ENABLE_TABBED_VIEW = true;
922         markWorkProfileUserAvailable();
923 
924         // In this case we prefer the other profile and don't display anything about the last
925         // chosen activity.
926         Intent sendIntent = createSendImageIntent();
927         List<ResolvedComponentInfo> resolvedComponentInfos =
928                 createResolvedComponentsForTest(2, PERSONAL_USER_HANDLE);
929 
930         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
931                 Mockito.anyBoolean(),
932                 Mockito.anyBoolean(),
933                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
934         when(sOverrides.resolverListController.getLastChosen())
935                 .thenReturn(resolvedComponentInfos.get(1).getResolveInfoAt(0));
936 
937         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
938         Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
939         waitForIdle();
940 
941         // The other entry is filtered to the last used slot
942         assertThat(activity.getAdapter().hasFilteredItem(), is(false));
943         assertThat(activity.getAdapter().getCount(), is(2));
944         assertThat(activity.getAdapter().getPlaceholderCount(), is(2));
945     }
946 
947     @Test
testClonedProfilePresent_personalAdapterIsSetWithPersonalProfile()948     public void testClonedProfilePresent_personalAdapterIsSetWithPersonalProfile() {
949         // enable cloneProfile
950         markCloneProfileUserAvailable();
951         List<ResolvedComponentInfo> resolvedComponentInfos =
952                 createResolvedComponentsWithCloneProfileForTest(
953                         3,
954                         PERSONAL_USER_HANDLE,
955                         sOverrides.cloneProfileUserHandle);
956         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
957                 Mockito.anyBoolean(),
958                 Mockito.anyBoolean(),
959                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
960         Intent sendIntent = createSendImageIntent();
961 
962         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
963         waitForIdle();
964 
965         assertThat(activity.getCurrentUserHandle(), is(activity.getPersonalProfileUserHandle()));
966         assertThat(activity.getAdapter().getCount(), is(3));
967     }
968 
969     @Test
testClonedProfilePresent_personalTabUsesExpectedAdapter()970     public void testClonedProfilePresent_personalTabUsesExpectedAdapter() {
971         // enable the work tab feature flag
972         ResolverActivity.ENABLE_TABBED_VIEW = true;
973         markWorkProfileUserAvailable();
974         // enable cloneProfile
975         markCloneProfileUserAvailable();
976         List<ResolvedComponentInfo> personalResolvedComponentInfos =
977                 createResolvedComponentsWithCloneProfileForTest(
978                         3,
979                         PERSONAL_USER_HANDLE,
980                         sOverrides.cloneProfileUserHandle);
981         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
982                 sOverrides.workProfileUserHandle);
983         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
984         Intent sendIntent = createSendImageIntent();
985 
986         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
987         waitForIdle();
988 
989         assertThat(activity.getCurrentUserHandle(), is(activity.getPersonalProfileUserHandle()));
990         assertThat(activity.getAdapter().getCount(), is(3));
991     }
992 
993     @Test
testClonedProfilePresent_layoutWithDefault_neverShown()994     public void testClonedProfilePresent_layoutWithDefault_neverShown() throws Exception {
995         // enable cloneProfile
996         markCloneProfileUserAvailable();
997         Intent sendIntent = createSendImageIntent();
998         List<ResolvedComponentInfo> resolvedComponentInfos =
999                 createResolvedComponentsWithCloneProfileForTest(
1000                         2,
1001                 PERSONAL_USER_HANDLE,
1002                         sOverrides.cloneProfileUserHandle);
1003 
1004         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1005                 Mockito.anyBoolean(),
1006                 Mockito.anyBoolean(),
1007                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1008         when(sOverrides.resolverListController.getLastChosen())
1009                 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
1010 
1011         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
1012         Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
1013         waitForIdle();
1014 
1015         assertThat(activity.getAdapter().hasFilteredItem(), is(false));
1016         assertThat(activity.getAdapter().getCount(), is(2));
1017         assertThat(activity.getAdapter().getPlaceholderCount(), is(2));
1018     }
1019 
1020     @Test
testClonedProfilePresent_alwaysButtonDisabled()1021     public void testClonedProfilePresent_alwaysButtonDisabled() throws Exception {
1022         // enable cloneProfile
1023         markCloneProfileUserAvailable();
1024         Intent sendIntent = createSendImageIntent();
1025         List<ResolvedComponentInfo> resolvedComponentInfos =
1026                 createResolvedComponentsWithCloneProfileForTest(
1027                         3,
1028                         PERSONAL_USER_HANDLE,
1029                         sOverrides.cloneProfileUserHandle);
1030 
1031         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1032                 Mockito.anyBoolean(),
1033                 Mockito.anyBoolean(),
1034                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1035         when(sOverrides.resolverListController.getLastChosen())
1036                 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
1037 
1038         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
1039         waitForIdle();
1040 
1041         // Confirm that the button bar is disabled by default
1042         onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
1043         onView(withId(R.id.button_always)).check(matches(not(isEnabled())));
1044 
1045         // Make a stable copy of the components as the original list may be modified
1046         List<ResolvedComponentInfo> stableCopy =
1047                 createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
1048 
1049         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
1050                 .perform(click());
1051 
1052         onView(withId(R.id.button_once)).check(matches(isEnabled()));
1053         onView(withId(R.id.button_always)).check(matches(not(isEnabled())));
1054     }
1055 
1056     @Test
testClonedProfilePresent_personalProfileActivityIsStartedInCorrectUser()1057     public void testClonedProfilePresent_personalProfileActivityIsStartedInCorrectUser()
1058             throws Exception {
1059         // enable the work tab feature flag
1060         ResolverActivity.ENABLE_TABBED_VIEW = true;
1061         markWorkProfileUserAvailable();
1062         // enable cloneProfile
1063         markCloneProfileUserAvailable();
1064 
1065         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1066                 createResolvedComponentsWithCloneProfileForTest(
1067                         3,
1068                         PERSONAL_USER_HANDLE,
1069                         sOverrides.cloneProfileUserHandle);
1070         List<ResolvedComponentInfo> workResolvedComponentInfos =
1071                 createResolvedComponentsForTest(3, sOverrides.workProfileUserHandle);
1072         sOverrides.hasCrossProfileIntents = false;
1073         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1074         Intent sendIntent = createSendImageIntent();
1075         sendIntent.setType("TestType");
1076         final UserHandle[] selectedActivityUserHandle = new UserHandle[1];
1077         sOverrides.onSafelyStartInternalCallback = result -> {
1078             selectedActivityUserHandle[0] = result.second;
1079             return true;
1080         };
1081 
1082         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
1083         waitForIdle();
1084         onView(first(allOf(withText(personalResolvedComponentInfos.get(0)
1085                 .getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
1086                 .perform(click());
1087         onView(withId(R.id.button_once))
1088                 .perform(click());
1089         waitForIdle();
1090 
1091         assertThat(selectedActivityUserHandle[0], is(activity.getAdapter().getUserHandle()));
1092     }
1093 
1094     @Test
testClonedProfilePresent_workProfileActivityIsStartedInCorrectUser()1095     public void testClonedProfilePresent_workProfileActivityIsStartedInCorrectUser()
1096             throws Exception {
1097         // enable the work tab feature flag
1098         ResolverActivity.ENABLE_TABBED_VIEW = true;
1099         markWorkProfileUserAvailable();
1100         // enable cloneProfile
1101         markCloneProfileUserAvailable();
1102 
1103         List<ResolvedComponentInfo> personalResolvedComponentInfos =
1104                 createResolvedComponentsWithCloneProfileForTest(
1105                         3,
1106                         PERSONAL_USER_HANDLE,
1107                         sOverrides.cloneProfileUserHandle);
1108         List<ResolvedComponentInfo> workResolvedComponentInfos =
1109                 createResolvedComponentsForTest(3, sOverrides.workProfileUserHandle);
1110         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
1111         Intent sendIntent = createSendImageIntent();
1112         sendIntent.setType("TestType");
1113         final UserHandle[] selectedActivityUserHandle = new UserHandle[1];
1114         sOverrides.onSafelyStartInternalCallback = result -> {
1115             selectedActivityUserHandle[0] = result.second;
1116             return true;
1117         };
1118 
1119         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
1120         waitForIdle();
1121         onView(withText(R.string.resolver_work_tab))
1122                 .perform(click());
1123         waitForIdle();
1124         onView(first(allOf(withText(workResolvedComponentInfos.get(0)
1125                 .getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
1126                 .perform(click());
1127         onView(withId(R.id.button_once))
1128                 .perform(click());
1129         waitForIdle();
1130 
1131         assertThat(selectedActivityUserHandle[0], is(activity.getAdapter().getUserHandle()));
1132     }
1133 
1134     @Test
testClonedProfilePresent_personalProfileResolverComparatorHasCorrectUsers()1135     public void testClonedProfilePresent_personalProfileResolverComparatorHasCorrectUsers()
1136             throws Exception {
1137         // enable cloneProfile
1138         markCloneProfileUserAvailable();
1139         List<ResolvedComponentInfo> resolvedComponentInfos =
1140                 createResolvedComponentsWithCloneProfileForTest(
1141                         3,
1142                         PERSONAL_USER_HANDLE,
1143                         sOverrides.cloneProfileUserHandle);
1144         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1145                 Mockito.anyBoolean(),
1146                 Mockito.anyBoolean(),
1147                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
1148         Intent sendIntent = createSendImageIntent();
1149 
1150         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
1151         waitForIdle();
1152         List<UserHandle> result = activity
1153                 .getResolverRankerServiceUserHandleList(PERSONAL_USER_HANDLE);
1154 
1155         assertTrue(result.containsAll(Lists.newArrayList(PERSONAL_USER_HANDLE,
1156                 sOverrides.cloneProfileUserHandle)));
1157     }
1158 
createSendImageIntent()1159     private Intent createSendImageIntent() {
1160         Intent sendIntent = new Intent();
1161         sendIntent.setAction(Intent.ACTION_SEND);
1162         sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
1163         sendIntent.setType("image/jpeg");
1164         return sendIntent;
1165     }
1166 
createOpenWebsiteIntent()1167     private Intent createOpenWebsiteIntent() {
1168         Intent sendIntent = new Intent();
1169         sendIntent.setAction(Intent.ACTION_VIEW);
1170         sendIntent.setData(Uri.parse("https://google.com"));
1171         return sendIntent;
1172     }
1173 
createResolvedComponentsForTest(int numberOfResults, UserHandle resolvedForUser)1174     private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults,
1175             UserHandle resolvedForUser) {
1176         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
1177         for (int i = 0; i < numberOfResults; i++) {
1178             infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
1179         }
1180         return infoList;
1181     }
1182 
createResolvedComponentsWithCloneProfileForTest( int numberOfResults, UserHandle resolvedForPersonalUser, UserHandle resolvedForClonedUser)1183     private List<ResolvedComponentInfo> createResolvedComponentsWithCloneProfileForTest(
1184             int numberOfResults,
1185             UserHandle resolvedForPersonalUser,
1186             UserHandle resolvedForClonedUser) {
1187         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
1188         for (int i = 0; i < 1; i++) {
1189             infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
1190                     resolvedForPersonalUser));
1191         }
1192         for (int i = 1; i < numberOfResults; i++) {
1193             infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
1194                     resolvedForClonedUser));
1195         }
1196         return infoList;
1197     }
1198 
createResolvedComponentsForTestWithOtherProfile( int numberOfResults, UserHandle resolvedForUser)1199     private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
1200             int numberOfResults, UserHandle resolvedForUser) {
1201         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
1202         for (int i = 0; i < numberOfResults; i++) {
1203             if (i == 0) {
1204                 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i,
1205                         resolvedForUser));
1206             } else {
1207                 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
1208             }
1209         }
1210         return infoList;
1211     }
1212 
createResolvedComponentsForTestWithOtherProfile( int numberOfResults, int userId, UserHandle resolvedForUser)1213     private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
1214             int numberOfResults, int userId, UserHandle resolvedForUser) {
1215         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
1216         for (int i = 0; i < numberOfResults; i++) {
1217             if (i == 0) {
1218                 infoList.add(
1219                         ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
1220                                 resolvedForUser));
1221             } else {
1222                 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
1223             }
1224         }
1225         return infoList;
1226     }
1227 
waitForIdle()1228     private void waitForIdle() {
1229         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
1230     }
1231 
markWorkProfileUserAvailable()1232     private void markWorkProfileUserAvailable() {
1233         ResolverWrapperActivity.sOverrides.workProfileUserHandle = UserHandle.of(10);
1234     }
1235 
markCloneProfileUserAvailable()1236     private void markCloneProfileUserAvailable() {
1237         ResolverWrapperActivity.sOverrides.cloneProfileUserHandle = UserHandle.of(11);
1238     }
1239 
setupResolverControllers( List<ResolvedComponentInfo> personalResolvedComponentInfos, List<ResolvedComponentInfo> workResolvedComponentInfos)1240     private void setupResolverControllers(
1241             List<ResolvedComponentInfo> personalResolvedComponentInfos,
1242             List<ResolvedComponentInfo> workResolvedComponentInfos) {
1243         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
1244                 Mockito.anyBoolean(),
1245                 Mockito.anyBoolean(),
1246                 Mockito.isA(List.class)))
1247                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
1248         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
1249                 Mockito.anyBoolean(),
1250                 Mockito.anyBoolean(),
1251                 Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
1252         when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
1253                 Mockito.anyBoolean(),
1254                 Mockito.anyBoolean(),
1255                 Mockito.isA(List.class),
1256                 eq(UserHandle.SYSTEM)))
1257                 .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
1258     }
1259 }
1260