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