Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a6aa9bd authored by Eric Biggers's avatar Eric Biggers Committed by Android (Google) Code Review
Browse files

Merge "Remove on-demand initialization of synthetic password"

parents fa5de876 91a9ee48
Loading
Loading
Loading
Loading
+25 −45
Original line number Diff line number Diff line
@@ -240,8 +240,7 @@ public class LockSettingsService extends ILockSettings.Stub {
    protected final UserManager mUserManager;
    private final IStorageManager mStorageManager;
    private final IActivityManager mActivityManager;
    @VisibleForTesting
    protected final SyntheticPasswordManager mSpManager;
    private final SyntheticPasswordManager mSpManager;

    private final java.security.KeyStore mJavaKeyStore;
    private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
@@ -946,7 +945,7 @@ public class LockSettingsService extends ILockSettings.Stub {
                    if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
                        Slogf.i(TAG, "Creating locksettings state for user %d now that boot "
                                + "is complete", userId);
                        initializeSyntheticPasswordLocked(userId);
                        initializeSyntheticPassword(userId);
                    }
                }
            }
@@ -985,7 +984,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        long protectorId = getCurrentLskfBasedProtectorId(userId);
        if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) {
            Slogf.i(TAG, "Migrating unsecured user %d to SP-based credential", userId);
            initializeSyntheticPasswordLocked(userId);
            initializeSyntheticPassword(userId);
        } else {
            Slogf.i(TAG, "Existing unsecured user %d has a synthetic password; re-encrypting CE " +
                    "key with it", userId);
@@ -1652,13 +1651,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        Objects.requireNonNull(savedCredential);
        if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
        synchronized (mSpManager) {
            if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
                if (!savedCredential.isNone()) {
                    throw new IllegalStateException("Saved credential given, but user has no SP");
                }
                // TODO(b/232452368): this case is only needed by unit tests now; remove it.
                initializeSyntheticPasswordLocked(userId);
            } else if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) {
            if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) {
                // get credential from keystore when profile has unified lock
                try {
                    //TODO: remove as part of b/80170828
@@ -2322,9 +2315,7 @@ public class LockSettingsService extends ILockSettings.Stub {
                return;
            }
            removeStateForReusedUserIdIfNecessary(userId, userSerialNumber);
            synchronized (mSpManager) {
                initializeSyntheticPasswordLocked(userId);
            }
            initializeSyntheticPassword(userId);
        }
    }

@@ -2650,9 +2641,9 @@ public class LockSettingsService extends ILockSettings.Stub {
     * until the time when Weaver is guaranteed to be available), or when upgrading from Android 13
     * or earlier where users with no LSKF didn't necessarily have an SP.
     */
    @GuardedBy("mSpManager")
    @VisibleForTesting
    SyntheticPassword initializeSyntheticPasswordLocked(int userId) {
    SyntheticPassword initializeSyntheticPassword(int userId) {
        synchronized (mSpManager) {
            Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
            Preconditions.checkState(getCurrentLskfBasedProtectorId(userId) ==
                    SyntheticPasswordManager.NULL_PROTECTOR_ID,
@@ -2666,6 +2657,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            onSyntheticPasswordKnown(userId, sp);
            return sp;
        }
    }

    @VisibleForTesting
    long getCurrentLskfBasedProtectorId(int userId) {
@@ -2680,13 +2672,6 @@ public class LockSettingsService extends ILockSettings.Stub {
        setLong(LSKF_LAST_CHANGED_TIME_KEY, System.currentTimeMillis(), userId);
    }

    @VisibleForTesting
    boolean isSyntheticPasswordBasedCredential(int userId) {
        synchronized (mSpManager) {
            return isSyntheticPasswordBasedCredentialLocked(userId);
        }
    }

    private boolean isSyntheticPasswordBasedCredentialLocked(int userId) {
        if (userId == USER_FRP) {
            final int type = mStorage.readPersistentDataBlock().type;
@@ -2925,20 +2910,15 @@ public class LockSettingsService extends ILockSettings.Stub {
            @NonNull EscrowTokenStateChangeCallback callback) {
        if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId + ", type=" + type);
        synchronized (mSpManager) {
            // If the user has no LSKF, then the token can be activated immediately, after creating
            // the user's SP if it doesn't already exist.  Otherwise, the token can't be activated
            // until the SP is unlocked by another protector (normally the LSKF-based one).
            // If the user has no LSKF, then the token can be activated immediately.  Otherwise, the
            // token can't be activated until the SP is unlocked by another protector (normally the
            // LSKF-based one).
            SyntheticPassword sp = null;
            if (!isUserSecure(userId)) {
                long protectorId = getCurrentLskfBasedProtectorId(userId);
                if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) {
                    // TODO(b/232452368): this case is only needed by unit tests now; remove it.
                    sp = initializeSyntheticPasswordLocked(userId);
                } else {
                sp = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), protectorId,
                        LockscreenCredential.createNone(), userId, null).syntheticPassword;
            }
            }
            disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
            if (!mSpManager.hasEscrowData(userId)) {
                throw new SecurityException("Escrow token is disabled on the current user");
+81 −125

File changed.

Preview size limit exceeded, changes collapsed.

+4 −5
Original line number Diff line number Diff line
@@ -42,14 +42,13 @@ import org.junit.runner.RunWith;
public class LockscreenFrpTest extends BaseLockSettingsServiceTests {

    @Before
    public void setDeviceNotProvisioned() throws Exception {
    public void setUp() throws Exception {
        PropertyInvalidatedCache.disableForTestMode();

        // FRP credential can only be verified prior to provisioning
        setDeviceProvisioned(false);
    }

    @Before
    public void disableProcessCaches() {
        PropertyInvalidatedCache.disableForTestMode();
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
    }

    @Test
+34 −57
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server.locksettings;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
import static com.android.internal.widget.LockPatternUtils.CURRENT_LSKF_BASED_PROTECTOR_ID_KEY;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -59,9 +58,6 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;


/**
 * atest FrameworksServicesTests:SyntheticPasswordTests
@@ -127,21 +123,11 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        return mGateKeeperService.getSecureUserId(SyntheticPasswordManager.fakeUserId(userId)) != 0;
    }

    private boolean hasSyntheticPassword(int userId) throws RemoteException {
        return mService.getLong(CURRENT_LSKF_BASED_PROTECTOR_ID_KEY, 0, userId) != 0;
    }

    private void initializeCredential(LockscreenCredential password, int userId)
    private void initSpAndSetCredential(int userId, LockscreenCredential credential)
            throws RemoteException {
        assertTrue(mService.setLockCredential(password, nonePassword(), userId));
        assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId));
        assertTrue(mService.isSyntheticPasswordBasedCredential(userId));
    }

    protected void initializeSyntheticPassword(int userId) {
        synchronized (mService.mSpManager) {
            mService.initializeSyntheticPasswordLocked(userId);
        }
        mService.initializeSyntheticPassword(userId);
        assertTrue(mService.setLockCredential(credential, nonePassword(), userId));
        assertEquals(credential.getType(), mService.getCredentialType(userId));
    }

    // Tests that the FRP credential is updated when an LSKF-based protector is created for the user
@@ -149,7 +135,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    @Test
    public void testFrpCredentialSyncedIfDeviceProvisioned() throws RemoteException {
        setDeviceProvisioned(true);
        initializeSyntheticPassword(PRIMARY_USER_ID);
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        verify(mStorage.mPersistentDataBlockManager).setFrpCredentialHandle(any());
    }

@@ -159,7 +145,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    @Test
    public void testEmptyFrpCredentialNotSyncedIfDeviceNotProvisioned() throws RemoteException {
        setDeviceProvisioned(false);
        initializeSyntheticPassword(PRIMARY_USER_ID);
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        verify(mStorage.mPersistentDataBlockManager, never()).setFrpCredentialHandle(any());
    }

@@ -169,7 +155,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    @Test
    public void testNonEmptyFrpCredentialSyncedIfDeviceNotProvisioned() throws RemoteException {
        setDeviceProvisioned(false);
        initializeSyntheticPassword(PRIMARY_USER_ID);
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        verify(mStorage.mPersistentDataBlockManager, never()).setFrpCredentialHandle(any());
        mService.setLockCredential(newPassword("password"), nonePassword(), PRIMARY_USER_ID);
        verify(mStorage.mPersistentDataBlockManager).setFrpCredentialHandle(any());
@@ -180,7 +166,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        final LockscreenCredential password = newPassword("password");
        final LockscreenCredential newPassword = newPassword("newpassword");

        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
        mService.setLockCredential(newPassword, password, PRIMARY_USER_ID);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
@@ -193,7 +179,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential badPassword = newPassword("badpassword");

        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
        verify(mActivityManager).unlockUser2(eq(PRIMARY_USER_ID), any());
@@ -207,7 +193,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential badPassword = newPassword("newpassword");

        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
        // clear password
        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
@@ -225,7 +211,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential badPassword = newPassword("new");

        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        mService.setLockCredential(badPassword, password, PRIMARY_USER_ID);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
@@ -242,7 +228,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    public void testVerifyPassesPrimaryUserAuthSecret() throws RemoteException {
        LockscreenCredential password = newPassword("password");

        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        reset(mAuthSecretService);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
@@ -253,7 +239,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException {
        LockscreenCredential password = newPassword("password");

        initializeCredential(password, SECONDARY_USER_ID);
        initSpAndSetCredential(SECONDARY_USER_ID, password);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, SECONDARY_USER_ID, 0 /* flags */).getResponseCode());
        verify(mAuthSecretService, never()).setPrimaryUserCredential(any(byte[].class));
@@ -262,7 +248,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    @Test
    public void testUnlockUserKeyIfUnsecuredPassesPrimaryUserAuthSecret() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);

        reset(mAuthSecretService);
@@ -275,7 +261,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential pattern = newPattern("123654");
        byte[] token = "some-high-entropy-secure-token".getBytes();
        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        // Disregard any reportPasswordChanged() invocations as part of credential setup.
        flushHandlerTasks();
        reset(mDevicePolicyManager);
@@ -310,7 +296,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential pattern = newPattern("123654");
        byte[] token = "some-high-entropy-secure-token".getBytes();
        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);

        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
@@ -336,7 +322,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        LockscreenCredential pattern = newPattern("123654");
        LockscreenCredential newPassword = newPassword("password");
        byte[] token = "some-high-entropy-secure-token".getBytes();
        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);

        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
@@ -356,38 +342,20 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    }

    @Test
    public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration()
            throws RemoteException {
        final byte[] token = "some-high-entropy-secure-token".getBytes();
        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
        assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
        assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
    }

    @Test
    public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration()
            throws RemoteException {
    public void testEscrowTokenActivatedImmediatelyIfNoUserPassword() throws RemoteException {
        final byte[] token = "some-high-entropy-secure-token".getBytes();
        // By first setting a password and then clearing it, we enter the state where SP is
        // initialized but the user currently has no password
        initializeCredential(newPassword("password"), PRIMARY_USER_ID);
        assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
                PRIMARY_USER_ID));
        assertTrue(mService.isSyntheticPasswordBasedCredential(PRIMARY_USER_ID));

        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
        assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
        assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
    }

    @Test
    public void testEscrowTokenActivatedLaterWithUserPassword() throws RemoteException {
        byte[] token = "some-high-entropy-secure-token".getBytes();
        LockscreenCredential password = newPassword("password");
        mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID);

        initSpAndSetCredential(PRIMARY_USER_ID, password);
        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        // Token not activated immediately since user password exists
        assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
@@ -407,6 +375,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        when(mUserManagerInternal.isUserManaged(PRIMARY_USER_ID)).thenReturn(false);
        when(mDeviceStateCache.isDeviceProvisioned()).thenReturn(true);

        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        try {
            mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
            fail("Escrow token should not be possible on unmanaged device");
@@ -421,7 +390,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {

        LockscreenCredential password = newPassword("password");
        LockscreenCredential pattern = newPattern("123654");
        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);

        long handle0 = mLocalService.addEscrowToken(token0, PRIMARY_USER_ID, null);
        long handle1 = mLocalService.addEscrowToken(token1, PRIMARY_USER_ID, null);
@@ -450,6 +419,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
        byte[] token = "some-high-entropy-secure-token".getBytes();

        mService.mHasSecureLockScreen = false;
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));

@@ -473,7 +443,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    @Test
    public void testGetHashFactorPrimaryUser() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
        assertNotNull(hashFactor);

@@ -486,6 +456,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {

    @Test
    public void testGetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        mService.initializeSyntheticPassword(MANAGED_PROFILE_USER_ID);

        LockscreenCredential pattern = newPattern("1236");
        mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
@@ -494,6 +467,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {

    @Test
    public void testGetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        mService.initializeSyntheticPassword(MANAGED_PROFILE_USER_ID);

        LockscreenCredential primaryPassword = newPassword("primary");
        LockscreenCredential profilePassword = newPassword("profile");
        mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID);
@@ -594,7 +570,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {

        LockscreenCredential password = newPassword("testGsiDisablesAuthSecret-password");

        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
        verify(mAuthSecretService, never()).setPrimaryUserCredential(any(byte[].class));
@@ -604,7 +580,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    public void testUnlockUserWithToken() throws Exception {
        LockscreenCredential password = newPassword("password");
        byte[] token = "some-high-entropy-secure-token".getBytes();
        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        // Disregard any reportPasswordChanged() invocations as part of credential setup.
        flushHandlerTasks();
        reset(mDevicePolicyManager);
@@ -625,7 +601,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    @Test
    public void testPasswordChange_NoOrphanedFilesLeft() throws Exception {
        LockscreenCredential password = newPassword("password");
        initializeCredential(password, PRIMARY_USER_ID);
        initSpAndSetCredential(PRIMARY_USER_ID, password);
        assertTrue(mService.setLockCredential(password, password, PRIMARY_USER_ID));
        assertNoOrphanedFilesLeft(PRIMARY_USER_ID);
    }
@@ -633,6 +609,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
    @Test
    public void testAddingEscrowToken_NoOrphanedFilesLeft() throws Exception {
        final byte[] token = "some-high-entropy-secure-token".getBytes();
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
        for (int i = 0; i < 16; i++) {
            long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
            assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+6 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import com.android.internal.widget.IWeakEscrowTokenRemovedListener;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.VerifyCredentialResponse;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@@ -49,6 +50,11 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class WeakEscrowTokenTests extends BaseLockSettingsServiceTests{

    @Before
    public void setUp() {
        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
    }

    @Test
    public void testWeakTokenActivatedImmediatelyIfNoUserPassword()
            throws RemoteException {
Loading