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