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