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