Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +4 −13 Original line number Diff line number Diff line Loading @@ -550,16 +550,6 @@ public class LockSettingsService extends ILockSettings.Stub { return (BiometricManager) mContext.getSystemService(Context.BIOMETRIC_SERVICE); } public int settingsGlobalGetInt(ContentResolver contentResolver, String keyName, int defaultValue) { return Settings.Global.getInt(contentResolver, keyName, defaultValue); } public int settingsSecureGetInt(ContentResolver contentResolver, String keyName, int defaultValue, int userId) { return Settings.Secure.getIntForUser(contentResolver, keyName, defaultValue, userId); } public java.security.KeyStore getJavaKeyStore() { try { java.security.KeyStore ks = java.security.KeyStore.getInstance( Loading Loading @@ -1027,9 +1017,9 @@ public class LockSettingsService extends ILockSettings.Stub { private void enforceFrpResolved() { final ContentResolver cr = mContext.getContentResolver(); final boolean inSetupWizard = mInjector.settingsSecureGetInt(cr, final boolean inSetupWizard = Settings.Secure.getIntForUser(cr, Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_SYSTEM) == 0; final boolean secureFrp = mInjector.settingsSecureGetInt(cr, final boolean secureFrp = Settings.Secure.getIntForUser(cr, Settings.Secure.SECURE_FRP_MODE, 0, UserHandle.USER_SYSTEM) == 1; if (inSetupWizard && secureFrp) { throw new SecurityException("Cannot change credential in SUW while factory reset" Loading Loading @@ -2155,7 +2145,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (credential == null || credential.isNone()) { throw new IllegalArgumentException("Credential can't be null or empty"); } if (userId == USER_FRP && mInjector.settingsGlobalGetInt(mContext.getContentResolver(), if (userId == USER_FRP && Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0) { Slog.e(TAG, "FRP credential can only be verified prior to provisioning."); return VerifyCredentialResponse.ERROR; Loading Loading @@ -3282,6 +3272,7 @@ public class LockSettingsService extends ILockSettings.Stub { for (UserInfo user : users) { if (userOwnsFrpCredential(mContext, user)) { if (!isUserSecure(user.id)) { Slogf.d(TAG, "Clearing FRP credential tied to user %d", user.id); mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, user.id, 0, null); } Loading services/core/java/com/android/server/locksettings/LockSettingsStorage.java +1 −1 Original line number Diff line number Diff line Loading @@ -550,7 +550,7 @@ class LockSettingsStorage { mCache.clear(); } @Nullable @VisibleForTesting @Nullable PersistentDataBlockManagerInternal getPersistentDataBlockManager() { if (mPersistentDataBlockManagerInternal == null) { mPersistentDataBlockManagerInternal = Loading services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +61 −12 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.hardware.weaver.V1_0.WeaverStatus; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserManager; import android.provider.Settings; import android.security.GateKeeper; import android.security.Scrypt; import android.service.gatekeeper.GateKeeperResponse; Loading Loading @@ -457,6 +458,11 @@ public class SyntheticPasswordManager { mPasswordSlotManager = passwordSlotManager; } private boolean isDeviceProvisioned() { return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; } @VisibleForTesting protected IWeaver getWeaverService() throws RemoteException { try { Loading Loading @@ -770,6 +776,17 @@ public class SyntheticPasswordManager { private int getNextAvailableWeaverSlot() { Set<Integer> usedSlots = getUsedWeaverSlots(); usedSlots.addAll(mPasswordSlotManager.getUsedSlots()); // If the device is not yet provisioned, then the Weaver slot used by the FRP credential may // be still needed and must not be reused yet. (This *should* instead check "has FRP been // resolved yet?", which would allow reusing the slot a bit earlier. However, the // SECURE_FRP_MODE setting gets set to 1 too late for it to be used here.) if (!isDeviceProvisioned()) { PersistentData persistentData = mStorage.readPersistentDataBlock(); if (persistentData != null && persistentData.type == PersistentData.TYPE_SP_WEAVER) { int slot = persistentData.userId; // Note: field name is misleading usedSlots.add(slot); } } for (int i = 0; i < mWeaverConfig.slots; i++) { if (!usedSlots.contains(i)) { return i; Loading Loading @@ -814,9 +831,14 @@ public class SyntheticPasswordManager { protectorSecret = transformUnderWeaverSecret(stretchedLskf, weaverSecret); } else { // Weaver is unavailable, so make the protector use Gatekeeper to verify the LSKF // instead. However, skip Gatekeeper when the LSKF is empty, since it wouldn't give any // benefit in that case as Gatekeeper isn't expected to provide secure deletion. // Weaver is unavailable, so make the protector use Gatekeeper (GK) to verify the LSKF. // // However, skip GK when the LSKF is empty. There are two reasons for this, one // performance and one correctness. The performance reason is that GK wouldn't give any // benefit with an empty LSKF anyway, since GK isn't expected to provide secure // deletion. The correctness reason is that it is unsafe to enroll a password in the // 'fakeUserId' GK range on an FRP-protected device that is in the setup wizard with FRP // not passed yet, as that may overwrite the enrollment used by the FRP credential. if (!credential.isNone()) { // In case GK enrollment leaves persistent state around (in RPMB), this will nuke // them to prevent them from accumulating and causing problems. Loading Loading @@ -908,12 +930,40 @@ public class SyntheticPasswordManager { } } private static boolean isNoneCredential(PasswordData pwd) { return pwd == null || pwd.credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE; } private boolean shouldSynchronizeFrpCredential(@Nullable PasswordData pwd, int userId) { if (mStorage.getPersistentDataBlockManager() == null) { return false; } UserInfo userInfo = mUserManager.getUserInfo(userId); if (!LockPatternUtils.userOwnsFrpCredential(mContext, userInfo)) { return false; } // When initializing the synthetic password of the user that will own the FRP credential, // the FRP data block must not be cleared if the device isn't provisioned yet, since in this // case the old value of the block may still be needed for the FRP authentication step. The // FRP data block will instead be cleared later, by // LockSettingsService.DeviceProvisionedObserver.clearFrpCredentialIfOwnerNotSecure(). // // Don't check the SECURE_FRP_MODE setting here, as it gets set to 1 too late. // // Don't delay anything for a nonempty credential. A nonempty credential can be set before // the device has been provisioned, but it's guaranteed to be after FRP was resolved. if (isNoneCredential(pwd) && !isDeviceProvisioned()) { Slog.d(TAG, "Not clearing FRP credential yet because device is not yet provisioned"); return false; } return true; } private void synchronizeFrpPassword(@Nullable PasswordData pwd, int requestedQuality, int userId) { if (mStorage.getPersistentDataBlockManager() != null && LockPatternUtils.userOwnsFrpCredential(mContext, mUserManager.getUserInfo(userId))) { if (pwd != null && pwd.credentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE) { if (shouldSynchronizeFrpCredential(pwd, userId)) { Slogf.d(TAG, "Syncing Gatekeeper-based FRP credential tied to user %d", userId); if (!isNoneCredential(pwd)) { mStorage.writePersistentDataBlock(PersistentData.TYPE_SP, userId, requestedQuality, pwd.toBytes()); } else { Loading @@ -924,10 +974,9 @@ public class SyntheticPasswordManager { private void synchronizeWeaverFrpPassword(@Nullable PasswordData pwd, int requestedQuality, int userId, int weaverSlot) { if (mStorage.getPersistentDataBlockManager() != null && LockPatternUtils.userOwnsFrpCredential(mContext, mUserManager.getUserInfo(userId))) { if (pwd != null && pwd.credentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE) { if (shouldSynchronizeFrpCredential(pwd, userId)) { Slogf.d(TAG, "Syncing Weaver-based FRP credential tied to user %d", userId); if (!isNoneCredential(pwd)) { mStorage.writePersistentDataBlock(PersistentData.TYPE_SP_WEAVER, weaverSlot, requestedQuality, pwd.toBytes()); } else { Loading Loading @@ -1058,7 +1107,7 @@ public class SyntheticPasswordManager { AuthenticationResult result = new AuthenticationResult(); if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { // This should never happen, due to the migration done in LSS.bootCompleted(). // This should never happen, due to the migration done in LSS.onThirdPartyAppsStarted(). Slogf.wtf(TAG, "Synthetic password not found for user %d", userId); result.gkResponse = VerifyCredentialResponse.ERROR; return result; Loading services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +31 −9 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DeviceStateCache; import android.app.trust.TrustManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.hardware.authsecret.V1_0.IAuthSecret; Loading @@ -41,14 +42,18 @@ import android.hardware.fingerprint.FingerprintManager; import android.os.FileUtils; import android.os.IProgressListener; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.provider.Settings; import android.security.KeyStore; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockSettingsInternal; import com.android.internal.widget.LockscreenCredential; Loading @@ -59,6 +64,7 @@ import com.android.server.wm.WindowManagerInternal; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.runner.RunWith; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; Loading Loading @@ -106,7 +112,8 @@ public abstract class BaseLockSettingsServiceTests { FingerprintManager mFingerprintManager; FaceManager mFaceManager; PackageManager mPackageManager; FakeSettings mSettings; @Rule public FakeSettingsProviderRule mSettingsRule = FakeSettingsProvider.rule(); @Before public void setUp_baseServices() throws Exception { Loading @@ -126,7 +133,6 @@ public abstract class BaseLockSettingsServiceTests { mFingerprintManager = mock(FingerprintManager.class); mFaceManager = mock(FaceManager.class); mPackageManager = mock(PackageManager.class); mSettings = new FakeSettings(); LocalServices.removeServiceForTest(LockSettingsInternal.class); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); Loading @@ -134,12 +140,13 @@ public abstract class BaseLockSettingsServiceTests { LocalServices.addService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); LocalServices.addService(WindowManagerInternal.class, mMockWindowManager); mContext = new MockLockSettingsContext(InstrumentationRegistry.getContext(), mUserManager, mNotificationManager, mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class), mFingerprintManager, mFaceManager, mPackageManager); final Context origContext = InstrumentationRegistry.getContext(); mContext = new MockLockSettingsContext(origContext, mSettingsRule.mockContentResolver(origContext), mUserManager, mNotificationManager, mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class), mFingerprintManager, mFaceManager, mPackageManager); mStorage = new LockSettingsStorageTestable(mContext, new File(InstrumentationRegistry.getContext().getFilesDir(), "locksettings")); new File(origContext.getFilesDir(), "locksettings")); File storageDir = mStorage.mStorageDir; if (storageDir.exists()) { FileUtils.deleteContents(storageDir); Loading @@ -153,7 +160,7 @@ public abstract class BaseLockSettingsServiceTests { mService = new LockSettingsServiceTestable(mContext, mStorage, mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager, mSpManager, mAuthSecretService, mGsiService, mRecoverableKeyStoreManager, mUserManagerInternal, mDeviceStateCache, mSettings); mUserManagerInternal, mDeviceStateCache); mService.mHasSecureLockScreen = true; when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO); mPrimaryUserProfiles.add(PRIMARY_USER_INFO); Loading Loading @@ -186,10 +193,25 @@ public abstract class BaseLockSettingsServiceTests { mockBiometricsHardwareFingerprintsAndTemplates(PRIMARY_USER_ID); mockBiometricsHardwareFingerprintsAndTemplates(MANAGED_PROFILE_USER_ID); mSettings.setDeviceProvisioned(true); setDeviceProvisioned(true); mLocalService = LocalServices.getService(LockSettingsInternal.class); } protected void setDeviceProvisioned(boolean provisioned) { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, provisioned ? 1 : 0); } protected void setUserSetupComplete(boolean complete) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, complete ? 1 : 0, UserHandle.USER_SYSTEM); } protected void setSecureFrpMode(boolean secure) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.SECURE_FRP_MODE, secure ? 1 : 0, UserHandle.USER_SYSTEM); } private UserInfo installChildProfile(int profileId) { final UserInfo userInfo = new UserInfo( profileId, null, null, UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE); Loading services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.javadeleted 100644 → 0 +0 −60 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.locksettings; import android.content.ContentResolver; import android.os.UserHandle; import android.provider.Settings; public class FakeSettings { private int mDeviceProvisioned; private int mSecureFrpMode; private int mUserSetupComplete; public void setDeviceProvisioned(boolean provisioned) { mDeviceProvisioned = provisioned ? 1 : 0; } public void setSecureFrpMode(boolean secure) { mSecureFrpMode = secure ? 1 : 0; } public void setUserSetupComplete(boolean complete) { mUserSetupComplete = complete ? 1 : 0; } public int globalGetInt(String keyName) { switch (keyName) { case Settings.Global.DEVICE_PROVISIONED: return mDeviceProvisioned; default: throw new IllegalArgumentException("Unhandled global settings: " + keyName); } } public int secureGetInt(ContentResolver contentResolver, String keyName, int defaultValue, int userId) { if (Settings.Secure.SECURE_FRP_MODE.equals(keyName) && userId == UserHandle.USER_SYSTEM) { return mSecureFrpMode; } if (Settings.Secure.USER_SETUP_COMPLETE.equals(keyName) && userId == UserHandle.USER_SYSTEM) { return mUserSetupComplete; } return defaultValue; } } Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +4 −13 Original line number Diff line number Diff line Loading @@ -550,16 +550,6 @@ public class LockSettingsService extends ILockSettings.Stub { return (BiometricManager) mContext.getSystemService(Context.BIOMETRIC_SERVICE); } public int settingsGlobalGetInt(ContentResolver contentResolver, String keyName, int defaultValue) { return Settings.Global.getInt(contentResolver, keyName, defaultValue); } public int settingsSecureGetInt(ContentResolver contentResolver, String keyName, int defaultValue, int userId) { return Settings.Secure.getIntForUser(contentResolver, keyName, defaultValue, userId); } public java.security.KeyStore getJavaKeyStore() { try { java.security.KeyStore ks = java.security.KeyStore.getInstance( Loading Loading @@ -1027,9 +1017,9 @@ public class LockSettingsService extends ILockSettings.Stub { private void enforceFrpResolved() { final ContentResolver cr = mContext.getContentResolver(); final boolean inSetupWizard = mInjector.settingsSecureGetInt(cr, final boolean inSetupWizard = Settings.Secure.getIntForUser(cr, Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_SYSTEM) == 0; final boolean secureFrp = mInjector.settingsSecureGetInt(cr, final boolean secureFrp = Settings.Secure.getIntForUser(cr, Settings.Secure.SECURE_FRP_MODE, 0, UserHandle.USER_SYSTEM) == 1; if (inSetupWizard && secureFrp) { throw new SecurityException("Cannot change credential in SUW while factory reset" Loading Loading @@ -2155,7 +2145,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (credential == null || credential.isNone()) { throw new IllegalArgumentException("Credential can't be null or empty"); } if (userId == USER_FRP && mInjector.settingsGlobalGetInt(mContext.getContentResolver(), if (userId == USER_FRP && Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0) { Slog.e(TAG, "FRP credential can only be verified prior to provisioning."); return VerifyCredentialResponse.ERROR; Loading Loading @@ -3282,6 +3272,7 @@ public class LockSettingsService extends ILockSettings.Stub { for (UserInfo user : users) { if (userOwnsFrpCredential(mContext, user)) { if (!isUserSecure(user.id)) { Slogf.d(TAG, "Clearing FRP credential tied to user %d", user.id); mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, user.id, 0, null); } Loading
services/core/java/com/android/server/locksettings/LockSettingsStorage.java +1 −1 Original line number Diff line number Diff line Loading @@ -550,7 +550,7 @@ class LockSettingsStorage { mCache.clear(); } @Nullable @VisibleForTesting @Nullable PersistentDataBlockManagerInternal getPersistentDataBlockManager() { if (mPersistentDataBlockManagerInternal == null) { mPersistentDataBlockManagerInternal = Loading
services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +61 −12 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.hardware.weaver.V1_0.WeaverStatus; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserManager; import android.provider.Settings; import android.security.GateKeeper; import android.security.Scrypt; import android.service.gatekeeper.GateKeeperResponse; Loading Loading @@ -457,6 +458,11 @@ public class SyntheticPasswordManager { mPasswordSlotManager = passwordSlotManager; } private boolean isDeviceProvisioned() { return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; } @VisibleForTesting protected IWeaver getWeaverService() throws RemoteException { try { Loading Loading @@ -770,6 +776,17 @@ public class SyntheticPasswordManager { private int getNextAvailableWeaverSlot() { Set<Integer> usedSlots = getUsedWeaverSlots(); usedSlots.addAll(mPasswordSlotManager.getUsedSlots()); // If the device is not yet provisioned, then the Weaver slot used by the FRP credential may // be still needed and must not be reused yet. (This *should* instead check "has FRP been // resolved yet?", which would allow reusing the slot a bit earlier. However, the // SECURE_FRP_MODE setting gets set to 1 too late for it to be used here.) if (!isDeviceProvisioned()) { PersistentData persistentData = mStorage.readPersistentDataBlock(); if (persistentData != null && persistentData.type == PersistentData.TYPE_SP_WEAVER) { int slot = persistentData.userId; // Note: field name is misleading usedSlots.add(slot); } } for (int i = 0; i < mWeaverConfig.slots; i++) { if (!usedSlots.contains(i)) { return i; Loading Loading @@ -814,9 +831,14 @@ public class SyntheticPasswordManager { protectorSecret = transformUnderWeaverSecret(stretchedLskf, weaverSecret); } else { // Weaver is unavailable, so make the protector use Gatekeeper to verify the LSKF // instead. However, skip Gatekeeper when the LSKF is empty, since it wouldn't give any // benefit in that case as Gatekeeper isn't expected to provide secure deletion. // Weaver is unavailable, so make the protector use Gatekeeper (GK) to verify the LSKF. // // However, skip GK when the LSKF is empty. There are two reasons for this, one // performance and one correctness. The performance reason is that GK wouldn't give any // benefit with an empty LSKF anyway, since GK isn't expected to provide secure // deletion. The correctness reason is that it is unsafe to enroll a password in the // 'fakeUserId' GK range on an FRP-protected device that is in the setup wizard with FRP // not passed yet, as that may overwrite the enrollment used by the FRP credential. if (!credential.isNone()) { // In case GK enrollment leaves persistent state around (in RPMB), this will nuke // them to prevent them from accumulating and causing problems. Loading Loading @@ -908,12 +930,40 @@ public class SyntheticPasswordManager { } } private static boolean isNoneCredential(PasswordData pwd) { return pwd == null || pwd.credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE; } private boolean shouldSynchronizeFrpCredential(@Nullable PasswordData pwd, int userId) { if (mStorage.getPersistentDataBlockManager() == null) { return false; } UserInfo userInfo = mUserManager.getUserInfo(userId); if (!LockPatternUtils.userOwnsFrpCredential(mContext, userInfo)) { return false; } // When initializing the synthetic password of the user that will own the FRP credential, // the FRP data block must not be cleared if the device isn't provisioned yet, since in this // case the old value of the block may still be needed for the FRP authentication step. The // FRP data block will instead be cleared later, by // LockSettingsService.DeviceProvisionedObserver.clearFrpCredentialIfOwnerNotSecure(). // // Don't check the SECURE_FRP_MODE setting here, as it gets set to 1 too late. // // Don't delay anything for a nonempty credential. A nonempty credential can be set before // the device has been provisioned, but it's guaranteed to be after FRP was resolved. if (isNoneCredential(pwd) && !isDeviceProvisioned()) { Slog.d(TAG, "Not clearing FRP credential yet because device is not yet provisioned"); return false; } return true; } private void synchronizeFrpPassword(@Nullable PasswordData pwd, int requestedQuality, int userId) { if (mStorage.getPersistentDataBlockManager() != null && LockPatternUtils.userOwnsFrpCredential(mContext, mUserManager.getUserInfo(userId))) { if (pwd != null && pwd.credentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE) { if (shouldSynchronizeFrpCredential(pwd, userId)) { Slogf.d(TAG, "Syncing Gatekeeper-based FRP credential tied to user %d", userId); if (!isNoneCredential(pwd)) { mStorage.writePersistentDataBlock(PersistentData.TYPE_SP, userId, requestedQuality, pwd.toBytes()); } else { Loading @@ -924,10 +974,9 @@ public class SyntheticPasswordManager { private void synchronizeWeaverFrpPassword(@Nullable PasswordData pwd, int requestedQuality, int userId, int weaverSlot) { if (mStorage.getPersistentDataBlockManager() != null && LockPatternUtils.userOwnsFrpCredential(mContext, mUserManager.getUserInfo(userId))) { if (pwd != null && pwd.credentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE) { if (shouldSynchronizeFrpCredential(pwd, userId)) { Slogf.d(TAG, "Syncing Weaver-based FRP credential tied to user %d", userId); if (!isNoneCredential(pwd)) { mStorage.writePersistentDataBlock(PersistentData.TYPE_SP_WEAVER, weaverSlot, requestedQuality, pwd.toBytes()); } else { Loading Loading @@ -1058,7 +1107,7 @@ public class SyntheticPasswordManager { AuthenticationResult result = new AuthenticationResult(); if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { // This should never happen, due to the migration done in LSS.bootCompleted(). // This should never happen, due to the migration done in LSS.onThirdPartyAppsStarted(). Slogf.wtf(TAG, "Synthetic password not found for user %d", userId); result.gkResponse = VerifyCredentialResponse.ERROR; return result; Loading
services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +31 −9 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DeviceStateCache; import android.app.trust.TrustManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.hardware.authsecret.V1_0.IAuthSecret; Loading @@ -41,14 +42,18 @@ import android.hardware.fingerprint.FingerprintManager; import android.os.FileUtils; import android.os.IProgressListener; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.provider.Settings; import android.security.KeyStore; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockSettingsInternal; import com.android.internal.widget.LockscreenCredential; Loading @@ -59,6 +64,7 @@ import com.android.server.wm.WindowManagerInternal; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.runner.RunWith; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; Loading Loading @@ -106,7 +112,8 @@ public abstract class BaseLockSettingsServiceTests { FingerprintManager mFingerprintManager; FaceManager mFaceManager; PackageManager mPackageManager; FakeSettings mSettings; @Rule public FakeSettingsProviderRule mSettingsRule = FakeSettingsProvider.rule(); @Before public void setUp_baseServices() throws Exception { Loading @@ -126,7 +133,6 @@ public abstract class BaseLockSettingsServiceTests { mFingerprintManager = mock(FingerprintManager.class); mFaceManager = mock(FaceManager.class); mPackageManager = mock(PackageManager.class); mSettings = new FakeSettings(); LocalServices.removeServiceForTest(LockSettingsInternal.class); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); Loading @@ -134,12 +140,13 @@ public abstract class BaseLockSettingsServiceTests { LocalServices.addService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); LocalServices.addService(WindowManagerInternal.class, mMockWindowManager); mContext = new MockLockSettingsContext(InstrumentationRegistry.getContext(), mUserManager, mNotificationManager, mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class), mFingerprintManager, mFaceManager, mPackageManager); final Context origContext = InstrumentationRegistry.getContext(); mContext = new MockLockSettingsContext(origContext, mSettingsRule.mockContentResolver(origContext), mUserManager, mNotificationManager, mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class), mFingerprintManager, mFaceManager, mPackageManager); mStorage = new LockSettingsStorageTestable(mContext, new File(InstrumentationRegistry.getContext().getFilesDir(), "locksettings")); new File(origContext.getFilesDir(), "locksettings")); File storageDir = mStorage.mStorageDir; if (storageDir.exists()) { FileUtils.deleteContents(storageDir); Loading @@ -153,7 +160,7 @@ public abstract class BaseLockSettingsServiceTests { mService = new LockSettingsServiceTestable(mContext, mStorage, mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager, mSpManager, mAuthSecretService, mGsiService, mRecoverableKeyStoreManager, mUserManagerInternal, mDeviceStateCache, mSettings); mUserManagerInternal, mDeviceStateCache); mService.mHasSecureLockScreen = true; when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO); mPrimaryUserProfiles.add(PRIMARY_USER_INFO); Loading Loading @@ -186,10 +193,25 @@ public abstract class BaseLockSettingsServiceTests { mockBiometricsHardwareFingerprintsAndTemplates(PRIMARY_USER_ID); mockBiometricsHardwareFingerprintsAndTemplates(MANAGED_PROFILE_USER_ID); mSettings.setDeviceProvisioned(true); setDeviceProvisioned(true); mLocalService = LocalServices.getService(LockSettingsInternal.class); } protected void setDeviceProvisioned(boolean provisioned) { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, provisioned ? 1 : 0); } protected void setUserSetupComplete(boolean complete) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, complete ? 1 : 0, UserHandle.USER_SYSTEM); } protected void setSecureFrpMode(boolean secure) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.SECURE_FRP_MODE, secure ? 1 : 0, UserHandle.USER_SYSTEM); } private UserInfo installChildProfile(int profileId) { final UserInfo userInfo = new UserInfo( profileId, null, null, UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE); Loading
services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.javadeleted 100644 → 0 +0 −60 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.locksettings; import android.content.ContentResolver; import android.os.UserHandle; import android.provider.Settings; public class FakeSettings { private int mDeviceProvisioned; private int mSecureFrpMode; private int mUserSetupComplete; public void setDeviceProvisioned(boolean provisioned) { mDeviceProvisioned = provisioned ? 1 : 0; } public void setSecureFrpMode(boolean secure) { mSecureFrpMode = secure ? 1 : 0; } public void setUserSetupComplete(boolean complete) { mUserSetupComplete = complete ? 1 : 0; } public int globalGetInt(String keyName) { switch (keyName) { case Settings.Global.DEVICE_PROVISIONED: return mDeviceProvisioned; default: throw new IllegalArgumentException("Unhandled global settings: " + keyName); } } public int secureGetInt(ContentResolver contentResolver, String keyName, int defaultValue, int userId) { if (Settings.Secure.SECURE_FRP_MODE.equals(keyName) && userId == UserHandle.USER_SYSTEM) { return mSecureFrpMode; } if (Settings.Secure.USER_SETUP_COMPLETE.equals(keyName) && userId == UserHandle.USER_SYSTEM) { return mUserSetupComplete; } return defaultValue; } }