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