Loading core/java/com/android/internal/app/IntentForwarderActivity.java +60 −20 Original line number Diff line number Diff line Loading @@ -16,14 +16,21 @@ package com.android.internal.app; import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; import android.annotation.Nullable; import android.annotation.StringRes; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.admin.DevicePolicyManager; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.os.Bundle; import android.os.RemoteException; Loading @@ -31,12 +38,11 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import java.util.Arrays; import java.util.HashSet; import java.util.List; import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; import java.util.Set; /** * This is used in conjunction with Loading @@ -44,7 +50,6 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; * be passed in and out of a managed profile. */ public class IntentForwarderActivity extends Activity { public static String TAG = "IntentForwarderActivity"; public static String FORWARD_INTENT_TO_PARENT Loading @@ -53,6 +58,9 @@ public class IntentForwarderActivity extends Activity { public static String FORWARD_INTENT_TO_MANAGED_PROFILE = "com.android.internal.app.ForwardIntentToManagedProfile"; private static final Set<String> ALLOWED_TEXT_MESSAGE_SCHEME = new HashSet<>(Arrays.asList("sms", "smsto", "mms", "mmsto")); private Injector mInjector; @Override Loading Loading @@ -93,19 +101,8 @@ public class IntentForwarderActivity extends Activity { newIntent.prepareToLeaveUser(callingUserId); } final android.content.pm.ResolveInfo ri = mInjector.getPackageManager().resolveActivityAsUser( newIntent, MATCH_DEFAULT_ONLY, final ResolveInfo ri = mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, targetUserId); // Don't show the disclosure if next activity is ResolverActivity or ChooserActivity // as those will already have shown work / personal as neccesary etc. final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null || !"android".equals(ri.activityInfo.packageName) || !(ResolverActivity.class.getName().equals(ri.activityInfo.name) || ChooserActivity.class.getName().equals(ri.activityInfo.name)); try { startActivityAsCaller(newIntent, null, false, targetUserId); } catch (RuntimeException e) { Loading @@ -124,8 +121,8 @@ public class IntentForwarderActivity extends Activity { + ActivityThread.currentProcessName(), e); } if (shouldShowDisclosure) { Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show(); if (shouldShowDisclosure(ri, intentReceived)) { mInjector.showToast(userMessageId, Toast.LENGTH_LONG); } } else { Slog.wtf(TAG, "the intent: " + intentReceived + " cannot be forwarded from user " Loading @@ -134,6 +131,35 @@ public class IntentForwarderActivity extends Activity { finish(); } private boolean shouldShowDisclosure(@Nullable ResolveInfo ri, Intent intent) { if (ri == null || ri.activityInfo == null) { return true; } if (ri.activityInfo.applicationInfo.isSystemApp() && (isDialerIntent(intent) || isTextMessageIntent(intent))) { return false; } return !isTargetResolverOrChooserActivity(ri.activityInfo); } private boolean isTextMessageIntent(Intent intent) { return Intent.ACTION_SENDTO.equals(intent.getAction()) && intent.getData() != null && ALLOWED_TEXT_MESSAGE_SCHEME.contains(intent.getData().getScheme()); } private boolean isDialerIntent(Intent intent) { return Intent.ACTION_DIAL.equals(intent.getAction()) || Intent.ACTION_CALL.equals(intent.getAction()); } private boolean isTargetResolverOrChooserActivity(ActivityInfo activityInfo) { if (!"android".equals(activityInfo.packageName)) { return false; } return ResolverActivity.class.getName().equals(activityInfo.name) || ChooserActivity.class.getName().equals(activityInfo.name); } /** * Check whether the intent can be forwarded to target user. Return the intent used for * forwarding if it can be forwarded, {@code null} otherwise. Loading Loading @@ -241,6 +267,16 @@ public class IntentForwarderActivity extends Activity { public PackageManager getPackageManager() { return IntentForwarderActivity.this.getPackageManager(); } @Override public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { return getPackageManager().resolveActivityAsUser(intent, flags, userId); } @Override public void showToast(int messageId, int duration) { Toast.makeText(IntentForwarderActivity.this, getString(messageId), duration).show(); } } public interface Injector { Loading @@ -249,5 +285,9 @@ public class IntentForwarderActivity extends Activity { UserManager getUserManager(); PackageManager getPackageManager(); ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId); void showToast(@StringRes int messageId, int duration); } } core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java +186 −19 Original line number Diff line number Diff line Loading @@ -16,46 +16,50 @@ package com.android.internal.app; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.support.test.InstrumentationRegistry; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.util.Log; import java.util.ArrayList; import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(AndroidJUnit4.class) public class IntentForwarderActivityTest { private static final ComponentName FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME = new ComponentName( "android", Loading @@ -77,22 +81,26 @@ public class IntentForwarderActivityTest { private static IntentForwarderActivity.Injector sInjector; private static ComponentName sComponentName; private static String sActivityName; private static String sPackageName; @Mock private IPackageManager mIPm; @Mock private PackageManager mPm; @Mock private UserManager mUserManager; @Mock private ApplicationInfo mApplicationInfo; @Rule public ActivityTestRule<IntentForwarderWrapperActivity> mActivityRule = new ActivityTestRule<>(IntentForwarderWrapperActivity.class, true, false); private Context mContext; public static final String PHONE_NUMBER = "123-456-789"; @Before public void setup() { MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getTargetContext(); sInjector = new TestInjector(); sInjector = spy(new TestInjector()); } @Test Loading Loading @@ -252,6 +260,149 @@ public class IntentForwarderActivityTest { assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn); } @Test public void shouldSkipDisclosure_notWhitelisted() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SEND) .setType(TYPE_PLAIN_TEXT); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_withResolverActivity() throws RemoteException { setupShouldSkipDisclosureTest(); sActivityName = ResolverActivity.class.getName(); sPackageName = "android"; Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SEND) .setType(TYPE_PLAIN_TEXT); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_callIntent_call() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_CALL); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_callIntent_dial() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_DIAL); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_callIntent_notCallOrDial() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_ALARM_CHANGED); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_sms() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("sms", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_smsto() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("smsto", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_mms() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("mms", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_mmsto() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_invalidUri() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("invalid", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector).showToast(anyInt(), anyInt()); } private void setupShouldSkipDisclosureTest() throws RemoteException { sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; sActivityName = "MyTestActivity"; sPackageName = "test.package.name"; when(mApplicationInfo.isSystemApp()).thenReturn(true); // Managed profile exists. List<UserInfo> profiles = new ArrayList<>(); profiles.add(CURRENT_USER_INFO); profiles.add(MANAGED_PROFILE_INFO); when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); // Intent can be forwarded. when(mIPm.canForwardTo( any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); } public static class IntentForwarderWrapperActivity extends IntentForwarderActivity { private Intent mStartActivityIntent; Loading @@ -276,7 +427,7 @@ public class IntentForwarderActivityTest { } } class TestInjector implements IntentForwarderActivity.Injector { public class TestInjector implements IntentForwarderActivity.Injector { @Override public IPackageManager getIPackageManager() { Loading @@ -292,5 +443,21 @@ public class IntentForwarderActivityTest { public PackageManager getPackageManager() { return mPm; } @Override public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { ActivityInfo activityInfo = new ActivityInfo(); activityInfo.packageName = sPackageName; activityInfo.name = sActivityName; activityInfo.applicationInfo = mApplicationInfo; ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = activityInfo; return resolveInfo; } @Override public void showToast(int messageId, int duration) {} } } No newline at end of file Loading
core/java/com/android/internal/app/IntentForwarderActivity.java +60 −20 Original line number Diff line number Diff line Loading @@ -16,14 +16,21 @@ package com.android.internal.app; import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; import android.annotation.Nullable; import android.annotation.StringRes; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.admin.DevicePolicyManager; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.os.Bundle; import android.os.RemoteException; Loading @@ -31,12 +38,11 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import java.util.Arrays; import java.util.HashSet; import java.util.List; import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; import java.util.Set; /** * This is used in conjunction with Loading @@ -44,7 +50,6 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; * be passed in and out of a managed profile. */ public class IntentForwarderActivity extends Activity { public static String TAG = "IntentForwarderActivity"; public static String FORWARD_INTENT_TO_PARENT Loading @@ -53,6 +58,9 @@ public class IntentForwarderActivity extends Activity { public static String FORWARD_INTENT_TO_MANAGED_PROFILE = "com.android.internal.app.ForwardIntentToManagedProfile"; private static final Set<String> ALLOWED_TEXT_MESSAGE_SCHEME = new HashSet<>(Arrays.asList("sms", "smsto", "mms", "mmsto")); private Injector mInjector; @Override Loading Loading @@ -93,19 +101,8 @@ public class IntentForwarderActivity extends Activity { newIntent.prepareToLeaveUser(callingUserId); } final android.content.pm.ResolveInfo ri = mInjector.getPackageManager().resolveActivityAsUser( newIntent, MATCH_DEFAULT_ONLY, final ResolveInfo ri = mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, targetUserId); // Don't show the disclosure if next activity is ResolverActivity or ChooserActivity // as those will already have shown work / personal as neccesary etc. final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null || !"android".equals(ri.activityInfo.packageName) || !(ResolverActivity.class.getName().equals(ri.activityInfo.name) || ChooserActivity.class.getName().equals(ri.activityInfo.name)); try { startActivityAsCaller(newIntent, null, false, targetUserId); } catch (RuntimeException e) { Loading @@ -124,8 +121,8 @@ public class IntentForwarderActivity extends Activity { + ActivityThread.currentProcessName(), e); } if (shouldShowDisclosure) { Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show(); if (shouldShowDisclosure(ri, intentReceived)) { mInjector.showToast(userMessageId, Toast.LENGTH_LONG); } } else { Slog.wtf(TAG, "the intent: " + intentReceived + " cannot be forwarded from user " Loading @@ -134,6 +131,35 @@ public class IntentForwarderActivity extends Activity { finish(); } private boolean shouldShowDisclosure(@Nullable ResolveInfo ri, Intent intent) { if (ri == null || ri.activityInfo == null) { return true; } if (ri.activityInfo.applicationInfo.isSystemApp() && (isDialerIntent(intent) || isTextMessageIntent(intent))) { return false; } return !isTargetResolverOrChooserActivity(ri.activityInfo); } private boolean isTextMessageIntent(Intent intent) { return Intent.ACTION_SENDTO.equals(intent.getAction()) && intent.getData() != null && ALLOWED_TEXT_MESSAGE_SCHEME.contains(intent.getData().getScheme()); } private boolean isDialerIntent(Intent intent) { return Intent.ACTION_DIAL.equals(intent.getAction()) || Intent.ACTION_CALL.equals(intent.getAction()); } private boolean isTargetResolverOrChooserActivity(ActivityInfo activityInfo) { if (!"android".equals(activityInfo.packageName)) { return false; } return ResolverActivity.class.getName().equals(activityInfo.name) || ChooserActivity.class.getName().equals(activityInfo.name); } /** * Check whether the intent can be forwarded to target user. Return the intent used for * forwarding if it can be forwarded, {@code null} otherwise. Loading Loading @@ -241,6 +267,16 @@ public class IntentForwarderActivity extends Activity { public PackageManager getPackageManager() { return IntentForwarderActivity.this.getPackageManager(); } @Override public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { return getPackageManager().resolveActivityAsUser(intent, flags, userId); } @Override public void showToast(int messageId, int duration) { Toast.makeText(IntentForwarderActivity.this, getString(messageId), duration).show(); } } public interface Injector { Loading @@ -249,5 +285,9 @@ public class IntentForwarderActivity extends Activity { UserManager getUserManager(); PackageManager getPackageManager(); ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId); void showToast(@StringRes int messageId, int duration); } }
core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java +186 −19 Original line number Diff line number Diff line Loading @@ -16,46 +16,50 @@ package com.android.internal.app; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.support.test.InstrumentationRegistry; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.util.Log; import java.util.ArrayList; import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(AndroidJUnit4.class) public class IntentForwarderActivityTest { private static final ComponentName FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME = new ComponentName( "android", Loading @@ -77,22 +81,26 @@ public class IntentForwarderActivityTest { private static IntentForwarderActivity.Injector sInjector; private static ComponentName sComponentName; private static String sActivityName; private static String sPackageName; @Mock private IPackageManager mIPm; @Mock private PackageManager mPm; @Mock private UserManager mUserManager; @Mock private ApplicationInfo mApplicationInfo; @Rule public ActivityTestRule<IntentForwarderWrapperActivity> mActivityRule = new ActivityTestRule<>(IntentForwarderWrapperActivity.class, true, false); private Context mContext; public static final String PHONE_NUMBER = "123-456-789"; @Before public void setup() { MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getTargetContext(); sInjector = new TestInjector(); sInjector = spy(new TestInjector()); } @Test Loading Loading @@ -252,6 +260,149 @@ public class IntentForwarderActivityTest { assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn); } @Test public void shouldSkipDisclosure_notWhitelisted() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SEND) .setType(TYPE_PLAIN_TEXT); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_withResolverActivity() throws RemoteException { setupShouldSkipDisclosureTest(); sActivityName = ResolverActivity.class.getName(); sPackageName = "android"; Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SEND) .setType(TYPE_PLAIN_TEXT); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_callIntent_call() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_CALL); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_callIntent_dial() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_DIAL); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_callIntent_notCallOrDial() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_ALARM_CHANGED); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_sms() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("sms", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_smsto() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("smsto", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_mms() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("mms", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_mmsto() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector, never()).showToast(anyInt(), anyInt()); } @Test public void shouldSkipDisclosure_textMessageIntent_invalidUri() throws RemoteException { setupShouldSkipDisclosureTest(); Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) .setAction(Intent.ACTION_SENDTO) .setData(Uri.fromParts("invalid", PHONE_NUMBER, null)); mActivityRule.launchActivity(intent); verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); verify(sInjector).showToast(anyInt(), anyInt()); } private void setupShouldSkipDisclosureTest() throws RemoteException { sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; sActivityName = "MyTestActivity"; sPackageName = "test.package.name"; when(mApplicationInfo.isSystemApp()).thenReturn(true); // Managed profile exists. List<UserInfo> profiles = new ArrayList<>(); profiles.add(CURRENT_USER_INFO); profiles.add(MANAGED_PROFILE_INFO); when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); // Intent can be forwarded. when(mIPm.canForwardTo( any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); } public static class IntentForwarderWrapperActivity extends IntentForwarderActivity { private Intent mStartActivityIntent; Loading @@ -276,7 +427,7 @@ public class IntentForwarderActivityTest { } } class TestInjector implements IntentForwarderActivity.Injector { public class TestInjector implements IntentForwarderActivity.Injector { @Override public IPackageManager getIPackageManager() { Loading @@ -292,5 +443,21 @@ public class IntentForwarderActivityTest { public PackageManager getPackageManager() { return mPm; } @Override public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { ActivityInfo activityInfo = new ActivityInfo(); activityInfo.packageName = sPackageName; activityInfo.name = sActivityName; activityInfo.applicationInfo = mApplicationInfo; ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = activityInfo; return resolveInfo; } @Override public void showToast(int messageId, int duration) {} } } No newline at end of file