1 /* 2 * Copyright (C) 2019 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.car.settings.security; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.app.admin.DevicePolicyManager; 22 import android.content.Context; 23 import android.content.ContextWrapper; 24 import android.content.Intent; 25 import android.os.RemoteException; 26 27 import com.android.car.settings.CarSettingsRobolectricTestRunner; 28 import com.android.car.settings.setupservice.InitialLockSetupService; 29 import com.android.car.settings.testutils.ShadowLockPatternUtils; 30 import com.android.car.setupwizardlib.IInitialLockSetupService; 31 import com.android.car.setupwizardlib.InitialLockSetupConstants.LockTypes; 32 import com.android.car.setupwizardlib.InitialLockSetupConstants.SetLockCodes; 33 import com.android.car.setupwizardlib.InitialLockSetupConstants.ValidateLockFlags; 34 import com.android.car.setupwizardlib.InitialLockSetupHelper; 35 import com.android.car.setupwizardlib.LockConfig; 36 import com.android.internal.widget.LockPatternUtils; 37 import com.android.internal.widget.LockPatternView; 38 39 import org.junit.Before; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 import org.robolectric.Robolectric; 43 import org.robolectric.RuntimeEnvironment; 44 import org.robolectric.Shadows; 45 import org.robolectric.annotation.Config; 46 import org.robolectric.shadows.ShadowContextWrapper; 47 48 import java.util.ArrayList; 49 import java.util.Arrays; 50 import java.util.List; 51 52 /** 53 * Tests that the {@link InitialLockSetupService} properly handles connections and lock requests. 54 */ 55 @Config(shadows = ShadowLockPatternUtils.class) 56 @RunWith(CarSettingsRobolectricTestRunner.class) 57 public class InitialLockSetupServiceTest { 58 59 private static final String LOCK_PERMISSION = "com.android.car.settings.SET_INITIAL_LOCK"; 60 61 private InitialLockSetupService mInitialLockSetupService; 62 private Context mContext; 63 64 @Before setupService()65 public void setupService() { 66 ShadowLockPatternUtils.reset(); 67 mInitialLockSetupService = Robolectric.buildService(InitialLockSetupService.class) 68 .create() 69 .get(); 70 mContext = RuntimeEnvironment.application; 71 ShadowContextWrapper shadowContextWrapper = Shadows.shadowOf((ContextWrapper) mContext); 72 shadowContextWrapper.grantPermissions(LOCK_PERMISSION); 73 } 74 75 @Test testBindReturnsNull_ifLockSet()76 public void testBindReturnsNull_ifLockSet() { 77 ShadowLockPatternUtils.setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC); 78 assertThat(mInitialLockSetupService.onBind(new Intent())).isNull(); 79 } 80 81 @Test testBindReturnsInstanceOfServiceInterface_ifLockNotSet()82 public void testBindReturnsInstanceOfServiceInterface_ifLockNotSet() throws RemoteException { 83 assertThat(mInitialLockSetupService.onBind( 84 new Intent()) instanceof IInitialLockSetupService.Stub).isTrue(); 85 } 86 87 @Test testGetLockConfig_returnsCorrectConfig()88 public void testGetLockConfig_returnsCorrectConfig() throws RemoteException { 89 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 90 mInitialLockSetupService.onBind(new Intent())); 91 LockConfig pinConfig = service.getLockConfig(LockTypes.PIN); 92 assertThat(pinConfig.enabled).isTrue(); 93 assertThat(pinConfig.minLockLength).isEqualTo(LockPatternUtils.MIN_LOCK_PASSWORD_SIZE); 94 LockConfig patternConfig = service.getLockConfig(LockTypes.PATTERN); 95 assertThat(patternConfig.enabled).isTrue(); 96 assertThat(patternConfig.minLockLength).isEqualTo(LockPatternUtils.MIN_LOCK_PATTERN_SIZE); 97 LockConfig passwordConfig = service.getLockConfig(LockTypes.PASSWORD); 98 assertThat(passwordConfig.enabled).isTrue(); 99 assertThat(passwordConfig.minLockLength).isEqualTo(LockPatternUtils.MIN_LOCK_PASSWORD_SIZE); 100 } 101 102 @Test testCheckValidLock_tooShort()103 public void testCheckValidLock_tooShort() throws RemoteException { 104 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 105 mInitialLockSetupService.onBind(new Intent())); 106 int result = service.checkValidLock(LockTypes.PASSWORD, "hi".getBytes()); 107 assertThat(result & ValidateLockFlags.INVALID_LENGTH) 108 .isEqualTo(ValidateLockFlags.INVALID_LENGTH); 109 } 110 111 @Test testCheckValidLock_longEnough()112 public void testCheckValidLock_longEnough() throws RemoteException { 113 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 114 mInitialLockSetupService.onBind(new Intent())); 115 int result = service.checkValidLock(LockTypes.PASSWORD, "password".getBytes()); 116 assertThat(result & ValidateLockFlags.INVALID_LENGTH) 117 .isNotEqualTo(ValidateLockFlags.INVALID_LENGTH); 118 } 119 120 @Test testCheckValidLockPin_withLetters()121 public void testCheckValidLockPin_withLetters() throws RemoteException { 122 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 123 mInitialLockSetupService.onBind(new Intent())); 124 int result = service.checkValidLock(LockTypes.PIN, "12a3".getBytes()); 125 assertThat(result & ValidateLockFlags.INVALID_BAD_SYMBOLS) 126 .isEqualTo(ValidateLockFlags.INVALID_BAD_SYMBOLS); 127 } 128 129 @Test testCheckValidLockPattern_tooShort()130 public void testCheckValidLockPattern_tooShort() throws RemoteException { 131 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 132 mInitialLockSetupService.onBind(new Intent())); 133 byte[] pattern = new byte[LockPatternUtils.MIN_LOCK_PATTERN_SIZE - 1]; 134 for (int i = 0; i < pattern.length; i++) { 135 pattern[i] = (byte) i; 136 } 137 int result = service.checkValidLock(LockTypes.PATTERN, pattern); 138 assertThat(result & ValidateLockFlags.INVALID_LENGTH) 139 .isEqualTo(ValidateLockFlags.INVALID_LENGTH); 140 } 141 142 @Test testCheckValidLockPattern_longEnough()143 public void testCheckValidLockPattern_longEnough() throws RemoteException { 144 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 145 mInitialLockSetupService.onBind(new Intent())); 146 byte[] pattern = new byte[LockPatternUtils.MIN_LOCK_PATTERN_SIZE + 1]; 147 for (int i = 0; i < pattern.length; i++) { 148 pattern[i] = (byte) i; 149 } 150 int result = service.checkValidLock(LockTypes.PATTERN, pattern); 151 assertThat(result & ValidateLockFlags.INVALID_LENGTH) 152 .isNotEqualTo(ValidateLockFlags.INVALID_LENGTH); 153 } 154 155 @Test testSetLockPassword_doesNotWorkWithExistingPassword()156 public void testSetLockPassword_doesNotWorkWithExistingPassword() throws RemoteException { 157 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 158 mInitialLockSetupService.onBind(new Intent())); 159 ShadowLockPatternUtils.setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC); 160 int result = service.setLock(LockTypes.PASSWORD, "password".getBytes()); 161 assertThat(result).isEqualTo(SetLockCodes.FAIL_LOCK_EXISTS); 162 } 163 164 @Test testSetLockPassword_doesNotWorkWithInvalidPassword()165 public void testSetLockPassword_doesNotWorkWithInvalidPassword() throws RemoteException { 166 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 167 mInitialLockSetupService.onBind(new Intent())); 168 int result = service.setLock(LockTypes.PASSWORD, "hi".getBytes()); 169 assertThat(result).isEqualTo(SetLockCodes.FAIL_LOCK_INVALID); 170 } 171 172 @Test testSetLockPassword_setsDevicePassword()173 public void testSetLockPassword_setsDevicePassword() throws RemoteException { 174 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 175 mInitialLockSetupService.onBind(new Intent())); 176 byte[] password = "password".getBytes(); 177 // Need copy since password is cleared. 178 byte[] expectedPassword = Arrays.copyOf(password, password.length); 179 int result = service.setLock(LockTypes.PASSWORD, password); 180 assertThat(result).isEqualTo(SetLockCodes.SUCCESS); 181 assertThat(Arrays.equals(ShadowLockPatternUtils.getSavedPassword(), 182 expectedPassword)).isTrue(); 183 } 184 185 @Test testSetLockPin_setsDevicePin()186 public void testSetLockPin_setsDevicePin() throws RemoteException { 187 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 188 mInitialLockSetupService.onBind(new Intent())); 189 byte[] password = "1580".getBytes(); 190 byte[] expectedPassword = Arrays.copyOf(password, password.length); 191 int result = service.setLock(LockTypes.PIN, password); 192 assertThat(result).isEqualTo(SetLockCodes.SUCCESS); 193 assertThat(Arrays.equals(ShadowLockPatternUtils.getSavedPassword(), 194 expectedPassword)).isTrue(); 195 } 196 197 @Test testSetLockPattern_setsDevicePattern()198 public void testSetLockPattern_setsDevicePattern() throws RemoteException { 199 IInitialLockSetupService service = IInitialLockSetupService.Stub.asInterface( 200 mInitialLockSetupService.onBind(new Intent())); 201 List<LockPatternView.Cell> pattern = new ArrayList<>(); 202 pattern.add(LockPatternView.Cell.of(0, 0)); 203 pattern.add(LockPatternView.Cell.of(1, 0)); 204 pattern.add(LockPatternView.Cell.of(2, 0)); 205 pattern.add(LockPatternView.Cell.of(0, 1)); 206 byte[] patternBytes = new byte[pattern.size()]; 207 for (int i = 0; i < patternBytes.length; i++) { 208 LockPatternView.Cell cell = pattern.get(i); 209 patternBytes[i] = InitialLockSetupHelper.getByteFromPatternCell(cell.getRow(), 210 cell.getColumn()); 211 } 212 int result = service.setLock(LockTypes.PATTERN, patternBytes); 213 assertThat(result).isEqualTo(SetLockCodes.SUCCESS); 214 List<LockPatternView.Cell> savedPattern = ShadowLockPatternUtils.getSavedPattern(); 215 assertThat(savedPattern).containsExactlyElementsIn(pattern); 216 } 217 218 @Test testBindFails_ifNoPermissionGranted()219 public void testBindFails_ifNoPermissionGranted() { 220 ShadowContextWrapper shadowContextWrapper = Shadows.shadowOf((ContextWrapper) mContext); 221 shadowContextWrapper.denyPermissions(LOCK_PERMISSION); 222 assertThat(mInitialLockSetupService.onBind(new Intent())).isNull(); 223 } 224 225 } 226