1 /* 2 * Copyright (C) 2016 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.locksettings; 18 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertTrue; 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyBoolean; 23 import static org.mockito.ArgumentMatchers.anyInt; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.Mockito.doAnswer; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.when; 28 29 import android.app.IActivityManager; 30 import android.app.KeyguardManager; 31 import android.app.NotificationManager; 32 import android.app.admin.DevicePolicyManager; 33 import android.app.admin.DevicePolicyManagerInternal; 34 import android.app.trust.TrustManager; 35 import android.content.ComponentName; 36 import android.content.pm.UserInfo; 37 import android.hardware.authsecret.V1_0.IAuthSecret; 38 import android.os.FileUtils; 39 import android.os.IProgressListener; 40 import android.os.RemoteException; 41 import android.os.UserManager; 42 import android.os.storage.IStorageManager; 43 import android.os.storage.StorageManager; 44 import android.security.KeyStore; 45 46 import androidx.test.InstrumentationRegistry; 47 import androidx.test.runner.AndroidJUnit4; 48 49 import com.android.internal.widget.ILockSettings; 50 import com.android.internal.widget.LockPatternUtils; 51 import com.android.internal.widget.LockSettingsInternal; 52 import com.android.server.LocalServices; 53 import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager; 54 import com.android.server.wm.WindowManagerInternal; 55 56 import org.junit.After; 57 import org.junit.Before; 58 import org.junit.runner.RunWith; 59 import org.mockito.invocation.InvocationOnMock; 60 import org.mockito.stubbing.Answer; 61 62 import java.io.File; 63 import java.util.ArrayList; 64 import java.util.Arrays; 65 66 @RunWith(AndroidJUnit4.class) 67 public abstract class BaseLockSettingsServiceTests { 68 protected static final int PRIMARY_USER_ID = 0; 69 protected static final int MANAGED_PROFILE_USER_ID = 12; 70 protected static final int TURNED_OFF_PROFILE_USER_ID = 17; 71 protected static final int SECONDARY_USER_ID = 20; 72 73 private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER_ID, null, null, 74 UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY); 75 private static final UserInfo SECONDARY_USER_INFO = new UserInfo(SECONDARY_USER_ID, null, null, 76 UserInfo.FLAG_INITIALIZED); 77 78 private ArrayList<UserInfo> mPrimaryUserProfiles = new ArrayList<>(); 79 80 LockSettingsService mService; 81 LockSettingsInternal mLocalService; 82 83 MockLockSettingsContext mContext; 84 LockSettingsStorageTestable mStorage; 85 86 LockPatternUtils mLockPatternUtils; 87 FakeGateKeeperService mGateKeeperService; 88 NotificationManager mNotificationManager; 89 UserManager mUserManager; 90 FakeStorageManager mStorageManager; 91 IActivityManager mActivityManager; 92 DevicePolicyManager mDevicePolicyManager; 93 DevicePolicyManagerInternal mDevicePolicyManagerInternal; 94 KeyStore mKeyStore; 95 MockSyntheticPasswordManager mSpManager; 96 IAuthSecret mAuthSecretService; 97 WindowManagerInternal mMockWindowManager; 98 FakeGsiService mGsiService; 99 PasswordSlotManagerTestable mPasswordSlotManager; 100 RecoverableKeyStoreManager mRecoverableKeyStoreManager; 101 protected boolean mHasSecureLockScreen; 102 103 @Before setUp_baseServices()104 public void setUp_baseServices() throws Exception { 105 mGateKeeperService = new FakeGateKeeperService(); 106 mNotificationManager = mock(NotificationManager.class); 107 mUserManager = mock(UserManager.class); 108 mStorageManager = new FakeStorageManager(); 109 mActivityManager = mock(IActivityManager.class); 110 mDevicePolicyManager = mock(DevicePolicyManager.class); 111 mDevicePolicyManagerInternal = mock(DevicePolicyManagerInternal.class); 112 mMockWindowManager = mock(WindowManagerInternal.class); 113 mGsiService = new FakeGsiService(); 114 mPasswordSlotManager = new PasswordSlotManagerTestable(); 115 mRecoverableKeyStoreManager = mock(RecoverableKeyStoreManager.class); 116 117 LocalServices.removeServiceForTest(LockSettingsInternal.class); 118 LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); 119 LocalServices.removeServiceForTest(WindowManagerInternal.class); 120 LocalServices.addService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); 121 LocalServices.addService(WindowManagerInternal.class, mMockWindowManager); 122 123 mContext = new MockLockSettingsContext(InstrumentationRegistry.getContext(), mUserManager, 124 mNotificationManager, mDevicePolicyManager, mock(StorageManager.class), 125 mock(TrustManager.class), mock(KeyguardManager.class)); 126 mStorage = new LockSettingsStorageTestable(mContext, 127 new File(InstrumentationRegistry.getContext().getFilesDir(), "locksettings")); 128 File storageDir = mStorage.mStorageDir; 129 if (storageDir.exists()) { 130 FileUtils.deleteContents(storageDir); 131 } else { 132 storageDir.mkdirs(); 133 } 134 135 mHasSecureLockScreen = true; 136 mLockPatternUtils = new LockPatternUtils(mContext) { 137 @Override 138 public ILockSettings getLockSettings() { 139 return mService; 140 } 141 142 @Override 143 public boolean hasSecureLockScreen() { 144 return mHasSecureLockScreen; 145 } 146 }; 147 mSpManager = new MockSyntheticPasswordManager(mContext, mStorage, mGateKeeperService, 148 mUserManager, mPasswordSlotManager); 149 mAuthSecretService = mock(IAuthSecret.class); 150 mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils, mStorage, 151 mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager, 152 mSpManager, mAuthSecretService, mGsiService, mRecoverableKeyStoreManager); 153 when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO); 154 mPrimaryUserProfiles.add(PRIMARY_USER_INFO); 155 installChildProfile(MANAGED_PROFILE_USER_ID); 156 installAndTurnOffChildProfile(TURNED_OFF_PROFILE_USER_ID); 157 for (UserInfo profile : mPrimaryUserProfiles) { 158 when(mUserManager.getProfiles(eq(profile.id))).thenReturn(mPrimaryUserProfiles); 159 } 160 when(mUserManager.getUserInfo(eq(SECONDARY_USER_ID))).thenReturn(SECONDARY_USER_INFO); 161 162 final ArrayList<UserInfo> allUsers = new ArrayList<>(mPrimaryUserProfiles); 163 allUsers.add(SECONDARY_USER_INFO); 164 when(mUserManager.getUsers(anyBoolean())).thenReturn(allUsers); 165 166 when(mActivityManager.unlockUser(anyInt(), any(), any(), any())).thenAnswer( 167 new Answer<Boolean>() { 168 @Override 169 public Boolean answer(InvocationOnMock invocation) throws Throwable { 170 Object[] args = invocation.getArguments(); 171 mStorageManager.unlockUser((int)args[0], (byte[])args[2], 172 (IProgressListener) args[3]); 173 return true; 174 } 175 }); 176 177 // Adding a fake Device Owner app which will enable escrow token support in LSS. 178 when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn( 179 new ComponentName("com.dummy.package", ".FakeDeviceOwner")); 180 mLocalService = LocalServices.getService(LockSettingsInternal.class); 181 } 182 installChildProfile(int profileId)183 private UserInfo installChildProfile(int profileId) { 184 final UserInfo userInfo = new UserInfo( 185 profileId, null, null, UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE); 186 userInfo.profileGroupId = PRIMARY_USER_ID; 187 mPrimaryUserProfiles.add(userInfo); 188 when(mUserManager.getUserInfo(eq(profileId))).thenReturn(userInfo); 189 when(mUserManager.getProfileParent(eq(profileId))).thenReturn(PRIMARY_USER_INFO); 190 when(mUserManager.isUserRunning(eq(profileId))).thenReturn(true); 191 when(mUserManager.isUserUnlocked(eq(profileId))).thenReturn(true); 192 return userInfo; 193 } 194 installAndTurnOffChildProfile(int profileId)195 private UserInfo installAndTurnOffChildProfile(int profileId) { 196 final UserInfo userInfo = installChildProfile(profileId); 197 userInfo.flags |= UserInfo.FLAG_QUIET_MODE; 198 when(mUserManager.isUserRunning(eq(profileId))).thenReturn(false); 199 when(mUserManager.isUserUnlocked(eq(profileId))).thenReturn(false); 200 return userInfo; 201 } 202 setUpStorageManagerMock()203 private IStorageManager setUpStorageManagerMock() throws RemoteException { 204 final IStorageManager sm = mock(IStorageManager.class); 205 206 doAnswer(new Answer<Void>() { 207 @Override 208 public Void answer(InvocationOnMock invocation) throws Throwable { 209 Object[] args = invocation.getArguments(); 210 mStorageManager.addUserKeyAuth((int) args[0] /* userId */, 211 (int) args[1] /* serialNumber */, 212 (byte[]) args[2] /* token */, 213 (byte[]) args[3] /* secret */); 214 return null; 215 } 216 }).when(sm).addUserKeyAuth(anyInt(), anyInt(), any(), any()); 217 218 doAnswer(new Answer<Void>() { 219 @Override 220 public Void answer(InvocationOnMock invocation) throws Throwable { 221 Object[] args = invocation.getArguments(); 222 mStorageManager.clearUserKeyAuth((int) args[0] /* userId */, 223 (int) args[1] /* serialNumber */, 224 (byte[]) args[2] /* token */, 225 (byte[]) args[3] /* secret */); 226 return null; 227 } 228 }).when(sm).clearUserKeyAuth(anyInt(), anyInt(), any(), any()); 229 230 doAnswer( 231 new Answer<Void>() { 232 @Override 233 public Void answer(InvocationOnMock invocation) throws Throwable { 234 Object[] args = invocation.getArguments(); 235 mStorageManager.fixateNewestUserKeyAuth((int) args[0] /* userId */); 236 return null; 237 } 238 }).when(sm).fixateNewestUserKeyAuth(anyInt()); 239 return sm; 240 } 241 242 @After tearDown_baseServices()243 public void tearDown_baseServices() throws Exception { 244 mStorage.closeDatabase(); 245 File db = InstrumentationRegistry.getContext().getDatabasePath("locksettings.db"); 246 assertTrue(!db.exists() || db.delete()); 247 248 File storageDir = mStorage.mStorageDir; 249 assertTrue(FileUtils.deleteContents(storageDir)); 250 251 mPasswordSlotManager.cleanup(); 252 } 253 flushHandlerTasks()254 protected void flushHandlerTasks() { 255 mService.mHandler.runWithScissors(() -> { }, 0 /*now*/); // Flush runnables on handler 256 } 257 assertNotEquals(long expected, long actual)258 protected void assertNotEquals(long expected, long actual) { 259 assertTrue(expected != actual); 260 } 261 assertArrayEquals(byte[] expected, byte[] actual)262 protected static void assertArrayEquals(byte[] expected, byte[] actual) { 263 assertTrue(Arrays.equals(expected, actual)); 264 } 265 assertArrayNotEquals(byte[] expected, byte[] actual)266 protected static void assertArrayNotEquals(byte[] expected, byte[] actual) { 267 assertFalse(Arrays.equals(expected, actual)); 268 } 269 } 270