/*
 * Copyright (C) 2017 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 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.SYNTHETIC_PASSWORD_ENABLED_KEY;
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.admin.PasswordMetrics;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
import com.android.server.locksettings.SyntheticPasswordManager.PasswordData;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

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


/**
 * atest FrameworksServicesTests:SyntheticPasswordTests
 */
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {

    public static final byte[] PAYLOAD = new byte[] {1, 2, -1, -2, 55};
    public static final byte[] PAYLOAD2 = new byte[] {2, 3, -2, -3, 44, 1};

    @Test
    public void testPasswordBasedSyntheticPassword() throws RemoteException {
        final int USER_ID = 10;
        final LockscreenCredential password = newPassword("user-password");
        final LockscreenCredential badPassword = newPassword("bad-password");
        MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage,
                mGateKeeperService, mUserManager, mPasswordSlotManager);
        AuthenticationToken authToken = manager.newSyntheticPasswordAndSid(mGateKeeperService, null,
                null, USER_ID);
        long handle = manager.createPasswordBasedSyntheticPassword(mGateKeeperService,
                password, authToken, USER_ID);

        AuthenticationResult result = manager.unwrapPasswordBasedSyntheticPassword(
                mGateKeeperService, handle, password, USER_ID, null);
        assertArrayEquals(result.authToken.deriveKeyStorePassword(),
                authToken.deriveKeyStorePassword());

        result = manager.unwrapPasswordBasedSyntheticPassword(mGateKeeperService, handle,
                badPassword, USER_ID, null);
        assertNull(result.authToken);
    }

    private void disableSyntheticPassword() throws RemoteException {
        mService.setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
    }

    private void enableSyntheticPassword() throws RemoteException {
        mService.setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
    }

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

    protected void initializeCredentialUnderSP(LockscreenCredential password, int userId)
            throws RemoteException {
        enableSyntheticPassword();
        assertTrue(mService.setLockCredential(password, nonePassword(), userId));
        assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId));
        assertTrue(mService.isSyntheticPasswordBasedCredential(userId));
    }

    @Test
    public void testSyntheticPasswordChangeCredential() throws RemoteException {
        final LockscreenCredential password = newPassword("password");
        final LockscreenCredential newPassword = newPassword("newpassword");

        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
        mService.setLockCredential(newPassword, password, PRIMARY_USER_ID);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                newPassword, 0, PRIMARY_USER_ID)
                        .getResponseCode());
        assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
    }

    @Test
    public void testSyntheticPasswordVerifyCredential() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential badPassword = newPassword("badpassword");

        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, 0, PRIMARY_USER_ID)
                        .getResponseCode());

        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
                badPassword, 0, PRIMARY_USER_ID)
                        .getResponseCode());
    }

    @Test
    public void testSyntheticPasswordClearCredential() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential badPassword = newPassword("newpassword");

        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
        // clear password
        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
        assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));

        // set a new password
        mService.setLockCredential(badPassword, nonePassword(), PRIMARY_USER_ID);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                badPassword, 0, PRIMARY_USER_ID)
                        .getResponseCode());
        assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
    }

    @Test
    public void testSyntheticPasswordChangeCredentialKeepsAuthSecret() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential badPassword = newPassword("new");

        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        mService.setLockCredential(badPassword, password, PRIMARY_USER_ID);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                badPassword, 0, PRIMARY_USER_ID)
                        .getResponseCode());

        // Check the same secret was passed each time
        ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
        verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture());
        assertEquals(1, secret.getAllValues().stream().distinct().count());
    }

    @Test
    public void testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential newPassword = newPassword("new");

        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        reset(mAuthSecretService);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, 0, PRIMARY_USER_ID)
                        .getResponseCode());
        verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
    }

    @Test
    public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException {
        LockscreenCredential password = newPassword("password");

        initializeCredentialUnderSP(password, SECONDARY_USER_ID);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, 0, SECONDARY_USER_ID)
                        .getResponseCode());
        verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
    }

    @Test
    public void testNoSyntheticPasswordOrCredentialDoesNotPassAuthSecret() throws RemoteException {
        mService.onUnlockUser(PRIMARY_USER_ID);
        flushHandlerTasks();
        verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
    }

    @Test
    public void testSyntheticPasswordAndCredentialDoesNotPassAuthSecret() throws RemoteException {
        LockscreenCredential password = newPassword("passwordForASyntheticPassword");
        initializeCredentialUnderSP(password, PRIMARY_USER_ID);

        reset(mAuthSecretService);
        mService.onUnlockUser(PRIMARY_USER_ID);
        flushHandlerTasks();
        verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
    }

    @Test
    public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException {
        LockscreenCredential password = newPassword("getASyntheticPassword");
        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);

        reset(mAuthSecretService);
        mService.onUnlockUser(PRIMARY_USER_ID);
        flushHandlerTasks();
        verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
    }

    @Test
    public void testTokenBasedResetPassword() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential pattern = newPattern("123654");
        byte[] token = "some-high-entropy-secure-token".getBytes();
        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        // Disregard any reportPasswordChanged() invocations as part of credential setup.
        flushHandlerTasks();
        reset(mDevicePolicyManager);

        byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);

        assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
        assertTrue(mService.hasPendingEscrowToken(PRIMARY_USER_ID));

        mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
        assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
        assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));

        mLocalService.setLockCredentialWithToken(pattern, handle, token, PRIMARY_USER_ID);

        // Verify DPM gets notified about new device lock
        flushHandlerTasks();
        final PasswordMetrics metric = PasswordMetrics.computeForCredential(pattern);
        assertEquals(metric, mService.getUserPasswordMetrics(PRIMARY_USER_ID));
        verify(mDevicePolicyManager).reportPasswordChanged(PRIMARY_USER_ID);

        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                pattern, 0, PRIMARY_USER_ID)
                    .getResponseCode());
        assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
    }

    @Test
    public void testTokenBasedClearPassword() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential pattern = newPattern("123654");
        byte[] token = "some-high-entropy-secure-token".getBytes();
        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);

        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));

        mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
        assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));

        mLocalService.setLockCredentialWithToken(nonePassword(), handle, token, PRIMARY_USER_ID);
        flushHandlerTasks(); // flush the unlockUser() call before changing password again
        mLocalService.setLockCredentialWithToken(pattern, handle, token,
                PRIMARY_USER_ID);

        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                pattern, 0, PRIMARY_USER_ID)
                        .getResponseCode());
        assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
    }

    @Test
    public void testTokenBasedResetPasswordAfterCredentialChanges() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential pattern = newPattern("123654");
        LockscreenCredential newPassword = newPassword("password");
        byte[] token = "some-high-entropy-secure-token".getBytes();
        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);

        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));

        mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
        assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));

        mService.setLockCredential(pattern, password, PRIMARY_USER_ID);

        mLocalService.setLockCredentialWithToken(newPassword, handle, token, PRIMARY_USER_ID);

        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                newPassword, 0, PRIMARY_USER_ID)
                    .getResponseCode());
        assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
    }

    @Test
    public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration()
            throws RemoteException {
        final byte[] token = "some-high-entropy-secure-token".getBytes();
        enableSyntheticPassword();
        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 {
        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
        initializeCredentialUnderSP(newPassword("password"), PRIMARY_USER_ID);
        assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
                PRIMARY_USER_ID));
        assertTrue(mService.isSyntheticPasswordBasedCredential(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 testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration()
            throws RemoteException {
        byte[] token = "some-high-entropy-secure-token".getBytes();
        LockscreenCredential password = newPassword("password");
        // Set up pre-SP user password
        disableSyntheticPassword();
        mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID);
        enableSyntheticPassword();

        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        // Token not activated immediately since user password exists
        assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
        // Activate token (password gets migrated to SP at the same time)
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, 0, PRIMARY_USER_ID)
                    .getResponseCode());
        // Verify token is activated
        assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
    }

    @Test
    public void testEscrowTokenCannotBeActivatedOnUnmanagedUser() {
        byte[] token = "some-high-entropy-secure-token".getBytes();
        when(mUserManagerInternal.isDeviceManaged()).thenReturn(false);
        when(mUserManagerInternal.isUserManaged(PRIMARY_USER_ID)).thenReturn(false);
        when(mDeviceStateCache.isDeviceProvisioned()).thenReturn(true);

        try {
            mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
            fail("Escrow token should not be possible on unmanaged device");
        } catch (SecurityException expected) { }
    }

    @Test
    public void testSetLockCredentialWithTokenFailsWithoutLockScreen() throws Exception {
        LockscreenCredential password = newPassword("password");
        LockscreenCredential pattern = newPattern("123654");
        byte[] token = "some-high-entropy-secure-token".getBytes();

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

        try {
            mLocalService.setLockCredentialWithToken(password, handle, token, PRIMARY_USER_ID);
            fail("An exception should have been thrown.");
        } catch (UnsupportedOperationException e) {
            // Success - the exception was expected.
        }
        assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));

        try {
            mLocalService.setLockCredentialWithToken(pattern, handle, token, PRIMARY_USER_ID);
            fail("An exception should have been thrown.");
        } catch (UnsupportedOperationException e) {
            // Success - the exception was expected.
        }
        assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));
    }

    @Test
    public void testGetHashFactorPrimaryUser() throws RemoteException {
        LockscreenCredential password = newPassword("password");
        mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID);
        byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
        assertNotNull(hashFactor);

        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
        byte[] newHashFactor = mService.getHashFactor(nonePassword(), PRIMARY_USER_ID);
        assertNotNull(newHashFactor);
        // Hash factor should never change after password change/removal
        assertArrayEquals(hashFactor, newHashFactor);
    }

    @Test
    public void testGetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
        LockscreenCredential pattern = newPattern("1236");
        mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
        assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
    }

    @Test
    public void testGetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
        LockscreenCredential primaryPassword = newPassword("primary");
        LockscreenCredential profilePassword = newPassword("profile");
        mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID);
        mService.setLockCredential(profilePassword, nonePassword(), MANAGED_PROFILE_USER_ID);
        assertNotNull(
                mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID));
    }

    @Test
    public void testPasswordData_serializeDeserialize() {
        PasswordData data = new PasswordData();
        data.scryptN = 11;
        data.scryptR = 22;
        data.scryptP = 33;
        data.credentialType = CREDENTIAL_TYPE_PASSWORD;
        data.salt = PAYLOAD;
        data.passwordHandle = PAYLOAD2;

        PasswordData deserialized = PasswordData.fromBytes(data.toBytes());

        assertEquals(11, deserialized.scryptN);
        assertEquals(22, deserialized.scryptR);
        assertEquals(33, deserialized.scryptP);
        assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.credentialType);
        assertArrayEquals(PAYLOAD, deserialized.salt);
        assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
    }

    @Test
    public void testPasswordData_deserialize() {
        // Test that we can deserialize existing PasswordData and don't inadvertently change the
        // wire format.
        byte[] serialized = new byte[] {
                0, 0, 0, 2, /* CREDENTIAL_TYPE_PASSWORD_OR_PIN */
                11, /* scryptN */
                22, /* scryptR */
                33, /* scryptP */
                0, 0, 0, 5, /* salt.length */
                1, 2, -1, -2, 55, /* salt */
                0, 0, 0, 6, /* passwordHandle.length */
                2, 3, -2, -3, 44, 1, /* passwordHandle */
        };
        PasswordData deserialized = PasswordData.fromBytes(serialized);

        assertEquals(11, deserialized.scryptN);
        assertEquals(22, deserialized.scryptR);
        assertEquals(33, deserialized.scryptP);
        assertEquals(CREDENTIAL_TYPE_PASSWORD_OR_PIN, deserialized.credentialType);
        assertArrayEquals(PAYLOAD, deserialized.salt);
        assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
    }

    @Test
    public void testGsiDisablesAuthSecret() throws RemoteException {
        mGsiService.setIsGsiRunning(true);

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

        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                password, 0, PRIMARY_USER_ID)
                        .getResponseCode());
        verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
    }

    @Test
    public void testUnlockUserWithToken() throws Exception {
        LockscreenCredential password = newPassword("password");
        byte[] token = "some-high-entropy-secure-token".getBytes();
        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        // Disregard any reportPasswordChanged() invocations as part of credential setup.
        flushHandlerTasks();
        reset(mDevicePolicyManager);

        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
        mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
        assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));

        mService.onCleanupUser(PRIMARY_USER_ID);
        assertNull(mLocalService.getUserPasswordMetrics(PRIMARY_USER_ID));

        assertTrue(mLocalService.unlockUserWithToken(handle, token, PRIMARY_USER_ID));
        assertEquals(PasswordMetrics.computeForCredential(password),
                mLocalService.getUserPasswordMetrics(PRIMARY_USER_ID));
    }

    @Test
    public void testPasswordChange_NoOrphanedFilesLeft() throws Exception {
        LockscreenCredential password = newPassword("password");
        initializeCredentialUnderSP(password, PRIMARY_USER_ID);
        assertTrue(mService.setLockCredential(password, password, PRIMARY_USER_ID));
        assertNoOrphanedFilesLeft(PRIMARY_USER_ID);
    }

    @Test
    public void testAddingEscrowToken_NoOrphanedFilesLeft() throws Exception {
        final byte[] token = "some-high-entropy-secure-token".getBytes();
        for (int i = 0; i < 16; i++) {
            long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
            assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
            mLocalService.removeEscrowToken(handle, PRIMARY_USER_ID);
        }
        assertNoOrphanedFilesLeft(PRIMARY_USER_ID);
    }

    private void assertNoOrphanedFilesLeft(int userId) {
        String handleString = String.format("%016x",
                mService.getSyntheticPasswordHandleLocked(userId));
        File directory = mStorage.getSyntheticPasswordDirectoryForUser(userId);
        for (File file : directory.listFiles()) {
            String[] parts = file.getName().split("\\.");
            if (!parts[0].equals(handleString) && !parts[0].equals("0000000000000000")) {
                fail("Orphaned state left: " + file.getName());
            }
        }
    }

    // b/62213311
    //TODO: add non-migration work profile case, and unify/un-unify transition.
    //TODO: test token after user resets password
    //TODO: test token based reset after unified work challenge
    //TODO: test clear password after unified work challenge
}
