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