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