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