1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.app; 18 19 import static androidx.test.espresso.Espresso.onView; 20 import static androidx.test.espresso.action.ViewActions.click; 21 import static androidx.test.espresso.assertion.ViewAssertions.matches; 22 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; 23 import static androidx.test.espresso.matcher.ViewMatchers.withId; 24 25 import static junit.framework.Assert.assertEquals; 26 import static junit.framework.Assert.assertNotNull; 27 import static junit.framework.Assert.assertNull; 28 29 import static org.mockito.ArgumentMatchers.any; 30 import static org.mockito.ArgumentMatchers.anyInt; 31 import static org.mockito.ArgumentMatchers.anyString; 32 import static org.mockito.ArgumentMatchers.eq; 33 import static org.mockito.ArgumentMatchers.nullable; 34 import static org.mockito.Mockito.mock; 35 import static org.mockito.Mockito.never; 36 import static org.mockito.Mockito.spy; 37 import static org.mockito.Mockito.verify; 38 import static org.mockito.Mockito.when; 39 40 import android.annotation.Nullable; 41 import android.content.ComponentName; 42 import android.content.Context; 43 import android.content.Intent; 44 import android.content.pm.ActivityInfo; 45 import android.content.pm.ApplicationInfo; 46 import android.content.pm.IPackageManager; 47 import android.content.pm.PackageManager; 48 import android.content.pm.ResolveInfo; 49 import android.content.pm.UserInfo; 50 import android.metrics.LogMaker; 51 import android.net.Uri; 52 import android.os.Bundle; 53 import android.os.RemoteException; 54 import android.os.UserHandle; 55 import android.os.UserManager; 56 import android.provider.Settings; 57 58 import androidx.test.InstrumentationRegistry; 59 import androidx.test.rule.ActivityTestRule; 60 import androidx.test.runner.AndroidJUnit4; 61 62 import com.android.internal.R; 63 import com.android.internal.logging.MetricsLogger; 64 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 65 66 import org.junit.After; 67 import org.junit.Before; 68 import org.junit.Rule; 69 import org.junit.Test; 70 import org.junit.runner.RunWith; 71 import org.mockito.ArgumentCaptor; 72 import org.mockito.Mock; 73 import org.mockito.MockitoAnnotations; 74 75 import java.util.ArrayList; 76 import java.util.List; 77 import java.util.concurrent.CompletableFuture; 78 import java.util.concurrent.TimeUnit; 79 80 @RunWith(AndroidJUnit4.class) 81 public class IntentForwarderActivityTest { 82 83 private static final ComponentName FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME = 84 new ComponentName( 85 "android", 86 IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE 87 ); 88 private static final ComponentName FORWARD_TO_PARENT_COMPONENT_NAME = 89 new ComponentName( 90 "android", 91 IntentForwarderActivity.FORWARD_INTENT_TO_PARENT 92 ); 93 private static final String TYPE_PLAIN_TEXT = "text/plain"; 94 95 private static UserInfo MANAGED_PROFILE_INFO = new UserInfo(); 96 97 static { 98 MANAGED_PROFILE_INFO.id = 10; 99 MANAGED_PROFILE_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE; 100 MANAGED_PROFILE_INFO.userType = UserManager.USER_TYPE_PROFILE_MANAGED; 101 } 102 103 private static UserInfo CURRENT_USER_INFO = new UserInfo(); 104 105 static { 106 CURRENT_USER_INFO.id = UserHandle.myUserId(); 107 CURRENT_USER_INFO.flags = 0; 108 } 109 110 private static IntentForwarderActivity.Injector sInjector; 111 private static ComponentName sComponentName; 112 private static String sActivityName; 113 private static String sPackageName; 114 115 @Mock 116 private IPackageManager mIPm; 117 @Mock 118 private PackageManager mPm; 119 @Mock 120 private UserManager mUserManager; 121 @Mock 122 private ApplicationInfo mApplicationInfo; 123 124 @Rule 125 public ActivityTestRule<IntentForwarderWrapperActivity> mActivityRule = 126 new ActivityTestRule<>(IntentForwarderWrapperActivity.class, true, false); 127 128 private Context mContext; 129 public static final String PHONE_NUMBER = "123-456-789"; 130 private int mDeviceProvisionedInitialValue; 131 132 @Before setup()133 public void setup() { 134 MockitoAnnotations.initMocks(this); 135 mContext = InstrumentationRegistry.getTargetContext(); 136 sInjector = spy(new TestInjector()); 137 mDeviceProvisionedInitialValue = Settings.Global.getInt(mContext.getContentResolver(), 138 Settings.Global.DEVICE_PROVISIONED, /* def= */ 0); 139 } 140 141 @After tearDown()142 public void tearDown() { 143 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 144 mDeviceProvisionedInitialValue); 145 } 146 147 @Test forwardToManagedProfile_canForward_sendIntent()148 public void forwardToManagedProfile_canForward_sendIntent() throws Exception { 149 sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; 150 sActivityName = "MyTestActivity"; 151 sPackageName = "test.package.name"; 152 153 // Intent can be forwarded. 154 when(mIPm.canForwardTo( 155 any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); 156 157 // Managed profile exists. 158 List<UserInfo> profiles = new ArrayList<>(); 159 profiles.add(CURRENT_USER_INFO); 160 profiles.add(MANAGED_PROFILE_INFO); 161 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 162 163 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class); 164 intent.setAction(Intent.ACTION_SEND); 165 intent.setType(TYPE_PLAIN_TEXT); 166 IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent); 167 168 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 169 verify(mIPm).canForwardTo(intentCaptor.capture(), eq(TYPE_PLAIN_TEXT), anyInt(), anyInt()); 170 assertEquals(Intent.ACTION_SEND, intentCaptor.getValue().getAction()); 171 172 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 173 onView(withId(R.id.icon)).check(matches(isDisplayed())); 174 onView(withId(R.id.open_cross_profile)).check(matches(isDisplayed())); 175 onView(withId(R.id.use_same_profile_browser)).check(matches(isDisplayed())); 176 onView(withId(R.id.button_open)).perform(click()); 177 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 178 179 assertNotNull(activity.mStartActivityIntent); 180 assertEquals(Intent.ACTION_SEND, activity.mStartActivityIntent.getAction()); 181 assertNull(activity.mStartActivityIntent.getPackage()); 182 assertNull(activity.mStartActivityIntent.getComponent()); 183 assertEquals(CURRENT_USER_INFO.id, activity.mStartActivityIntent.getContentUserHint()); 184 185 assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn); 186 } 187 188 @Test forwardToManagedProfile_cannotForward_sendIntent()189 public void forwardToManagedProfile_cannotForward_sendIntent() throws Exception { 190 sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; 191 192 // Intent cannot be forwarded. 193 when(mIPm.canForwardTo( 194 any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(false); 195 196 // Managed profile exists. 197 List<UserInfo> profiles = new ArrayList<>(); 198 profiles.add(CURRENT_USER_INFO); 199 profiles.add(MANAGED_PROFILE_INFO); 200 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 201 202 // Create ACTION_SEND intent. 203 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class); 204 intent.setAction(Intent.ACTION_SEND); 205 IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent); 206 207 assertNull(activity.mStartActivityIntent); 208 } 209 210 @Test forwardToManagedProfile_noManagedProfile_sendIntent()211 public void forwardToManagedProfile_noManagedProfile_sendIntent() throws Exception { 212 sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; 213 214 // Intent can be forwarded. 215 when(mIPm.canForwardTo( 216 any(Intent.class), anyString(), anyInt(), anyInt())).thenReturn(true); 217 218 // Managed profile does not exist. 219 List<UserInfo> profiles = new ArrayList<>(); 220 profiles.add(CURRENT_USER_INFO); 221 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 222 223 // Create ACTION_SEND intent. 224 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class); 225 intent.setAction(Intent.ACTION_SEND); 226 IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent); 227 228 assertNull(activity.mStartActivityIntent); 229 } 230 231 @Test launchInSameProfile_chooserIntent()232 public void launchInSameProfile_chooserIntent() { 233 sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; 234 235 // Manage profile exists. 236 List<UserInfo> profiles = new ArrayList<>(); 237 profiles.add(CURRENT_USER_INFO); 238 profiles.add(MANAGED_PROFILE_INFO); 239 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 240 241 // Create chooser Intent 242 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class); 243 intent.setAction(Intent.ACTION_CHOOSER); 244 Intent sendIntent = new Intent(Intent.ACTION_SEND); 245 sendIntent.setComponent(new ComponentName("xx", "yyy")); 246 sendIntent.setType(TYPE_PLAIN_TEXT); 247 intent.putExtra(Intent.EXTRA_INTENT, sendIntent); 248 IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent); 249 250 assertNotNull(activity.mStartActivityIntent); 251 assertEquals(Intent.ACTION_CHOOSER, activity.mStartActivityIntent.getAction()); 252 assertNull(activity.mStartActivityIntent.getPackage()); 253 assertNull(activity.mStartActivityIntent.getComponent()); 254 255 Intent innerIntent = activity.mStartActivityIntent.getParcelableExtra(Intent.EXTRA_INTENT); 256 assertNotNull(innerIntent); 257 assertEquals(Intent.ACTION_SEND, innerIntent.getAction()); 258 assertNull(innerIntent.getComponent()); 259 assertNull(innerIntent.getPackage()); 260 assertEquals(UserHandle.USER_CURRENT, innerIntent.getContentUserHint()); 261 262 assertEquals(CURRENT_USER_INFO.id, activity.mUserIdActivityLaunchedIn); 263 } 264 265 @Test forwardToManagedProfile_canForward_selectorIntent()266 public void forwardToManagedProfile_canForward_selectorIntent() throws Exception { 267 sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; 268 sActivityName = "MyTestActivity"; 269 sPackageName = "test.package.name"; 270 271 // Intent can be forwarded. 272 when(mIPm.canForwardTo( 273 any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); 274 275 // Manage profile exists. 276 List<UserInfo> profiles = new ArrayList<>(); 277 profiles.add(CURRENT_USER_INFO); 278 profiles.add(MANAGED_PROFILE_INFO); 279 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 280 281 // Create selector intent. 282 Intent intent = Intent.makeMainSelectorActivity( 283 Intent.ACTION_VIEW, Intent.CATEGORY_BROWSABLE); 284 285 IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent); 286 287 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 288 verify(mIPm).canForwardTo( 289 intentCaptor.capture(), nullable(String.class), anyInt(), anyInt()); 290 assertEquals(Intent.ACTION_VIEW, intentCaptor.getValue().getAction()); 291 292 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 293 onView(withId(R.id.icon)).check(matches(isDisplayed())); 294 onView(withId(R.id.open_cross_profile)).check(matches(isDisplayed())); 295 onView(withId(R.id.use_same_profile_browser)).check(matches(isDisplayed())); 296 onView(withId(R.id.button_open)).perform(click()); 297 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 298 299 assertNotNull(activity.mStartActivityIntent); 300 assertEquals(Intent.ACTION_MAIN, activity.mStartActivityIntent.getAction()); 301 assertNull(activity.mStartActivityIntent.getPackage()); 302 assertNull(activity.mStartActivityIntent.getComponent()); 303 assertEquals(CURRENT_USER_INFO.id, activity.mStartActivityIntent.getContentUserHint()); 304 305 Intent innerIntent = activity.mStartActivityIntent.getSelector(); 306 assertNotNull(innerIntent); 307 assertEquals(Intent.ACTION_VIEW, innerIntent.getAction()); 308 assertNull(innerIntent.getComponent()); 309 assertNull(innerIntent.getPackage()); 310 311 assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn); 312 } 313 314 @Test shouldSkipDisclosure_notWhitelisted()315 public void shouldSkipDisclosure_notWhitelisted() throws RemoteException { 316 setupShouldSkipDisclosureTest(); 317 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 318 .setAction(Intent.ACTION_SEND) 319 .setType(TYPE_PLAIN_TEXT); 320 321 mActivityRule.launchActivity(intent); 322 323 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 324 verify(sInjector).showToast(anyString(), anyInt()); 325 } 326 327 @Test shouldSkipDisclosure_withResolverActivity()328 public void shouldSkipDisclosure_withResolverActivity() throws RemoteException { 329 setupShouldSkipDisclosureTest(); 330 sActivityName = ResolverActivity.class.getName(); 331 sPackageName = "android"; 332 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 333 .setAction(Intent.ACTION_SEND) 334 .setType(TYPE_PLAIN_TEXT); 335 336 mActivityRule.launchActivity(intent); 337 338 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 339 verify(sInjector, never()).showToast(anyString(), anyInt()); 340 } 341 342 @Test shouldSkipDisclosure_callIntent_call()343 public void shouldSkipDisclosure_callIntent_call() throws RemoteException { 344 setupShouldSkipDisclosureTest(); 345 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 346 .setAction(Intent.ACTION_CALL); 347 348 mActivityRule.launchActivity(intent); 349 350 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 351 verify(sInjector, never()).showToast(anyString(), anyInt()); 352 } 353 354 @Test shouldSkipDisclosure_callIntent_callPrivileged()355 public void shouldSkipDisclosure_callIntent_callPrivileged() throws RemoteException { 356 setupShouldSkipDisclosureTest(); 357 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 358 .setAction(Intent.ACTION_CALL_PRIVILEGED); 359 360 mActivityRule.launchActivity(intent); 361 362 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 363 verify(sInjector, never()).showToast(anyString(), anyInt()); 364 } 365 366 @Test shouldSkipDisclosure_callIntent_callEmergency()367 public void shouldSkipDisclosure_callIntent_callEmergency() throws RemoteException { 368 setupShouldSkipDisclosureTest(); 369 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 370 .setAction(Intent.ACTION_CALL_EMERGENCY); 371 372 mActivityRule.launchActivity(intent); 373 374 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 375 verify(sInjector, never()).showToast(anyString(), anyInt()); 376 } 377 378 @Test shouldSkipDisclosure_callIntent_dial()379 public void shouldSkipDisclosure_callIntent_dial() throws RemoteException { 380 setupShouldSkipDisclosureTest(); 381 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 382 .setAction(Intent.ACTION_DIAL); 383 384 mActivityRule.launchActivity(intent); 385 386 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 387 verify(sInjector, never()).showToast(anyString(), anyInt()); 388 } 389 390 @Test shouldSkipDisclosure_callIntent_notCallOrDial()391 public void shouldSkipDisclosure_callIntent_notCallOrDial() throws RemoteException { 392 setupShouldSkipDisclosureTest(); 393 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 394 .setAction(Intent.ACTION_ALARM_CHANGED); 395 396 mActivityRule.launchActivity(intent); 397 398 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 399 verify(sInjector).showToast(anyString(), anyInt()); 400 } 401 402 @Test shouldSkipDisclosure_callIntent_actionViewTel()403 public void shouldSkipDisclosure_callIntent_actionViewTel() throws RemoteException { 404 setupShouldSkipDisclosureTest(); 405 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 406 .setAction(Intent.ACTION_VIEW) 407 .addCategory(Intent.CATEGORY_BROWSABLE) 408 .setData(Uri.fromParts("tel", PHONE_NUMBER, null)); 409 410 mActivityRule.launchActivity(intent); 411 412 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 413 verify(sInjector, never()).showToast(anyString(), anyInt()); 414 } 415 416 @Test shouldSkipDisclosure_textMessageIntent_sms()417 public void shouldSkipDisclosure_textMessageIntent_sms() throws RemoteException { 418 setupShouldSkipDisclosureTest(); 419 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 420 .setAction(Intent.ACTION_SENDTO) 421 .setData(Uri.fromParts("sms", PHONE_NUMBER, null)); 422 423 mActivityRule.launchActivity(intent); 424 425 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 426 verify(sInjector, never()).showToast(anyString(), anyInt()); 427 } 428 429 @Test shouldSkipDisclosure_textMessageIntent_smsto()430 public void shouldSkipDisclosure_textMessageIntent_smsto() throws RemoteException { 431 setupShouldSkipDisclosureTest(); 432 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 433 .setAction(Intent.ACTION_SENDTO) 434 .setData(Uri.fromParts("smsto", PHONE_NUMBER, null)); 435 436 mActivityRule.launchActivity(intent); 437 438 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 439 verify(sInjector, never()).showToast(anyString(), anyInt()); 440 } 441 442 @Test shouldSkipDisclosure_textMessageIntent_mms()443 public void shouldSkipDisclosure_textMessageIntent_mms() throws RemoteException { 444 setupShouldSkipDisclosureTest(); 445 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 446 .setAction(Intent.ACTION_SENDTO) 447 .setData(Uri.fromParts("mms", PHONE_NUMBER, null)); 448 449 mActivityRule.launchActivity(intent); 450 451 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 452 verify(sInjector, never()).showToast(anyString(), anyInt()); 453 } 454 455 @Test shouldSkipDisclosure_textMessageIntent_mmsto()456 public void shouldSkipDisclosure_textMessageIntent_mmsto() throws RemoteException { 457 setupShouldSkipDisclosureTest(); 458 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 459 .setAction(Intent.ACTION_SENDTO) 460 .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null)); 461 462 mActivityRule.launchActivity(intent); 463 464 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 465 verify(sInjector, never()).showToast(anyString(), anyInt()); 466 } 467 468 @Test shouldSkipDisclosure_textMessageIntent_actionViewSms()469 public void shouldSkipDisclosure_textMessageIntent_actionViewSms() throws RemoteException { 470 setupShouldSkipDisclosureTest(); 471 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 472 .setAction(Intent.ACTION_VIEW) 473 .addCategory(Intent.CATEGORY_BROWSABLE) 474 .setData(Uri.fromParts("sms", PHONE_NUMBER, null)); 475 476 mActivityRule.launchActivity(intent); 477 478 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 479 verify(sInjector, never()).showToast(anyString(), anyInt()); 480 } 481 482 @Test shouldSkipDisclosure_textMessageIntent_actionViewSmsto()483 public void shouldSkipDisclosure_textMessageIntent_actionViewSmsto() throws RemoteException { 484 setupShouldSkipDisclosureTest(); 485 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 486 .setAction(Intent.ACTION_VIEW) 487 .addCategory(Intent.CATEGORY_BROWSABLE) 488 .setData(Uri.fromParts("smsto", PHONE_NUMBER, null)); 489 490 mActivityRule.launchActivity(intent); 491 492 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 493 verify(sInjector, never()).showToast(anyString(), anyInt()); 494 } 495 496 @Test shouldSkipDisclosure_textMessageIntent_actionViewMms()497 public void shouldSkipDisclosure_textMessageIntent_actionViewMms() throws RemoteException { 498 setupShouldSkipDisclosureTest(); 499 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 500 .setAction(Intent.ACTION_VIEW) 501 .addCategory(Intent.CATEGORY_BROWSABLE) 502 .setData(Uri.fromParts("mms", PHONE_NUMBER, null)); 503 504 mActivityRule.launchActivity(intent); 505 506 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 507 verify(sInjector, never()).showToast(anyString(), anyInt()); 508 } 509 510 @Test shouldSkipDisclosure_textMessageIntent_actionViewMmsto()511 public void shouldSkipDisclosure_textMessageIntent_actionViewMmsto() throws RemoteException { 512 setupShouldSkipDisclosureTest(); 513 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 514 .setAction(Intent.ACTION_VIEW) 515 .addCategory(Intent.CATEGORY_BROWSABLE) 516 .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null)); 517 518 mActivityRule.launchActivity(intent); 519 520 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 521 verify(sInjector, never()).showToast(anyString(), anyInt()); 522 } 523 524 @Test shouldSkipDisclosure_textMessageIntent_invalidUri()525 public void shouldSkipDisclosure_textMessageIntent_invalidUri() throws RemoteException { 526 setupShouldSkipDisclosureTest(); 527 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 528 .setAction(Intent.ACTION_SENDTO) 529 .setData(Uri.fromParts("invalid", PHONE_NUMBER, null)); 530 531 mActivityRule.launchActivity(intent); 532 533 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 534 verify(sInjector).showToast(anyString(), anyInt()); 535 } 536 537 @Test shouldSkipDisclosure_viewBrowsableIntent_invalidUri()538 public void shouldSkipDisclosure_viewBrowsableIntent_invalidUri() throws RemoteException { 539 setupShouldSkipDisclosureTest(); 540 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 541 .setAction(Intent.ACTION_VIEW) 542 .addCategory(Intent.CATEGORY_BROWSABLE) 543 .setData(Uri.fromParts("invalid", PHONE_NUMBER, null)); 544 545 mActivityRule.launchActivity(intent); 546 547 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 548 verify(sInjector).showToast(anyString(), anyInt()); 549 } 550 551 @Test shouldSkipDisclosure_viewBrowsableIntent_normalUrl()552 public void shouldSkipDisclosure_viewBrowsableIntent_normalUrl() throws RemoteException { 553 setupShouldSkipDisclosureTest(); 554 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 555 .setAction(Intent.ACTION_VIEW) 556 .addCategory(Intent.CATEGORY_BROWSABLE) 557 .setData(Uri.fromParts("http", "apache.org", null)); 558 559 mActivityRule.launchActivity(intent); 560 561 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 562 verify(sInjector).showToast(anyString(), anyInt()); 563 } 564 565 @Test shouldSkipDisclosure_duringDeviceSetup()566 public void shouldSkipDisclosure_duringDeviceSetup() throws RemoteException { 567 setupShouldSkipDisclosureTest(); 568 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 569 /* value= */ 0); 570 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) 571 .setAction(Intent.ACTION_VIEW) 572 .addCategory(Intent.CATEGORY_BROWSABLE) 573 .setData(Uri.fromParts("http", "apache.org", null)); 574 575 mActivityRule.launchActivity(intent); 576 577 verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); 578 verify(sInjector, never()).showToast(anyString(), anyInt()); 579 } 580 581 @Test forwardToManagedProfile_LoggingTest()582 public void forwardToManagedProfile_LoggingTest() throws Exception { 583 sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; 584 585 // Intent can be forwarded. 586 when(mIPm.canForwardTo( 587 any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); 588 589 // Managed profile exists. 590 List<UserInfo> profiles = new ArrayList<>(); 591 profiles.add(CURRENT_USER_INFO); 592 profiles.add(MANAGED_PROFILE_INFO); 593 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 594 595 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class); 596 intent.setAction(Intent.ACTION_SEND); 597 intent.setType(TYPE_PLAIN_TEXT); 598 IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent); 599 600 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); 601 verify(activity.getMetricsLogger()).write(logMakerCaptor.capture()); 602 assertEquals(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE, 603 logMakerCaptor.getValue().getCategory()); 604 assertEquals(MetricsEvent.MANAGED_PROFILE, 605 logMakerCaptor.getValue().getSubtype()); 606 } 607 608 @Test forwardToParent_LoggingTest()609 public void forwardToParent_LoggingTest() throws Exception { 610 sComponentName = FORWARD_TO_PARENT_COMPONENT_NAME; 611 612 // Intent can be forwarded. 613 when(mIPm.canForwardTo( 614 any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); 615 616 // Managed profile exists. 617 List<UserInfo> profiles = new ArrayList<>(); 618 profiles.add(CURRENT_USER_INFO); 619 profiles.add(MANAGED_PROFILE_INFO); 620 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 621 622 Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class); 623 intent.setAction(Intent.ACTION_SEND); 624 intent.setType(TYPE_PLAIN_TEXT); 625 IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent); 626 627 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class); 628 verify(activity.getMetricsLogger()).write(logMakerCaptor.capture()); 629 assertEquals(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE, 630 logMakerCaptor.getValue().getCategory()); 631 assertEquals(MetricsEvent.PARENT_PROFILE, 632 logMakerCaptor.getValue().getSubtype()); 633 } 634 setupShouldSkipDisclosureTest()635 private void setupShouldSkipDisclosureTest() throws RemoteException { 636 sComponentName = FORWARD_TO_PARENT_COMPONENT_NAME; 637 sActivityName = "MyTestActivity"; 638 sPackageName = "test.package.name"; 639 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 640 /* value= */ 1); 641 when(mApplicationInfo.isSystemApp()).thenReturn(true); 642 // Managed profile exists. 643 List<UserInfo> profiles = new ArrayList<>(); 644 profiles.add(CURRENT_USER_INFO); 645 profiles.add(MANAGED_PROFILE_INFO); 646 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 647 when(mUserManager.getProfileParent(anyInt())).thenReturn(CURRENT_USER_INFO); 648 // Intent can be forwarded. 649 when(mIPm.canForwardTo( 650 any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); 651 } 652 653 public static class IntentForwarderWrapperActivity extends IntentForwarderActivity { 654 655 private Intent mStartActivityIntent; 656 private int mUserIdActivityLaunchedIn; 657 private MetricsLogger mMetricsLogger = mock(MetricsLogger.class); 658 659 @Override onCreate(@ullable Bundle savedInstanceState)660 public void onCreate(@Nullable Bundle savedInstanceState) { 661 getIntent().setComponent(sComponentName); 662 super.onCreate(savedInstanceState); 663 try { 664 mExecutorService.awaitTermination(/* timeout= */ 30, TimeUnit.SECONDS); 665 } catch (InterruptedException e) { 666 e.printStackTrace(); 667 } 668 } 669 670 @Override createInjector()671 protected Injector createInjector() { 672 return sInjector; 673 } 674 675 @Override startActivityAsCaller(Intent intent, @Nullable Bundle options, boolean ignoreTargetSecurity, int userId)676 public void startActivityAsCaller(Intent intent, @Nullable Bundle options, 677 boolean ignoreTargetSecurity, int userId) { 678 mStartActivityIntent = intent; 679 mUserIdActivityLaunchedIn = userId; 680 } 681 682 @Override createContextAsUser(UserHandle user, int flags)683 public Context createContextAsUser(UserHandle user, int flags) { 684 return this; 685 } 686 687 @Override getMetricsLogger()688 protected MetricsLogger getMetricsLogger() { 689 return mMetricsLogger; 690 } 691 } 692 693 public class TestInjector implements IntentForwarderActivity.Injector { 694 695 @Override getIPackageManager()696 public IPackageManager getIPackageManager() { 697 return mIPm; 698 } 699 700 @Override getUserManager()701 public UserManager getUserManager() { 702 return mUserManager; 703 } 704 705 @Override getPackageManager()706 public PackageManager getPackageManager() { 707 return mPm; 708 } 709 710 @Override resolveActivityAsUser( Intent intent, int flags, int userId)711 public CompletableFuture<ResolveInfo> resolveActivityAsUser( 712 Intent intent, int flags, int userId) { 713 ActivityInfo activityInfo = new ActivityInfo(); 714 activityInfo.packageName = sPackageName; 715 activityInfo.name = sActivityName; 716 activityInfo.applicationInfo = mApplicationInfo; 717 718 ResolveInfo resolveInfo = new ResolveInfo(); 719 resolveInfo.activityInfo = activityInfo; 720 721 return CompletableFuture.completedFuture(resolveInfo); 722 } 723 724 @Override showToast(String message, int duration)725 public void showToast(String message, int duration) {} 726 } 727 } 728