1 /* 2 * Copyright 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.server.am; 18 19 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED; 20 21 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertTrue; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.ArgumentMatchers.nullable; 28 import static org.mockito.Mockito.when; 29 30 import android.app.KeyguardManager; 31 import android.app.admin.DevicePolicyManagerInternal; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.pm.ActivityInfo; 35 import android.content.pm.ApplicationInfo; 36 import android.content.pm.PackageManagerInternal; 37 import android.content.pm.UserInfo; 38 import android.os.UserHandle; 39 import android.os.UserManager; 40 import android.support.test.filters.SmallTest; 41 import android.testing.DexmakerShareClassLoaderRule; 42 43 import com.android.internal.app.SuspendedAppActivity; 44 import com.android.internal.app.UnlaunchableAppActivity; 45 import com.android.server.LocalServices; 46 import com.android.server.pm.PackageManagerService; 47 48 import org.junit.Before; 49 import org.junit.Rule; 50 import org.junit.Test; 51 import org.mockito.Mock; 52 import org.mockito.MockitoAnnotations; 53 54 /** 55 * Unit tests for {@link ActivityStartInterceptorTest}. 56 * 57 * Build/Install/Run: 58 * bit FrameworksServicesTests:com.android.server.am.ActivityStartInterceptorTest 59 */ 60 @SmallTest 61 public class ActivityStartInterceptorTest { 62 private static final int TEST_USER_ID = 1; 63 private static final int TEST_REAL_CALLING_UID = 2; 64 private static final int TEST_REAL_CALLING_PID = 3; 65 private static final String TEST_CALLING_PACKAGE = "com.test.caller"; 66 private static final int TEST_START_FLAGS = 4; 67 private static final Intent ADMIN_SUPPORT_INTENT = 68 new Intent("com.test.ADMIN_SUPPORT"); 69 private static final Intent CONFIRM_CREDENTIALS_INTENT = 70 new Intent("com.test.CONFIRM_CREDENTIALS"); 71 private static final UserInfo PARENT_USER_INFO = new UserInfo(0 /* userId */, "parent", 72 0 /* flags */); 73 private static final String TEST_PACKAGE_NAME = "com.test.package"; 74 75 @Rule 76 public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = 77 new DexmakerShareClassLoaderRule(); 78 79 @Mock 80 private Context mContext; 81 @Mock 82 private ActivityManagerService mService; 83 @Mock 84 private ActivityStackSupervisor mSupervisor; 85 @Mock 86 private DevicePolicyManagerInternal mDevicePolicyManager; 87 @Mock 88 private PackageManagerInternal mPackageManagerInternal; 89 @Mock 90 private UserManager mUserManager; 91 @Mock 92 private UserController mUserController; 93 @Mock 94 private KeyguardManager mKeyguardManager; 95 @Mock 96 private PackageManagerService mPackageManager; 97 98 private ActivityStartInterceptor mInterceptor; 99 private ActivityInfo mAInfo = new ActivityInfo(); 100 101 @Before 102 public void setUp() { 103 MockitoAnnotations.initMocks(this); 104 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext, 105 mUserController); 106 mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID, 107 TEST_START_FLAGS, TEST_CALLING_PACKAGE); 108 109 // Mock DevicePolicyManagerInternal 110 LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); 111 LocalServices.addService(DevicePolicyManagerInternal.class, 112 mDevicePolicyManager); 113 when(mDevicePolicyManager 114 .createShowAdminSupportIntent(TEST_USER_ID, true)) 115 .thenReturn(ADMIN_SUPPORT_INTENT); 116 when(mService.getPackageManagerInternalLocked()).thenReturn(mPackageManagerInternal); 117 118 // Mock UserManager 119 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 120 when(mUserManager.getProfileParent(TEST_USER_ID)).thenReturn(PARENT_USER_INFO); 121 122 // Mock KeyguardManager 123 when(mContext.getSystemService(Context.KEYGUARD_SERVICE)).thenReturn(mKeyguardManager); 124 when(mKeyguardManager.createConfirmDeviceCredentialIntent( 125 nullable(CharSequence.class), nullable(CharSequence.class), eq(TEST_USER_ID))). 126 thenReturn(CONFIRM_CREDENTIALS_INTENT); 127 128 // Mock PackageManager 129 when(mService.getPackageManager()).thenReturn(mPackageManager); 130 when(mPackageManager.getHarmfulAppWarning(TEST_PACKAGE_NAME, TEST_USER_ID)) 131 .thenReturn(null); 132 133 // Initialise activity info 134 mAInfo.applicationInfo = new ApplicationInfo(); 135 mAInfo.packageName = mAInfo.applicationInfo.packageName = TEST_PACKAGE_NAME; 136 } 137 138 @Test 139 public void testSuspendedByAdminPackage() { 140 // GIVEN the package we're about to launch is currently suspended 141 mAInfo.applicationInfo.flags = FLAG_SUSPENDED; 142 143 when(mPackageManagerInternal.getSuspendingPackage(TEST_PACKAGE_NAME, TEST_USER_ID)) 144 .thenReturn(PLATFORM_PACKAGE_NAME); 145 146 // THEN calling intercept returns true 147 assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); 148 149 // THEN the returned intent is the admin support intent 150 assertEquals(ADMIN_SUPPORT_INTENT, mInterceptor.mIntent); 151 } 152 153 @Test 154 public void testSuspendedPackage() { 155 mAInfo.applicationInfo.flags = FLAG_SUSPENDED; 156 final String suspendingPackage = "com.test.suspending.package"; 157 final String dialogMessage = "Test Message"; 158 when(mPackageManagerInternal.getSuspendingPackage(TEST_PACKAGE_NAME, TEST_USER_ID)) 159 .thenReturn(suspendingPackage); 160 when(mPackageManagerInternal.getSuspendedDialogMessage(TEST_PACKAGE_NAME, TEST_USER_ID)) 161 .thenReturn(dialogMessage); 162 // THEN calling intercept returns true 163 assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); 164 165 // Check intent parameters 166 assertEquals(dialogMessage, 167 mInterceptor.mIntent.getStringExtra(SuspendedAppActivity.EXTRA_DIALOG_MESSAGE)); 168 assertEquals(suspendingPackage, 169 mInterceptor.mIntent.getStringExtra(SuspendedAppActivity.EXTRA_SUSPENDING_PACKAGE)); 170 assertEquals(TEST_PACKAGE_NAME, 171 mInterceptor.mIntent.getStringExtra(SuspendedAppActivity.EXTRA_SUSPENDED_PACKAGE)); 172 assertEquals(TEST_USER_ID, mInterceptor.mIntent.getIntExtra(Intent.EXTRA_USER_ID, -1000)); 173 } 174 175 @Test 176 public void testInterceptQuietProfile() { 177 // GIVEN that the user the activity is starting as is currently in quiet mode 178 when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true); 179 180 // THEN calling intercept returns true 181 assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); 182 183 // THEN the returned intent is the quiet mode intent 184 assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID) 185 .filterEquals(mInterceptor.mIntent)); 186 } 187 188 @Test 189 public void testWorkChallenge() { 190 // GIVEN that the user the activity is starting as is currently locked 191 when(mUserController.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true); 192 193 // THEN calling intercept returns true 194 mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null); 195 196 // THEN the returned intent is the quiet mode intent 197 assertTrue(CONFIRM_CREDENTIALS_INTENT.filterEquals(mInterceptor.mIntent)); 198 } 199 200 @Test 201 public void testNoInterception() { 202 // GIVEN that none of the interception conditions are met 203 204 // THEN calling intercept returns false 205 assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); 206 } 207 } 208