/*
 * Copyright (C) 2009 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 android.accounts.cts;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorDescription;
import android.accounts.AuthenticatorException;
import android.accounts.OnAccountsUpdateListener;
import android.accounts.OperationCanceledException;
import android.accounts.cts.common.Fixtures;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.StrictMode;
import android.platform.test.annotations.Presubmit;
import android.test.ActivityInstrumentationTestCase2;

import java.io.IOException;
import java.lang.Math;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * You can run those unit tests with the following command line:
 *
 *  adb shell am instrument
 *   -e debug false -w
 *   -e class android.accounts.cts.AccountManagerTest
 * android.accounts.cts/android.support.test.runner.AndroidJUnitRunner
 */
public class AccountManagerTest extends ActivityInstrumentationTestCase2<AccountDummyActivity> {

    public static final String ACCOUNT_NAME = "android.accounts.cts.account.name";
    public static final String ACCOUNT_NEW_NAME = "android.accounts.cts.account.name.rename";
    public static final String ACCOUNT_NAME_OTHER = "android.accounts.cts.account.name.other";

    public static final String ACCOUNT_TYPE = "android.accounts.cts.account.type";
    public static final String ACCOUNT_TYPE_CUSTOM = "android.accounts.cts.custom.account.type";
    public static final String ACCOUNT_TYPE_ABSENT = "android.accounts.cts.account.type.absent";

    public static final String ACCOUNT_PASSWORD = "android.accounts.cts.account.password";

    public static final String ACCOUNT_STATUS_TOKEN = "android.accounts.cts.account.status.token";

    public static final String AUTH_TOKEN_TYPE = "mockAuthTokenType";
    public static final String AUTH_EXPIRING_TOKEN_TYPE = "mockAuthExpiringTokenType";
    public static final String AUTH_TOKEN_LABEL = "mockAuthTokenLabel";
    public static final long AUTH_TOKEN_DURATION_MILLIS = 10000L; // Ten seconds.

    public static final String FEATURE_1 = "feature.1";
    public static final String FEATURE_2 = "feature.2";
    public static final String NON_EXISTING_FEATURE = "feature.3";

    public static final String OPTION_NAME_1 = "option.name.1";
    public static final String OPTION_VALUE_1 = "option.value.1";

    public static final String OPTION_NAME_2 = "option.name.2";
    public static final String OPTION_VALUE_2 = "option.value.2";

    public static final String[] REQUIRED_FEATURES = new String[] { FEATURE_1, FEATURE_2 };

    public static final Bundle OPTIONS_BUNDLE = new Bundle();

    public static final Bundle USERDATA_BUNDLE = new Bundle();

    public static final String USERDATA_NAME_1 = "user.data.name.1";
    public static final String USERDATA_NAME_2 = "user.data.name.2";
    public static final String USERDATA_VALUE_1 = "user.data.value.1";
    public static final String USERDATA_VALUE_2 = "user.data.value.2";

    public static final Account ACCOUNT = new Account(ACCOUNT_NAME, ACCOUNT_TYPE);
    public static final Account ACCOUNT_FOR_NEW_REMOVE_ACCOUNT_API = new Account(
            MockAccountAuthenticator.ACCOUNT_NAME_FOR_NEW_REMOVE_API, ACCOUNT_TYPE);
    public static final Account ACCOUNT_FOR_DEFAULT_IMPL = new Account(
            MockAccountAuthenticator.ACCOUNT_NAME_FOR_DEFAULT_IMPL, ACCOUNT_TYPE);
    public static final Account ACCOUNT_SAME_TYPE = new Account(ACCOUNT_NAME_OTHER, ACCOUNT_TYPE);

    public static final Account CUSTOM_TOKEN_ACCOUNT =
            new Account(ACCOUNT_NAME,ACCOUNT_TYPE_CUSTOM);

    // Installed packages to test visibility API.
    public static final String PACKAGE_NAME_1 = "android.accounts.cts.unaffiliated";
    public static final String PACKAGE_NAME_PRIVILEGED = "android.accounts.cts"; // authenticator

    public static final Bundle SESSION_BUNDLE = new Bundle();
    public static final String SESSION_DATA_NAME_1 = "session.data.name.1";
    public static final String SESSION_DATA_VALUE_1 = "session.data.value.1";

    public static final String ERROR_MESSAGE = "android.accounts.cts.account.error.message";

    public static final String KEY_CIPHER = "cipher";
    public static final String KEY_MAC = "mac";

    private static MockAccountAuthenticator mockAuthenticator;
    private static final int LATCH_TIMEOUT_MS = 1000;
    private static AccountManager am;

    public synchronized static MockAccountAuthenticator getMockAuthenticator(Context context) {
        if (null == mockAuthenticator) {
            mockAuthenticator = new MockAccountAuthenticator(context);
        }
        return mockAuthenticator;
    }

    private Activity mActivity;
    private Context mContext;

    public AccountManagerTest() {
        super(AccountDummyActivity.class);
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();
        mActivity = getActivity();
        mContext = getInstrumentation().getTargetContext();

        OPTIONS_BUNDLE.putString(OPTION_NAME_1, OPTION_VALUE_1);
        OPTIONS_BUNDLE.putString(OPTION_NAME_2, OPTION_VALUE_2);

        USERDATA_BUNDLE.putString(USERDATA_NAME_1, USERDATA_VALUE_1);

        SESSION_BUNDLE.putString(SESSION_DATA_NAME_1, SESSION_DATA_VALUE_1);
        SESSION_BUNDLE.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);

        getMockAuthenticator(mContext);

        am = AccountManager.get(mContext);
    }

    @Override
    public void tearDown() throws Exception, AuthenticatorException, OperationCanceledException {
        mockAuthenticator.clearData();

        // Need to clean up created account
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));
        assertTrue(removeAccount(am, ACCOUNT_SAME_TYPE, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        // Clean out any other accounts added during the tests.
        Account[] ctsAccounts = am.getAccountsByType(ACCOUNT_TYPE);
        Account[] ctsCustomAccounts = am.getAccountsByType(ACCOUNT_TYPE_CUSTOM);
        ArrayList<Account> accounts = new ArrayList<>(Arrays.asList(ctsAccounts));
        accounts.addAll(Arrays.asList(ctsCustomAccounts));
        for (Account ctsAccount : accounts) {
            removeAccount(am, ctsAccount, mActivity, null /* callback */);
        }

        // need to clean up the authenticator cached data
        mockAuthenticator.clearData();

        super.tearDown();
    }

    interface TokenFetcher {
        public Bundle fetch(String tokenType)
                throws OperationCanceledException, AuthenticatorException, IOException;
        public Account getAccount();
    }

    private void validateSuccessfulTokenFetchingLifecycle(TokenFetcher fetcher, String tokenType)
            throws OperationCanceledException, AuthenticatorException, IOException {
        Account account = fetcher.getAccount();
        Bundle expected = new Bundle();
        expected.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
        expected.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);

        // First fetch.
        Bundle actual = fetcher.fetch(tokenType);
        assertTrue(mockAuthenticator.isRecentlyCalled());
        validateAccountAndAuthTokenResult(expected, actual);

        /*
         * On the second fetch the cache will be populated if we are using a authenticator with
         * customTokens=false or we are using a scope that will cause the authenticator to set an
         * expiration time (and that expiration time hasn't been reached).
         */
        actual = fetcher.fetch(tokenType);

        boolean isCachingExpected =
                ACCOUNT_TYPE.equals(account.type) || AUTH_EXPIRING_TOKEN_TYPE.equals(tokenType);
        assertEquals(isCachingExpected, !mockAuthenticator.isRecentlyCalled());
        validateAccountAndAuthTokenResult(expected, actual);

        try {
            // Delay further execution until expiring tokens can actually expire.
            Thread.sleep(mockAuthenticator.getTokenDurationMillis() + 50L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        /*
         * With the time shift above, the third request will result in cache hits only from
         * customToken=false authenticators.
         */
        actual = fetcher.fetch(tokenType);
        isCachingExpected = ACCOUNT_TYPE.equals(account.type);
        assertEquals(isCachingExpected, !mockAuthenticator.isRecentlyCalled());
        validateAccountAndAuthTokenResult(expected, actual);

        // invalidate token
        String token = actual.getString(AccountManager.KEY_AUTHTOKEN);
        am.invalidateAuthToken(account.type, token);

        /*
         * Upon invalidating the token, the cache should be clear regardless of authenticator.
         */
        actual = fetcher.fetch(tokenType);
        assertTrue(mockAuthenticator.isRecentlyCalled());
        validateAccountAndAuthTokenResult(expected, actual);
    }

    private void validateAccountAndAuthTokenResult(Bundle actual) {
        assertEquals(
                ACCOUNT.name,
                actual.get(AccountManager.KEY_ACCOUNT_NAME));
        assertEquals(
                ACCOUNT.type,
                actual.get(AccountManager.KEY_ACCOUNT_TYPE));
        assertEquals(
                mockAuthenticator.getLastTokenServed(),
                actual.get(AccountManager.KEY_AUTHTOKEN));
    }

    private void validateAccountAndAuthTokenResult(Bundle expected, Bundle actual) {
        assertEquals(
                expected.get(AccountManager.KEY_ACCOUNT_NAME),
                actual.get(AccountManager.KEY_ACCOUNT_NAME));
        assertEquals(
                expected.get(AccountManager.KEY_ACCOUNT_TYPE),
                actual.get(AccountManager.KEY_ACCOUNT_TYPE));
        assertEquals(
                mockAuthenticator.getLastTokenServed(),
                actual.get(AccountManager.KEY_AUTHTOKEN));
    }

    private void validateAccountAndNoAuthTokenResult(Bundle result) {
        assertEquals(ACCOUNT_NAME, result.get(AccountManager.KEY_ACCOUNT_NAME));
        assertEquals(ACCOUNT_TYPE, result.get(AccountManager.KEY_ACCOUNT_TYPE));
        assertNull(result.get(AccountManager.KEY_AUTHTOKEN));
    }

    private void validateNullResult(Bundle resultBundle) {
        assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_NAME));
        assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_TYPE));
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
    }

    private void validateAccountAndAuthTokenType() {
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
        assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
    }

    private void validateFeatures() {
        assertEquals(REQUIRED_FEATURES[0], mockAuthenticator.getRequiredFeatures()[0]);
        assertEquals(REQUIRED_FEATURES[1], mockAuthenticator.getRequiredFeatures()[1]);
    }

    private void validateOptions(Bundle expectedOptions, Bundle actualOptions) {
        // In ICS AccountManager may add options to indicate the caller id.
        // We only validate that the passed in options are present in the actual ones
        if (expectedOptions != null) {
            assertNotNull(actualOptions);
            assertEquals(expectedOptions.get(OPTION_NAME_1), actualOptions.get(OPTION_NAME_1));
            assertEquals(expectedOptions.get(OPTION_NAME_2), actualOptions.get(OPTION_NAME_2));
        }
    }

    private void validateSystemOptions(Bundle options) {
        assertNotNull(options.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME));
        assertTrue(options.containsKey(AccountManager.KEY_CALLER_UID));
        assertTrue(options.containsKey(AccountManager.KEY_CALLER_PID));
    }

    private void validateCredentials() {
        assertEquals(ACCOUNT, mockAuthenticator.getAccount());
    }

    private int getAccountsCount() {
        Account[] accounts = am.getAccounts();
        assertNotNull(accounts);
        return accounts.length;
    }

    private Bundle addAccount(AccountManager am, String accountType, String authTokenType,
            String[] requiredFeatures, Bundle options, Activity activity,
            AccountManagerCallback<Bundle> callback, Handler handler) throws
                IOException, AuthenticatorException, OperationCanceledException {

        AccountManagerFuture<Bundle> futureBundle = am.addAccount(
                accountType,
                authTokenType,
                requiredFeatures,
                options,
                activity,
                callback,
                handler);

        Bundle resultBundle = futureBundle.getResult();
        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        return resultBundle;
    }

    private Account renameAccount(AccountManager am, Account account, String newName)
            throws OperationCanceledException, AuthenticatorException, IOException {
        AccountManagerFuture<Account> futureAccount = am.renameAccount(
                account, newName, null /* callback */, null /* handler */);
        Account renamedAccount = futureAccount.getResult();
        assertTrue(futureAccount.isDone());
        assertNotNull(renamedAccount);
        return renamedAccount;
    }

    private boolean removeAccount(AccountManager am, Account account,
            AccountManagerCallback<Boolean> callback) throws IOException, AuthenticatorException,
                OperationCanceledException {
        AccountManagerFuture<Boolean> futureBoolean = am.removeAccount(account,
                callback,
                null /* handler */);
        Boolean resultBoolean = futureBoolean.getResult();
        assertTrue(futureBoolean.isDone());

        return resultBoolean;
    }

    private Bundle removeAccountWithIntentLaunch(AccountManager am, Account account,
            Activity activity, AccountManagerCallback<Bundle> callback) throws IOException,
            AuthenticatorException, OperationCanceledException {

        AccountManagerFuture<Bundle> futureBundle = am.removeAccount(account,
                activity,
                callback,
                null /* handler */);
        Bundle resultBundle = futureBundle.getResult();
        assertTrue(futureBundle.isDone());

        return resultBundle;
    }

    private Bundle removeAccount(AccountManager am, Account account, Activity activity,
            AccountManagerCallback<Bundle> callback) throws IOException, AuthenticatorException,
                OperationCanceledException {

        AccountManagerFuture<Bundle> futureBundle = am.removeAccount(account,
                activity,
                callback,
                null /* handler */);
        Bundle resultBundle = futureBundle.getResult();
        assertTrue(futureBundle.isDone());

        return resultBundle;
    }

    private boolean removeAccountExplicitly(AccountManager am, Account account) {
        return am.removeAccountExplicitly(account);
    }

    private void addAccountExplicitly(Account account, String password, Bundle userdata) {
        assertTrue(am.addAccountExplicitly(account, password, userdata));
    }

    private Bundle getAuthTokenByFeature(String[] features, Activity activity)
            throws IOException, AuthenticatorException, OperationCanceledException {

        AccountManagerFuture<Bundle> futureBundle = am.getAuthTokenByFeatures(ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                features,
                activity,
                OPTIONS_BUNDLE,
                OPTIONS_BUNDLE,
                null /* no callback */,
                null /* no handler */
        );

        Bundle resultBundle = futureBundle.getResult();

        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        return resultBundle;
    }

    private boolean isAccountPresent(Account[] accounts, Account accountToCheck) {
        if (null == accounts || null == accountToCheck) {
            return false;
        }
        boolean result = false;
        int length = accounts.length;
        for (int n=0; n<length; n++) {
            if(accountToCheck.equals(accounts[n])) {
                result = true;
                break;
            }
        }
        return result;
    }

    /**
     * Test singleton
     */
    public void testGet() {
        assertNotNull(AccountManager.get(mContext));
    }

    /**
     * Test creation of intent
     */
    public void testNewChooseAccountIntent() {
        Intent intent = AccountManager.newChooseAccountIntent(null, null, null,
                null, null,
                null, null);
        assertNotNull(intent);
    }

    /**
     * Test creation of intent
     */
    public void testNewChooseAccountIntentDepracated() {
        Intent intent = AccountManager.newChooseAccountIntent(null, null, null, false,
                null, null,
                null, null);
        assertNotNull(intent);
    }

    /**
     * Test a basic addAccount()
     */
    public void testAddAccount() throws IOException, AuthenticatorException,
            OperationCanceledException {

        Bundle resultBundle = addAccount(am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                OPTIONS_BUNDLE,
                mActivity,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        validateAccountAndAuthTokenType();
        validateFeatures();
        validateOptions(OPTIONS_BUNDLE, mockAuthenticator.mOptionsAddAccount);
        validateSystemOptions(mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);

        // Assert returned result
        validateAccountAndNoAuthTokenResult(resultBundle);
    }

    /**
     * Test addAccount() with callback and handler
     */
    public void testAddAccountWithCallbackAndHandler() throws IOException,
            AuthenticatorException, OperationCanceledException {

        testAddAccountWithCallbackAndHandler(null /* handler */);
        testAddAccountWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    /**
     * Test addAccount() with no associated account authenticator
     */
    public void testAddAccountWithNoAuthenticator() throws IOException,
            AuthenticatorException, OperationCanceledException {

        try {
            AccountManagerFuture<Bundle> futureBundle = am.addAccount(
                    "nonExistingAccountType",
                    null,
                    null,
                    null,
                    null,
                    null,
                    null);

            futureBundle.getResult();
            fail();
        } catch (AuthenticatorException expectedException) {
            return;
        }
    }

    private void testAddAccountWithCallbackAndHandler(Handler handler) throws IOException,
            AuthenticatorException, OperationCanceledException {

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = null;
                try {
                    resultBundle = bundleFuture.getResult();
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    fail("should not throw an AuthenticatorException");
                }

                // Assert parameters has been passed correctly
                validateAccountAndAuthTokenType();
                validateFeatures();
                validateOptions(OPTIONS_BUNDLE, mockAuthenticator.mOptionsAddAccount);
                validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
                validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
                validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);

                // Assert return result
                validateAccountAndNoAuthTokenResult(resultBundle);

                latch.countDown();
            }
        };

        addAccount(am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                OPTIONS_BUNDLE,
                mActivity,
                callback,
                handler);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    /**
     * Test addAccountExplicitly(), renameAccount() and removeAccount().
     */
    public void testAddAccountExplicitlyAndRemoveAccount() throws IOException,
            AuthenticatorException, OperationCanceledException {

        final int expectedAccountsCount = getAccountsCount();

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Assert that we have one more account
        Account[] accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(1 + expectedAccountsCount, accounts.length);
        assertTrue(isAccountPresent(am.getAccounts(), ACCOUNT));
        // Need to clean up
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        // and verify that we go back to the initial state
        accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(expectedAccountsCount, accounts.length);
    }

    /**
     * Test addAccountExplicitly(), renameAccount() and removeAccount().
     */
    public void testAddAccountExplicitlyAndRemoveAccountWithNewApi() throws IOException,
            AuthenticatorException, OperationCanceledException {

        final int expectedAccountsCount = getAccountsCount();

        addAccountExplicitly(ACCOUNT_FOR_NEW_REMOVE_ACCOUNT_API, ACCOUNT_PASSWORD, null /* userData */);

        // Assert that we have one more account
        Account[] accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(1 + expectedAccountsCount, accounts.length);
        assertTrue(isAccountPresent(am.getAccounts(), ACCOUNT_FOR_NEW_REMOVE_ACCOUNT_API));
        // Deprecated API should not work
        assertFalse(removeAccount(am, ACCOUNT_FOR_NEW_REMOVE_ACCOUNT_API, null /* callback */));
        accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(1 + expectedAccountsCount, accounts.length);
        assertTrue(isAccountPresent(am.getAccounts(), ACCOUNT_FOR_NEW_REMOVE_ACCOUNT_API));
        // Check removal of account
        assertTrue(removeAccountWithIntentLaunch(am, ACCOUNT_FOR_NEW_REMOVE_ACCOUNT_API, mActivity, null /* callback */)
                .getBoolean(AccountManager.KEY_BOOLEAN_RESULT));
        // and verify that we go back to the initial state
        accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(expectedAccountsCount, accounts.length);
    }

    /**
     * Test addAccountExplicitly(), renameAccount() and removeAccount() calling
     * into default implementations.
     */
    public void testAddAccountExplicitlyAndRemoveAccountWithDefaultImpl() throws IOException,
            AuthenticatorException, OperationCanceledException {

        final int expectedAccountsCount = getAccountsCount();

        addAccountExplicitly(ACCOUNT_FOR_DEFAULT_IMPL, ACCOUNT_PASSWORD, null /* userData */);

        // Assert that we have one more account
        Account[] accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(1 + expectedAccountsCount, accounts.length);
        assertTrue(isAccountPresent(am.getAccounts(), ACCOUNT_FOR_DEFAULT_IMPL));
        // Check removal of account
        assertTrue(removeAccountWithIntentLaunch(am, ACCOUNT_FOR_DEFAULT_IMPL, mActivity, null /* callback */)
                .getBoolean(AccountManager.KEY_BOOLEAN_RESULT));
        // and verify that we go back to the initial state
        accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(expectedAccountsCount, accounts.length);
    }

    /**
     * Test addAccountExplicitly(), renameAccount() and removeAccount().
     */
    public void testAddAccountExplicitlyAndRemoveAccountWithDeprecatedApi() throws IOException,
            AuthenticatorException, OperationCanceledException {

        final int expectedAccountsCount = getAccountsCount();

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Assert that we have one more account
        Account[] accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(1 + expectedAccountsCount, accounts.length);
        assertTrue(isAccountPresent(am.getAccounts(), ACCOUNT));
        // Need to clean up
        assertTrue(removeAccount(am, ACCOUNT, null /* callback */));

        // and verify that we go back to the initial state
        accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(expectedAccountsCount, accounts.length);
    }

    /**
     * Test addAccountExplicitly() and removeAccountExplictly().
     */
    public void testAddAccountExplicitlyAndRemoveAccountExplicitly() {
        final int expectedAccountsCount = getAccountsCount();

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Assert that we have one more account
        Account[] accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(1 + expectedAccountsCount, accounts.length);
        assertTrue(isAccountPresent(am.getAccounts(), ACCOUNT));
        // Need to clean up
        assertTrue(removeAccountExplicitly(am, ACCOUNT));

        // and verify that we go back to the initial state
        accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(expectedAccountsCount, accounts.length);
    }

    /**
     * Test updates to account visibility.
     */
    public void testSetAccountVisibility()
            throws IOException, AuthenticatorException, OperationCanceledException {
        am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_1, AccountManager.VISIBILITY_VISIBLE);
        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_1),
                AccountManager.VISIBILITY_VISIBLE);

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_1, AccountManager.VISIBILITY_NOT_VISIBLE);
        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_1),
                AccountManager.VISIBILITY_NOT_VISIBLE);

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_PRIVILEGED,
                AccountManager.VISIBILITY_VISIBLE);
        // No changes to PACKAGE_NAME_1
        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_1),
                AccountManager.VISIBILITY_NOT_VISIBLE);
    }

    /**
     * Test updates to account visibility for authenticator package.
     */
    public void testSetAccountVisibilityForPrivilegedPackage()
            throws IOException, AuthenticatorException, OperationCanceledException {
        am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_PRIVILEGED),
                AccountManager.VISIBILITY_VISIBLE);
        Map<String, Integer> visibilities = am.getPackagesAndVisibilityForAccount(ACCOUNT);
        assertNull(visibilities.get(PACKAGE_NAME_PRIVILEGED)); // no entry in database

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_PRIVILEGED,
                AccountManager.VISIBILITY_NOT_VISIBLE);
        visibilities = am.getPackagesAndVisibilityForAccount(ACCOUNT);
        // database is updated
        assertEquals((int) visibilities.get(PACKAGE_NAME_PRIVILEGED),
                AccountManager.VISIBILITY_NOT_VISIBLE);
        // VISIBILITY_VISIBLE is used for Authenticator despite database entry.
        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_PRIVILEGED),
                AccountManager.VISIBILITY_VISIBLE);
    }

    /**
     * Test getPackagesAndVisibilityForAccount() method.
     */
    public void testGetPackagesAndVisibilityForAccount()
            throws IOException, AuthenticatorException, OperationCanceledException {
        am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        Map<String, Integer> visibilities = am.getPackagesAndVisibilityForAccount(ACCOUNT);
        assertNull(visibilities.get(PACKAGE_NAME_1)); // no entry in database

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_1, AccountManager.VISIBILITY_VISIBLE);
        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_PRIVILEGED,
                AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
        visibilities = am.getPackagesAndVisibilityForAccount(ACCOUNT);
        assertEquals(visibilities.size(), 2);
        assertEquals((int) visibilities.get(PACKAGE_NAME_1), AccountManager.VISIBILITY_VISIBLE);
        assertEquals((int) visibilities.get(PACKAGE_NAME_PRIVILEGED),
                AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
    }

    /**
     * Test addAccountExplicitly(), setAccountVisibility() , getAccountVisibility(), and
     * removeAccount().
     */
    public void testAddAccountExplicitlyWithVisibility()
            throws IOException, AuthenticatorException, OperationCanceledException {
        Map<String, Integer> visibility = new HashMap<>();
        visibility.put(PACKAGE_NAME_1, AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);

        final int expectedAccountsCount = getAccountsCount();

        am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */, visibility);

        // Assert that we have one more account
        Account[] accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(1 + expectedAccountsCount, accounts.length);
        assertTrue(isAccountPresent(am.getAccounts(), ACCOUNT));

        // Visibility values were stored.
        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_1),
                AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */)
                .getBoolean(AccountManager.KEY_BOOLEAN_RESULT));

        // Visibility values were removed
        Map<Account, Integer> visibilities =
                am.getAccountsAndVisibilityForPackage(PACKAGE_NAME_1, ACCOUNT_TYPE);
        assertNull(visibilities.get(ACCOUNT));

        // and verify that we go back to the initial state
        accounts = am.getAccounts();
        assertNotNull(accounts);
        assertEquals(expectedAccountsCount, accounts.length);
    }

    /**
     * Test testGetAccountsAndVisibilityForPackage(), getAccountsByTypeForPackage() methods.
     */
    public void testGetAccountsAndVisibilityForPackage() {
        am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */, null);
        am.addAccountExplicitly(ACCOUNT_SAME_TYPE, ACCOUNT_PASSWORD, null /* userData */, null);

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_1, AccountManager.VISIBILITY_NOT_VISIBLE);
        am.setAccountVisibility(ACCOUNT_SAME_TYPE, PACKAGE_NAME_1,
                AccountManager.VISIBILITY_VISIBLE);
        assertEquals(am.getAccountVisibility(ACCOUNT_SAME_TYPE, PACKAGE_NAME_1),
                AccountManager.VISIBILITY_VISIBLE);
        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_1),
                AccountManager.VISIBILITY_NOT_VISIBLE);
        Account[] accounts = am.getAccountsByTypeForPackage(ACCOUNT_TYPE, PACKAGE_NAME_1);
        assertEquals(accounts.length, 1); // VISIBILITY_NOT_VISIBLE accounts are not returned.
        assertEquals(accounts[0], ACCOUNT_SAME_TYPE);
        Map<Account, Integer> visibilities =
                am.getAccountsAndVisibilityForPackage(PACKAGE_NAME_1, ACCOUNT_TYPE);
        assertEquals((int) visibilities.get(ACCOUNT), AccountManager.VISIBILITY_NOT_VISIBLE);

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_1,
                AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);

        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_1),
                AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
        // VISIBILITY_USER_MANAGED_NOT_VISIBLE accounts are returned by getAccountsByTypeForPackage
        assertEquals(am.getAccountsByTypeForPackage(ACCOUNT_TYPE, PACKAGE_NAME_1).length, 2);
        visibilities = am.getAccountsAndVisibilityForPackage(PACKAGE_NAME_1, ACCOUNT_TYPE);
        assertEquals((int) visibilities.get(ACCOUNT),
                AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_1,
                AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);

        assertEquals(am.getAccountVisibility(ACCOUNT, PACKAGE_NAME_1),
                AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
        assertEquals(am.getAccountsByTypeForPackage(ACCOUNT_TYPE, PACKAGE_NAME_1).length, 2);
        visibilities = am.getAccountsAndVisibilityForPackage(PACKAGE_NAME_1, ACCOUNT_TYPE);
        assertEquals((int) visibilities.get(ACCOUNT),
                AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);

        am.setAccountVisibility(ACCOUNT, PACKAGE_NAME_1, AccountManager.VISIBILITY_VISIBLE);

        assertEquals(am.getAccountsByTypeForPackage(ACCOUNT_TYPE, PACKAGE_NAME_1).length, 2);
        visibilities = am.getAccountsAndVisibilityForPackage(PACKAGE_NAME_1, ACCOUNT_TYPE);
        assertEquals((int) visibilities.get(ACCOUNT), AccountManager.VISIBILITY_VISIBLE);
        assertEquals(am.getAccountsByTypeForPackage(ACCOUNT_TYPE, PACKAGE_NAME_1).length, 2);

        // VISIBILITY_USER MANAGED_NOT_VISIBLE accounts are not returned when type is null.
        // It should be equivalent to callling am.getAccounts() which doesn't return
        // VISIBILITY_USER MANAGED_NOT_VISIBLE accounts.
        assertEquals(am.getAccountsByTypeForPackage(null, PACKAGE_NAME_1).length,
            am.getAccounts().length);
    }

    /**
     * Test checks order of accounts returned by getAccounts...().
     * Accounts should be grouped by type.
     */
    public void testGetAccountsReturnedOrder() {
        Account account_1_1 = new Account("account_z", ACCOUNT_TYPE);
        Account account_1_2 = new Account("account_c", ACCOUNT_TYPE);
        Account account_1_3 = new Account("account_a", ACCOUNT_TYPE);

        Account account_2_1 = new Account("account_b", ACCOUNT_TYPE_CUSTOM);
        Account account_2_2 = new Account("account_f", ACCOUNT_TYPE_CUSTOM);
        Account account_2_3 = new Account("account_a", ACCOUNT_TYPE_CUSTOM);

        am.addAccountExplicitly(account_1_1, ACCOUNT_PASSWORD, null /* userData */, null);
        am.addAccountExplicitly(account_1_2, ACCOUNT_PASSWORD, null /* userData */, null);
        am.addAccountExplicitly(account_2_1, ACCOUNT_PASSWORD, null /* userData */, null);

        verifyAccountsGroupedByType(am.getAccounts());
        verifyAccountsGroupedByType(am.getAccountsByType(null));
        verifyAccountsGroupedByType(am.getAccountsByTypeForPackage(null, PACKAGE_NAME_1));

        am.addAccountExplicitly(account_2_2, ACCOUNT_PASSWORD, null /* userData */, null);

        verifyAccountsGroupedByType(am.getAccounts());
        verifyAccountsGroupedByType(am.getAccountsByType(null));
        verifyAccountsGroupedByType(am.getAccountsByTypeForPackage(null, PACKAGE_NAME_1));

        am.addAccountExplicitly(account_1_3, ACCOUNT_PASSWORD, null /* userData */, null);
        verifyAccountsGroupedByType(am.getAccounts());
        verifyAccountsGroupedByType(am.getAccountsByType(null));
        verifyAccountsGroupedByType(am.getAccountsByTypeForPackage(null, PACKAGE_NAME_1));

        am.addAccountExplicitly(account_2_3, ACCOUNT_PASSWORD, null /* userData */, null);

        verifyAccountsGroupedByType(am.getAccounts());
        verifyAccountsGroupedByType(am.getAccountsByType(null));
        verifyAccountsGroupedByType(am.getAccountsByTypeForPackage(null, PACKAGE_NAME_1));
    }

    /**
     * Test setUserData() and getUserData().
     */
    public void testAccountRenameAndGetPreviousName()
            throws OperationCanceledException, AuthenticatorException, IOException {
        // Add a first account

        boolean result = am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, USERDATA_BUNDLE);

        assertTrue(result);

        // Prior to a rename, the previous name should be null.
        String nullName = am.getPreviousName(ACCOUNT);
        assertNull(nullName);

        final int expectedAccountsCount = getAccountsCount();

        Account renamedAccount = renameAccount(am, ACCOUNT, ACCOUNT_NEW_NAME);
        /*
         *  Make sure that the resultant renamed account has the correct name
         *  and is associated with the correct account type.
         */
        assertEquals(ACCOUNT_NEW_NAME, renamedAccount.name);
        assertEquals(ACCOUNT.type, renamedAccount.type);

        // Make sure the total number of accounts is the same.
        Account[] accounts = am.getAccounts();
        assertEquals(expectedAccountsCount, accounts.length);

        // Make sure the old account isn't present.
        assertFalse(isAccountPresent(am.getAccounts(), ACCOUNT));

        // But that the new one is.
        assertTrue(isAccountPresent(am.getAccounts(), renamedAccount));

        // Check that the UserData is still present.
        assertEquals(USERDATA_VALUE_1, am.getUserData(renamedAccount, USERDATA_NAME_1));

        assertEquals(ACCOUNT.name, am.getPreviousName(renamedAccount));

        // Need to clean up
        assertTrue(removeAccount(am, renamedAccount, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

    }

    /**
     * Test getAccounts() and getAccountsByType()
     */
    public void testGetAccountsAndGetAccountsByType() {

        assertEquals(false, isAccountPresent(am.getAccounts(), ACCOUNT));
        assertEquals(false, isAccountPresent(am.getAccounts(), ACCOUNT_SAME_TYPE));

        final int accountsCount = getAccountsCount();

        // Add a first account
        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Check that we have the new account
        Account[] accounts = am.getAccounts();
        assertEquals(1 + accountsCount, accounts.length);
        assertEquals(true, isAccountPresent(accounts, ACCOUNT));

        // Add another account
        addAccountExplicitly(ACCOUNT_SAME_TYPE, ACCOUNT_PASSWORD, null /* userData */);

        // Check that we have one more account again
        accounts = am.getAccounts();
        assertEquals(2 + accountsCount, accounts.length);
        assertEquals(true, isAccountPresent(accounts, ACCOUNT_SAME_TYPE));

        // Check if we have one from first type
        accounts = am.getAccountsByType(ACCOUNT_TYPE);
        assertEquals(2, accounts.length);

        // Check if we dont have any account from the other type
        accounts = am.getAccountsByType(ACCOUNT_TYPE_ABSENT);
        assertEquals(0, accounts.length);
    }

    /**
     * Test getAuthenticatorTypes()
     */
    public void testGetAuthenticatorTypes() {
        AuthenticatorDescription[] types = am.getAuthenticatorTypes();
        for(AuthenticatorDescription description: types) {
            if (description.type.equals(ACCOUNT_TYPE)) {
                return;
            }
        }
        fail("should have found Authenticator type: " + ACCOUNT_TYPE);
    }

    /**
     * Test setPassword() and getPassword()
     */
    public void testSetAndGetAndClearPassword() {
        // Add a first account
        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Check that the password is the one we defined
        assertEquals(ACCOUNT_PASSWORD, am.getPassword(ACCOUNT));

        // Clear the password and check that it is cleared
        am.clearPassword(ACCOUNT);
        assertNull(am.getPassword(ACCOUNT));

        // Reset the password
        am.setPassword(ACCOUNT, ACCOUNT_PASSWORD);

        // Check that the password is the one we defined
        assertEquals(ACCOUNT_PASSWORD, am.getPassword(ACCOUNT));
    }

    /**
     * Test setUserData() and getUserData()
     */
    public void testSetAndGetUserData() {
        // Add a first account
        boolean result = am.addAccountExplicitly(ACCOUNT,
                                ACCOUNT_PASSWORD,
                                USERDATA_BUNDLE);

        assertTrue(result);

        // Check that the UserData is the one we defined
        assertEquals(USERDATA_VALUE_1, am.getUserData(ACCOUNT, USERDATA_NAME_1));

        am.setUserData(ACCOUNT, USERDATA_NAME_2, USERDATA_VALUE_2);

        // Check that the UserData is the one we defined
        assertEquals(USERDATA_VALUE_2, am.getUserData(ACCOUNT, USERDATA_NAME_2));
    }

    /**
     * Test getAccountsByTypeAndFeatures()
     */
    public void testGetAccountsByTypeAndFeatures() throws IOException,
            AuthenticatorException, OperationCanceledException {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        AccountManagerFuture<Account[]> futureAccounts = am.getAccountsByTypeAndFeatures(
                ACCOUNT_TYPE, REQUIRED_FEATURES, null, null);

        Account[] accounts = futureAccounts.getResult();

        assertNotNull(accounts);
        assertEquals(1, accounts.length);
        assertEquals(true, isAccountPresent(accounts, ACCOUNT));

        futureAccounts = am.getAccountsByTypeAndFeatures(ACCOUNT_TYPE,
                new String[] { NON_EXISTING_FEATURE },
                null /* callback*/,
                null /* handler */);
        accounts = futureAccounts.getResult();

        assertNotNull(accounts);
        assertEquals(0, accounts.length);
    }

    /**
     * Test getAccountsByTypeAndFeatures() with callback and handler
     */
    public void testGetAccountsByTypeAndFeaturesWithCallbackAndHandler() throws IOException,
            AuthenticatorException, OperationCanceledException {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        testGetAccountsByTypeAndFeaturesWithCallbackAndHandler(null /* handler */);
        testGetAccountsByTypeAndFeaturesWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    private void testGetAccountsByTypeAndFeaturesWithCallbackAndHandler(Handler handler) throws
            IOException, AuthenticatorException, OperationCanceledException {

        final CountDownLatch latch1 = new CountDownLatch(1);

        AccountManagerCallback<Account[]> callback1 = new AccountManagerCallback<Account[]>() {
            @Override
            public void run(AccountManagerFuture<Account[]> accountsFuture) {
                try {
                    Account[] accounts = accountsFuture.getResult();
                    assertNotNull(accounts);
                    assertEquals(1, accounts.length);
                    assertEquals(true, isAccountPresent(accounts, ACCOUNT));
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    fail("should not throw an AuthenticatorException");
                } finally {
                  latch1.countDown();
                }
            }
        };

        AccountManagerFuture<Account[]> futureAccounts = am.getAccountsByTypeAndFeatures(
                ACCOUNT_TYPE,
                REQUIRED_FEATURES,
                callback1,
                handler);

        Account[] accounts = futureAccounts.getResult();

        assertNotNull(accounts);
        assertEquals(1, accounts.length);
        assertEquals(true, isAccountPresent(accounts, ACCOUNT));

        // Wait with timeout for the callback to do its work
        try {
            latch1.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }

        final CountDownLatch latch2 = new CountDownLatch(1);

        AccountManagerCallback<Account[]> callback2 = new AccountManagerCallback<Account[]>() {
            @Override
            public void run(AccountManagerFuture<Account[]> accountsFuture) {
                try {
                    Account[] accounts = accountsFuture.getResult();
                    assertNotNull(accounts);
                    assertEquals(0, accounts.length);
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    fail("should not throw an AuthenticatorException");
                } finally {
                  latch2.countDown();
                }
            }
        };

        accounts = null;

        futureAccounts = am.getAccountsByTypeAndFeatures(ACCOUNT_TYPE,
                new String[] { NON_EXISTING_FEATURE },
                callback2,
                handler);

        accounts = futureAccounts.getResult();
        assertNotNull(accounts);
        assertEquals(0, accounts.length);

        // Wait with timeout for the callback to do its work
        try {
            latch2.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    /**
     * Test setAuthToken() and peekAuthToken()
     */
    public void testSetAndPeekAndInvalidateAuthToken() {
        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
        String expected = "x";
        am.setAuthToken(ACCOUNT, AUTH_TOKEN_TYPE, expected);

        // Ask for the AuthToken
        String token = am.peekAuthToken(ACCOUNT, AUTH_TOKEN_TYPE);
        assertNotNull(token);
        assertEquals(expected, token);

        am.invalidateAuthToken(ACCOUNT_TYPE, token);
        token = am.peekAuthToken(ACCOUNT, AUTH_TOKEN_TYPE);
        assertNull(token);
    }

    /**
     * Test successful blockingGetAuthToken() with customTokens=false authenticator.
     */
    public void testBlockingGetAuthToken_DefaultToken_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null);

        String token = am.blockingGetAuthToken(ACCOUNT,
                AUTH_TOKEN_TYPE,
                false /* no failure notification */);

        // Ask for the AuthToken
        assertNotNull(token);
        assertEquals(mockAuthenticator.getLastTokenServed(), token);
    }

    private static class BlockingGetAuthTokenFetcher implements TokenFetcher {
        private final Account mAccount;

        BlockingGetAuthTokenFetcher(Account account) {
            mAccount = account;
        }

        @Override
        public Bundle fetch(String tokenType)
                throws OperationCanceledException, AuthenticatorException, IOException {
            String token = am.blockingGetAuthToken(
                    getAccount(),
                    tokenType,
                    false /* no failure notification */);
            Bundle result = new Bundle();
            result.putString(AccountManager.KEY_AUTHTOKEN, token);
            result.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);
            result.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type);
            return result;
        }
        @Override
        public Account getAccount() {
            return CUSTOM_TOKEN_ACCOUNT;
        }
    }

    /**
     * Test successful blockingGetAuthToken() with customTokens=true authenticator.
     */
    public void testBlockingGetAuthToken_CustomToken_NoCaching_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(CUSTOM_TOKEN_ACCOUNT, ACCOUNT_PASSWORD, null);
        TokenFetcher f = new BlockingGetAuthTokenFetcher(CUSTOM_TOKEN_ACCOUNT);
        validateSuccessfulTokenFetchingLifecycle(f, AUTH_TOKEN_TYPE);
    }

    /**
     * Test successful blockingGetAuthToken() with customTokens=true authenticator.
     */
    public void testBlockingGetAuthToken_CustomToken_ExpiringCache_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(CUSTOM_TOKEN_ACCOUNT, ACCOUNT_PASSWORD, null);
        TokenFetcher f = new BlockingGetAuthTokenFetcher(CUSTOM_TOKEN_ACCOUNT);
        validateSuccessfulTokenFetchingLifecycle(f, AUTH_EXPIRING_TOKEN_TYPE);
    }

    /**
     * Test successful getAuthToken() using a future with customTokens=false authenticator.
     */
    public void testDeprecatedGetAuthTokenWithFuture_NoOptions_DefaultToken_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
        AccountManagerFuture<Bundle> futureBundle = am.getAuthToken(ACCOUNT,
                AUTH_TOKEN_TYPE,
                false /* no failure notification */,
                null /* no callback */,
                null /* no handler */
        );

        Bundle resultBundle = futureBundle.getResult();

        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        // Assert returned result
        validateAccountAndAuthTokenResult(resultBundle);
    }

    /**
     * Test successful getAuthToken() using a future with customTokens=false without
     * expiring tokens.
     */
    public void testDeprecatedGetAuthTokenWithFuture_NoOptions_CustomToken_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(CUSTOM_TOKEN_ACCOUNT, ACCOUNT_PASSWORD, null);
        // validateSuccessfulTokenFetchingLifecycle(AccountManager am, TokenFetcher fetcher, String tokenType)
        TokenFetcher f = new TokenFetcher() {
            @Override
            public Bundle fetch(String tokenType)
                    throws OperationCanceledException, AuthenticatorException, IOException {
                AccountManagerFuture<Bundle> futureBundle = am.getAuthToken(
                        getAccount(),
                        tokenType,
                        false /* no failure notification */,
                        null /* no callback */,
                        null /* no handler */
                );
                Bundle actual = futureBundle.getResult();
                assertTrue(futureBundle.isDone());
                assertNotNull(actual);
                return actual;
            }

            @Override
            public Account getAccount() {
                return CUSTOM_TOKEN_ACCOUNT;
            }
        };
        validateSuccessfulTokenFetchingLifecycle(f, AUTH_EXPIRING_TOKEN_TYPE);
        validateSuccessfulTokenFetchingLifecycle(f, AUTH_TOKEN_TYPE);
    }

    /**
     * Test successful getAuthToken() using a future with customTokens=false without
     * expiring tokens.
     */
    public void testGetAuthTokenWithFuture_Options_DefaultToken_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        AccountManagerFuture<Bundle> futureBundle = am.getAuthToken(ACCOUNT,
                AUTH_TOKEN_TYPE,
                OPTIONS_BUNDLE,
                mActivity,
                null /* no callback */,
                null /* no handler */
        );

        Bundle resultBundle = futureBundle.getResult();

        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        // Assert returned result
        validateAccountAndAuthTokenResult(resultBundle);

        validateOptions(null, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(OPTIONS_BUNDLE, mockAuthenticator.mOptionsGetAuthToken);
        validateSystemOptions(mockAuthenticator.mOptionsGetAuthToken);
    }

    /**
     * Test successful getAuthToken() using a future with customTokens=false without
     * expiring tokens.
     */
    public void testGetAuthTokenWithFuture_Options_CustomToken_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(CUSTOM_TOKEN_ACCOUNT, ACCOUNT_PASSWORD, null);
        TokenFetcher fetcherWithOptions = new TokenFetcher() {
            @Override
            public Bundle fetch(String tokenType)
                    throws OperationCanceledException, AuthenticatorException, IOException {
                AccountManagerFuture<Bundle> futureBundle = am.getAuthToken(
                        getAccount(),
                        tokenType,
                        OPTIONS_BUNDLE,
                        false /* no failure notification */,
                        null /* no callback */,
                        null /* no handler */
                );
                Bundle actual = futureBundle.getResult();
                assertTrue(futureBundle.isDone());
                assertNotNull(actual);
                return actual;
            }

            @Override
            public Account getAccount() {
                return CUSTOM_TOKEN_ACCOUNT;
            }
        };
        validateSuccessfulTokenFetchingLifecycle(fetcherWithOptions, AUTH_TOKEN_TYPE);
        validateSuccessfulTokenFetchingLifecycle(fetcherWithOptions, AUTH_EXPIRING_TOKEN_TYPE);
    }


    /**
     * Test successful getAuthToken() using a future with customTokens=false without
     * expiring tokens.
     */
    public void testGetAuthTokenWithCallback_Options_Handler_DefaultToken_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null);
        final HandlerThread handlerThread = new HandlerThread("accounts.test");
        handlerThread.start();
        TokenFetcher fetcherWithOptions = new TokenFetcher() {
            @Override
            public Bundle fetch(String tokenType)
                    throws OperationCanceledException, AuthenticatorException, IOException {
                final AtomicReference<Bundle> actualRef = new AtomicReference<>();
                final CountDownLatch latch = new CountDownLatch(1);

                AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
                    @Override
                    public void run(AccountManagerFuture<Bundle> bundleFuture) {
                        Bundle resultBundle = null;
                        try {
                            resultBundle = bundleFuture.getResult();
                            actualRef.set(resultBundle);
                        } catch (OperationCanceledException e) {
                            fail("should not throw an OperationCanceledException");
                        } catch (IOException e) {
                            fail("should not throw an IOException");
                        } catch (AuthenticatorException e) {
                            fail("should not throw an AuthenticatorException");
                        } finally {
                            latch.countDown();
                        }
                    }
                };

                am.getAuthToken(getAccount(),
                        tokenType,
                        OPTIONS_BUNDLE,
                        false /* no failure notification */,
                        callback,
                        new Handler(handlerThread.getLooper()));

                // Wait with timeout for the callback to do its work
                try {
                    latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    fail("should not throw an InterruptedException");
                }
                return actualRef.get();
            }

            @Override
            public Account getAccount() {
                return ACCOUNT;
            }
        };
        validateSuccessfulTokenFetchingLifecycle(fetcherWithOptions, AUTH_TOKEN_TYPE);
        validateSuccessfulTokenFetchingLifecycle(fetcherWithOptions, AUTH_EXPIRING_TOKEN_TYPE);
    }

    /**
     * Test successful getAuthToken() using a future with customTokens=false without
     * expiring tokens.
     */
    public void testGetAuthTokenWithCallback_Options_Handler_CustomToken_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        addAccountExplicitly(CUSTOM_TOKEN_ACCOUNT, ACCOUNT_PASSWORD, null);
        final HandlerThread handlerThread = new HandlerThread("accounts.test");
        handlerThread.start();
        TokenFetcher fetcherWithOptions = new TokenFetcher() {
            @Override
            public Bundle fetch(String tokenType)
                    throws OperationCanceledException, AuthenticatorException, IOException {
                final AtomicReference<Bundle> actualRef = new AtomicReference<>();
                final CountDownLatch latch = new CountDownLatch(1);

                AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
                    @Override
                    public void run(AccountManagerFuture<Bundle> bundleFuture) {
                        Bundle resultBundle = null;
                        try {
                            resultBundle = bundleFuture.getResult();
                            actualRef.set(resultBundle);
                        } catch (OperationCanceledException e) {
                            fail("should not throw an OperationCanceledException");
                        } catch (IOException e) {
                            fail("should not throw an IOException");
                        } catch (AuthenticatorException e) {
                            fail("should not throw an AuthenticatorException");
                        } finally {
                            latch.countDown();
                        }
                    }
                };

                am.getAuthToken(getAccount(),
                        tokenType,
                        OPTIONS_BUNDLE,
                        false /* no failure notification */,
                        callback,
                        new Handler(handlerThread.getLooper()));

                // Wait with timeout for the callback to do its work
                try {
                    latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    fail("should not throw an InterruptedException");
                }
                return actualRef.get();
            }

            @Override
            public Account getAccount() {
                return CUSTOM_TOKEN_ACCOUNT;
            }
        };
        validateSuccessfulTokenFetchingLifecycle(fetcherWithOptions, AUTH_TOKEN_TYPE);
        validateSuccessfulTokenFetchingLifecycle(fetcherWithOptions, AUTH_EXPIRING_TOKEN_TYPE);
    }

    /**
     * Test getAuthToken() with callback and handler
     */
    public void testGetAuthTokenWithCallbackAndHandler() throws IOException, AuthenticatorException,
            OperationCanceledException {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        testGetAuthTokenWithCallbackAndHandler(null /* handler */);
        testGetAuthTokenWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    private void testGetAuthTokenWithCallbackAndHandler(Handler handler) throws IOException,
            AuthenticatorException, OperationCanceledException {

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {

                Bundle resultBundle = null;
                try {
                    resultBundle = bundleFuture.getResult();

                    // Assert returned result
                    validateAccountAndAuthTokenResult(resultBundle);

                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    fail("should not throw an AuthenticatorException");
                }
                finally {
                    latch.countDown();
                }
            }
        };

        AccountManagerFuture<Bundle> futureBundle = am.getAuthToken(ACCOUNT,
                AUTH_TOKEN_TYPE,
                false /* no failure notification */,
                callback,
                handler
        );

        Bundle resultBundle = futureBundle.getResult();

        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    /**
     * test getAuthToken() with options and callback and handler
     */
    public void testGetAuthTokenWithOptionsAndCallback() throws IOException,
            AuthenticatorException, OperationCanceledException {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        testGetAuthTokenWithOptionsAndCallbackAndHandler(null /* handler */);
        testGetAuthTokenWithOptionsAndCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    private void testGetAuthTokenWithOptionsAndCallbackAndHandler(Handler handler) throws
            IOException, AuthenticatorException, OperationCanceledException {

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {

                Bundle resultBundle = null;
                try {
                    resultBundle = bundleFuture.getResult();
                    // Assert returned result
                    validateAccountAndAuthTokenResult(resultBundle);
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    fail("should not throw an AuthenticatorException");
                }
                finally {
                    latch.countDown();
                }
            }
        };

        AccountManagerFuture<Bundle> futureBundle = am.getAuthToken(ACCOUNT,
                AUTH_TOKEN_TYPE,
                OPTIONS_BUNDLE,
                mActivity,
                callback,
                handler
        );

        Bundle resultBundle = futureBundle.getResult();

        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    /**
     * Test getAuthTokenByFeatures()
     */
    public void testGetAuthTokenByFeatures() throws IOException, AuthenticatorException,
            OperationCanceledException {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        Bundle resultBundle = getAuthTokenByFeature(
                new String[] { NON_EXISTING_FEATURE },
                null /* activity */
        );

        // Assert returned result
        validateNullResult(resultBundle);

        validateOptions(null, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);

        mockAuthenticator.clearData();

        // Now test with existing features and an activity
        resultBundle = getAuthTokenByFeature(
                new String[] { NON_EXISTING_FEATURE },
                mActivity
        );

        // Assert returned result
        validateAccountAndAuthTokenResult(resultBundle);

        validateOptions(OPTIONS_BUNDLE, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);

        mockAuthenticator.clearData();

        // Now test with existing features and no activity
        resultBundle = getAuthTokenByFeature(
                REQUIRED_FEATURES,
                null /* activity */
        );

        // Assert returned result
        validateAccountAndAuthTokenResult(resultBundle);

        validateOptions(null, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);

        mockAuthenticator.clearData();

        // Now test with existing features and an activity
        resultBundle = getAuthTokenByFeature(
                REQUIRED_FEATURES,
                mActivity
        );

        // Assert returned result
        validateAccountAndAuthTokenResult(resultBundle);

        validateOptions(null, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
    }

    /**
     * Test confirmCredentials()
     */
    @Presubmit
    public void testConfirmCredentials() throws IOException, AuthenticatorException,
            OperationCanceledException {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        AccountManagerFuture<Bundle> futureBundle = am.confirmCredentials(ACCOUNT,
                OPTIONS_BUNDLE,
                mActivity,
                null /* callback*/,
                null /* handler */);

        futureBundle.getResult();

        // Assert returned result
        validateCredentials();
    }

    /**
     * Tests the setting of lastAuthenticatedTime on adding account
     */
    public void testLastAuthenticatedTimeAfterAddAccount() throws IOException,
            AuthenticatorException, OperationCanceledException {
        assertTrue(addAccountAndReturnAccountAddedTime(ACCOUNT, ACCOUNT_PASSWORD) > 0);
    }

    /**
     * Test confirmCredentials() for account not on device. Just that no error
     * should be thrown.
     */
    public void testConfirmCredentialsAccountNotOnDevice() throws IOException,
            AuthenticatorException, OperationCanceledException {

        Account account = new Account("AccountNotOnThisDevice", ACCOUNT_TYPE);
        AccountManagerFuture<Bundle> futureBundle = am.confirmCredentials(account,
                OPTIONS_BUNDLE,
                mActivity,
                null /* callback */,
                null /* handler */);

        futureBundle.getResult();
    }

    /**
     * Tests the setting of lastAuthenticatedTime on confirmCredentials being
     * successful.
     */
    public void testLastAuthenticatedTimeAfterConfirmCredentialsSuccess() throws IOException,
            AuthenticatorException, OperationCanceledException {

        long accountAddTime = addAccountAndReturnAccountAddedTime(ACCOUNT, ACCOUNT_PASSWORD);

        // Now this confirm credentials call returns true, which in turn
        // should update the last authenticated timestamp.
        Bundle result = am.confirmCredentials(ACCOUNT,
                OPTIONS_BUNDLE, /* options */
                null, /* activity */
                null /* callback */,
                null /* handler */).getResult();
        long confirmedCredTime = result.getLong(
                AccountManager.KEY_LAST_AUTHENTICATED_TIME, -1);
        assertTrue(confirmedCredTime > accountAddTime);
    }

    /**
     * Tests the setting of lastAuthenticatedTime on updateCredentials being
     * successful.
     */
    public void testLastAuthenticatedTimeAfterUpdateCredentialsSuccess() throws IOException,
            AuthenticatorException, OperationCanceledException {

        long accountAddTime = addAccountAndReturnAccountAddedTime(ACCOUNT, ACCOUNT_PASSWORD);

        am.updateCredentials(ACCOUNT,
                AUTH_TOKEN_TYPE,
                OPTIONS_BUNDLE,
                mActivity,
                null /* callback */,
                null /* handler */).getResult();
        long updateCredTime = getLastAuthenticatedTime(ACCOUNT);
        assertTrue(updateCredTime > accountAddTime);
    }

    /**
     * LastAuthenticatedTime on setPassword should not be disturbed.
     */
    public void testLastAuthenticatedTimeAfterSetPassword() throws IOException,
            AuthenticatorException, OperationCanceledException {
        long accountAddTime = addAccountAndReturnAccountAddedTime(ACCOUNT, ACCOUNT_PASSWORD);
        mockAuthenticator.callSetPassword();
        long setPasswordTime = getLastAuthenticatedTime(ACCOUNT);
        assertTrue(setPasswordTime == accountAddTime);
    }

    /**
     * Test confirmCredentials() with callback
     */
    public void testConfirmCredentialsWithCallbackAndHandler() {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        testConfirmCredentialsWithCallbackAndHandler(null /* handler */);
        testConfirmCredentialsWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    private void testConfirmCredentialsWithCallbackAndHandler(Handler handler) {
        final CountDownLatch latch = new CountDownLatch(1);
        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {

                Bundle resultBundle = null;
                try {
                    resultBundle = bundleFuture.getResult();

                    // Assert returned result
                    validateCredentials();

                    assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    fail("should not throw an AuthenticatorException");
                }
                finally {
                    latch.countDown();
                }
            }
        };
        AccountManagerFuture<Bundle> futureBundle = am.confirmCredentials(ACCOUNT,
                OPTIONS_BUNDLE,
                mActivity,
                callback,
                handler);
        // Wait with timeout for the callback to do its work
        try {
            latch.await(3 * LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    /**
     * Test updateCredentials()
     */
    public void testUpdateCredentials() throws IOException, AuthenticatorException,
            OperationCanceledException {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        AccountManagerFuture<Bundle> futureBundle = am.updateCredentials(ACCOUNT,
                AUTH_TOKEN_TYPE,
                OPTIONS_BUNDLE,
                mActivity,
                null /* callback*/,
                null /* handler */);

        Bundle result = futureBundle.getResult();

        validateAccountAndNoAuthTokenResult(result);

        // Assert returned result
        validateCredentials();
    }

    /**
     * Test updateCredentials() with callback and handler
     */
    public void testUpdateCredentialsWithCallbackAndHandler() throws IOException,
            AuthenticatorException, OperationCanceledException {

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        testUpdateCredentialsWithCallbackAndHandler(null /* handler */);
        testUpdateCredentialsWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    private void testUpdateCredentialsWithCallbackAndHandler(Handler handler) throws IOException,
            AuthenticatorException, OperationCanceledException {

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {

                Bundle resultBundle = null;
                try {
                    resultBundle = bundleFuture.getResult();

                    // Assert returned result
                    validateCredentials();
                    assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));

                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    fail("should not throw an AuthenticatorException");
                }
                finally {
                    latch.countDown();
                }
            }
        };

        AccountManagerFuture<Bundle> futureBundle = am.updateCredentials(ACCOUNT,
                AUTH_TOKEN_TYPE,
                OPTIONS_BUNDLE,
                mActivity,
                callback,
                handler);

        futureBundle.getResult();

        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    /**
     * Test editProperties()
     */
    public void testEditProperties() throws IOException, AuthenticatorException,
            OperationCanceledException {

        AccountManagerFuture<Bundle> futureBundle = am.editProperties(ACCOUNT_TYPE,
                mActivity,
                null /* callback */,
                null /* handler*/);

        Bundle result = futureBundle.getResult();

        validateAccountAndNoAuthTokenResult(result);

        // Assert returned result
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
    }

    /**
     * Test editProperties() with callback and handler
     */
    public void testEditPropertiesWithCallbackAndHandler() {
        testEditPropertiesWithCallbackAndHandler(null /* handler */);
        testEditPropertiesWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    private void testEditPropertiesWithCallbackAndHandler(Handler handler) {
        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                try {
                    // Assert returned result
                    assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
                }
                finally {
                    latch.countDown();
                }
            }
        };

        AccountManagerFuture<Bundle> futureBundle = am.editProperties(ACCOUNT_TYPE,
                mActivity,
                callback,
                handler);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    /**
     * Test addOnAccountsUpdatedListener() with handler
     */
    public void testAddOnAccountsUpdatedListenerWithHandler() throws IOException,
            AuthenticatorException, OperationCanceledException {

        testAddOnAccountsUpdatedListenerWithHandler(null /* handler */,
                false /* updateImmediately */);

        // Need to cleanup intermediate state
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        testAddOnAccountsUpdatedListenerWithHandler(null /* handler */,
                true /* updateImmediately */);

        // Need to cleanup intermediate state
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        testAddOnAccountsUpdatedListenerWithHandler(new Handler(Looper.getMainLooper()),
                false /* updateImmediately */);

        // Need to cleanup intermediate state
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        testAddOnAccountsUpdatedListenerWithHandler(new Handler(Looper.getMainLooper()),
                true /* updateImmediately */);
    }

    private void testAddOnAccountsUpdatedListenerWithHandler(Handler handler,
            boolean updateImmediately) {

        final CountDownLatch latch = new CountDownLatch(1);
        OnAccountsUpdateListener listener =  accounts -> latch.countDown();

        // Add a listener
        am.addOnAccountsUpdatedListener(listener,
                handler,
                updateImmediately);

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }

        // Cleanup
        am.removeOnAccountsUpdatedListener(listener);
    }

    /**
     * Test addOnAccountsUpdatedListener() with visibility
     */
    public void testAddOnAccountsUpdatedListenerWithVisibility() throws IOException,
            AuthenticatorException, OperationCanceledException {

        testAddOnAccountsUpdatedListenerWithVisibility(null /* handler */,
                false /* updateImmediately */, new String[] {ACCOUNT_TYPE, ACCOUNT_TYPE_ABSENT});

        // Need to cleanup intermediate state
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        testAddOnAccountsUpdatedListenerWithVisibility(null /* handler */,
                true /* updateImmediately */, null /* types */);

        // Need to cleanup intermediate state
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        testAddOnAccountsUpdatedListenerWithVisibility(new Handler(Looper.getMainLooper()),
                false /* updateImmediately */, new String[] {ACCOUNT_TYPE});

        // Need to cleanup intermediate state
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        testAddOnAccountsUpdatedListenerWithVisibility(new Handler(Looper.getMainLooper()),
                true /* updateImmediately */, new String[] {ACCOUNT_TYPE});
    }

    private void testAddOnAccountsUpdatedListenerWithVisibility(Handler handler,
            boolean updateImmediately, String[] accountTypes) {

        final CountDownLatch latch = new CountDownLatch(1);
        OnAccountsUpdateListener listener =  accounts -> latch.countDown();

        // Add a listener
        am.addOnAccountsUpdatedListener(listener,
                handler,
                updateImmediately,
                accountTypes);

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }

        // Cleanup
        am.removeOnAccountsUpdatedListener(listener);
    }

    /**
     * Test removeOnAccountsUpdatedListener() with handler
     */
    public void testRemoveOnAccountsUpdatedListener() throws IOException, AuthenticatorException,
            OperationCanceledException {

        testRemoveOnAccountsUpdatedListenerWithHandler(null /* handler */);

        // Need to cleanup intermediate state
        assertTrue(removeAccount(am, ACCOUNT, mActivity, null /* callback */).getBoolean(
                AccountManager.KEY_BOOLEAN_RESULT));

        testRemoveOnAccountsUpdatedListenerWithHandler(new Handler(Looper.getMainLooper()));
    }

    private void testRemoveOnAccountsUpdatedListenerWithHandler(Handler handler) {

        final CountDownLatch latch = new CountDownLatch(1);
        OnAccountsUpdateListener listener =  accounts -> fail("should not be called");

        // First add a listener
        am.addOnAccountsUpdatedListener(listener,
                handler,
                false /* updateImmediately */);

        // Then remove the listener
        am.removeOnAccountsUpdatedListener(listener);

        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    /**
     * Test hasFeature
     */
    public void testHasFeature()
            throws IOException, AuthenticatorException, OperationCanceledException {

        assertHasFeature(null /* handler */);
        assertHasFeature(new Handler(Looper.getMainLooper()));

        assertHasFeatureWithCallback(null /* handler */);
        assertHasFeatureWithCallback(new Handler(Looper.getMainLooper()));
    }

    private void assertHasFeature(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        Bundle resultBundle = addAccount(am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                OPTIONS_BUNDLE,
                mActivity,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        validateAccountAndAuthTokenType();
        validateFeatures();

        AccountManagerFuture<Boolean> booleanFuture = am.hasFeatures(ACCOUNT,
                new String[]{FEATURE_1},
                null /* callback */,
                handler);
        assertTrue(booleanFuture.getResult());

        booleanFuture = am.hasFeatures(ACCOUNT,
                new String[]{FEATURE_2},
                null /* callback */,
                handler);
        assertTrue(booleanFuture.getResult());

        booleanFuture = am.hasFeatures(ACCOUNT,
                new String[]{FEATURE_1, FEATURE_2},
                null /* callback */,
                handler);
        assertTrue(booleanFuture.getResult());

        booleanFuture = am.hasFeatures(ACCOUNT,
                new String[]{NON_EXISTING_FEATURE},
                null /* callback */,
                handler);
        assertFalse(booleanFuture.getResult());

        booleanFuture = am.hasFeatures(ACCOUNT,
                new String[]{NON_EXISTING_FEATURE, FEATURE_1},
                null /* callback */,
                handler);
        assertFalse(booleanFuture.getResult());

        booleanFuture = am.hasFeatures(ACCOUNT,
                new String[]{NON_EXISTING_FEATURE, FEATURE_1, FEATURE_2},
                null /* callback */,
                handler);
        assertFalse(booleanFuture.getResult());
    }

    private AccountManagerCallback<Boolean> getAssertTrueCallback(final CountDownLatch latch) {
        return new AccountManagerCallback<Boolean>() {
            @Override
            public void run(AccountManagerFuture<Boolean> booleanFuture) {
                try {
                    // Assert returned result should be TRUE
                    assertTrue(booleanFuture.getResult());
                } catch (Exception e) {
                    fail("Exception: " + e);
                } finally {
                    latch.countDown();
                }
            }
        };
    }

    private AccountManagerCallback<Boolean> getAssertFalseCallback(final CountDownLatch latch) {
        return new AccountManagerCallback<Boolean>() {
            @Override
            public void run(AccountManagerFuture<Boolean> booleanFuture) {
                try {
                    // Assert returned result should be FALSE
                    assertFalse(booleanFuture.getResult());
                } catch (Exception e) {
                    fail("Exception: " + e);
                } finally {
                    latch.countDown();
                }
            }
        };
    }

    private void waitForLatch(final CountDownLatch latch) {
        // Wait with timeout for the callback to do its work
        try {
            latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            fail("should not throw an InterruptedException");
        }
    }

    private void assertHasFeatureWithCallback(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        Bundle resultBundle = addAccount(am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                OPTIONS_BUNDLE,
                mActivity,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        validateAccountAndAuthTokenType();
        validateFeatures();

        CountDownLatch latch = new CountDownLatch(1);
        am.hasFeatures(ACCOUNT,
                new String[]{FEATURE_1},
                getAssertTrueCallback(latch),
                handler);
        waitForLatch(latch);

        latch = new CountDownLatch(1);
        am.hasFeatures(ACCOUNT,
                new String[]{FEATURE_2},
                getAssertTrueCallback(latch),
                handler);
        waitForLatch(latch);

        latch = new CountDownLatch(1);
        am.hasFeatures(ACCOUNT,
                new String[]{FEATURE_1, FEATURE_2},
                getAssertTrueCallback(latch),
                handler);
        waitForLatch(latch);

        latch = new CountDownLatch(1);
        am.hasFeatures(ACCOUNT,
                new String[]{NON_EXISTING_FEATURE},
                getAssertFalseCallback(latch),
                handler);
        waitForLatch(latch);

        latch = new CountDownLatch(1);
        am.hasFeatures(ACCOUNT,
                new String[]{NON_EXISTING_FEATURE, FEATURE_1},
                getAssertFalseCallback(latch),
                handler);
        waitForLatch(latch);

        latch = new CountDownLatch(1);
        am.hasFeatures(ACCOUNT,
                new String[]{NON_EXISTING_FEATURE, FEATURE_1, FEATURE_2},
                getAssertFalseCallback(latch),
                handler);
        waitForLatch(latch);
    }

    private long getLastAuthenticatedTime(Account account) throws OperationCanceledException,
            AuthenticatorException, IOException {
        Bundle options = new Bundle();
        options.putBoolean(MockAccountAuthenticator.KEY_RETURN_INTENT, true);
        // Not really confirming, but a way to get last authenticated timestamp
        Bundle result = am.confirmCredentials(account,
                options,// OPTIONS_BUNDLE,
                null, /* activity */
                null /* callback */,
                null /* handler */).getResult();
        return result.getLong(
                AccountManager.KEY_LAST_AUTHENTICATED_TIME, -1);
    }

    private long addAccountAndReturnAccountAddedTime(Account account, String password)
            throws OperationCanceledException, AuthenticatorException, IOException {
        addAccount(am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                OPTIONS_BUNDLE,
                mActivity,
                null /* callback */,
                null /* handler */);
        return getLastAuthenticatedTime(account);
    }

    /**
     * Tests that AccountManagerService is properly caching data.
     */
    public void testGetsAreCached() {

        // Add an account,
        assertEquals(false, isAccountPresent(am.getAccounts(), ACCOUNT));
        addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);

        // Then verify that we don't hit disk retrieving it,
        StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
        try {
            StrictMode.setThreadPolicy(
                    new StrictMode.ThreadPolicy.Builder().detectDiskReads().penaltyDeath().build());
            Account[] accounts = am.getAccounts();
            assertNotNull(accounts);
            assertTrue(accounts.length > 0);
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
    }

    /**
     * Tests a basic startAddAccountSession() which returns a bundle containing
     * encrypted session bundle, account password and status token.
     */
    public void testStartAddAccountSession()
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        validateStartAddAccountSessionParametersAndOptions(accountName, options);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
    }

    /**
     * Tests startAddAccountSession() with null session bundle. Only account
     * password and status token should be included in the result as session
     * bundle is not inspected.
     */
    public void testStartAddAccountSessionWithNullSessionBundle()
            throws IOException, AuthenticatorException, OperationCanceledException {
        final Bundle options = new Bundle();
        final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
        options.putAll(OPTIONS_BUNDLE);

        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        validateStartAddAccountSessionParametersAndOptions(accountName, options);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        assertNull(resultBundle.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
        assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
        assertEquals(ACCOUNT_STATUS_TOKEN,
                resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
    }

    /**
     * Tests startAddAccountSession() with empty session bundle. An encrypted
     * session bundle, account password and status token should be included in
     * the result as session bundle is not inspected.
     */
    public void testStartAddAccountSessionWithEmptySessionBundle()
            throws IOException, AuthenticatorException, OperationCanceledException {
        final Bundle options = new Bundle();
        final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
        options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, new Bundle());
        options.putAll(OPTIONS_BUNDLE);

        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        validateStartAddAccountSessionParametersAndOptions(accountName, options);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
    }

    /**
     * Tests startAddAccountSession with authenticator activity started. When
     * Activity is provided, AccountManager would start the resolution Intent
     * and return the final result which contains an encrypted session bundle,
     * account password and status token.
     */
    public void testStartAddAccountSessionIntervene()
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                mActivity,
                null /* callback */,
                null /* handler */);

        validateStartAddAccountSessionParametersAndOptions(accountName, options);

        // Assert returned result
        assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
    }

    /**
     * Tests startAddAccountSession with KEY_INTENT returned but not started
     * automatically. When no Activity is provided and authenticator requires
     * additional data from user, KEY_INTENT will be returned by AccountManager.
     */
    public void testStartAddAccountSessionWithReturnIntent()
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        validateStartAddAccountSessionParametersAndOptions(accountName, options);

        // Assert returned result
        Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
        // Assert that KEY_INTENT is returned.
        assertNotNull(returnIntent);
        assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
        // Assert that no other data is returned.
        assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
        assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
        assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
    }

    /**
     * Tests startAddAccountSession error case. AuthenticatorException is
     * expected when authenticator return
     * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
     */
    public void testStartAddAccountSessionError() throws IOException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_ERROR + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountNameAndError(accountName);

        try {
            startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);
            fail("startAddAccountSession should throw AuthenticatorException in error case.");
        } catch (AuthenticatorException e) {
        }
    }

    /**
     * Tests startAddAccountSession() with callback and handler. An encrypted
     * session bundle, account password and status token should be included in
     * the result. Callback should be triggered with the result regardless of a
     * handler is provided or not.
     */
    public void testStartAddAccountSessionWithCallbackAndHandler()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testStartAddAccountSessionWithCallbackAndHandler(null /* handler */);
        testStartAddAccountSessionWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests startAddAccountSession() with callback and handler and activity
     * started. When Activity is provided, AccountManager would start the
     * resolution Intent and return the final result which contains an encrypted
     * session bundle, account password and status token. Callback should be
     * triggered with the result regardless of a handled is provided or not.
     */
    public void testStartAddAccountSessionWithCallbackAndHandlerWithIntervene()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testStartAddAccountSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
        testStartAddAccountSessionWithCallbackAndHandlerWithIntervene(
                new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests startAddAccountSession() with callback and handler with KEY_INTENT
     * returned. When no Activity is provided and authenticator requires
     * additional data from user, KEY_INTENT will be returned by AccountManager
     * in callback regardless of a handler is provided or not.
     */
    public void testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
        testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent(
                new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests startAddAccountSession() error case with callback and handler.
     * AuthenticatorException is expected when authenticator return
     * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
     */
    public void testStartAddAccountSessionErrorWithCallbackAndHandler()
            throws IOException, OperationCanceledException {
        testStartAddAccountSessionErrorWithCallbackAndHandler(null /* handler */);
        testStartAddAccountSessionErrorWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    private void testStartAddAccountSessionWithCallbackAndHandler(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        // Wait with timeout for the callback to do its work
        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                validateStartAddAccountSessionParametersAndOptions(accountName, options);

                // Assert returned result
                // Assert that auth token was stripped.
                assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
                validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);

                latch.countDown();
            }
        };

        startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                mActivity,
                callback,
                handler);
        waitForLatch(latch);
    }

    private void testStartAddAccountSessionWithCallbackAndHandlerWithIntervene(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        // Wait with timeout for the callback to do its work
        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                validateStartAddAccountSessionParametersAndOptions(accountName, options);

                // Assert returned result
                assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
                // Assert that auth token was stripped.
                assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
                validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);

                latch.countDown();
            }
        };

        startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                mActivity,
                callback,
                handler);
        waitForLatch(latch);
    }

    private void testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        // Wait with timeout for the callback to do its work
        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                validateStartAddAccountSessionParametersAndOptions(accountName, options);

                // Assert returned result
                Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
                // Assert KEY_INTENT is returned.
                assertNotNull(returnIntent);
                assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
                // Assert that no other data is returned.
                assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
                assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
                assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
                assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));

                latch.countDown();
            }
        };

        startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null, // activity
                callback,
                handler);
        waitForLatch(latch);
    }

    private void testStartAddAccountSessionErrorWithCallbackAndHandler(Handler handler)
            throws IOException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountNameAndError(accountName);

        // Wait with timeout for the callback to do its work
        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                try {
                    bundleFuture.getResult();
                    fail("should have thrown an AuthenticatorException");
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    latch.countDown();
                }
            }
        };

        try {
            startAddAccountSession(
                    am,
                    ACCOUNT_TYPE,
                    AUTH_TOKEN_TYPE,
                    REQUIRED_FEATURES,
                    options,
                    mActivity,
                    callback,
                    handler);
            // AuthenticatorException should be thrown when authenticator
            // returns AccountManager.ERROR_CODE_INVALID_RESPONSE.
            fail("should have thrown an AuthenticatorException");
        } catch (AuthenticatorException e1) {
        }

        waitForLatch(latch);
    }

    /**
     * Test a basic startUpdateCredentialsSession() which returns a bundle containing
     * encrypted session bundle, account password and status token.
     */
    public void testStartUpdateCredentialsSession()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        Bundle resultBundle = startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        validateStartUpdateCredentialsSessionParametersAndOptions(accountName, options);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
    }

    /**
     * Tests startUpdateCredentialsSession() with null session bundle. Only account
     * password and status token should be included in the result as session
     * bundle is not inspected.
     */
    public void testStartUpdateCredentialsSessionWithNullSessionBundle()
            throws IOException, AuthenticatorException, OperationCanceledException {
        Bundle options = new Bundle();
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
        options.putAll(OPTIONS_BUNDLE);

        Bundle resultBundle = startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        validateStartUpdateCredentialsSessionParametersAndOptions(accountName, options);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        assertNull(resultBundle.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
        assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
        assertEquals(ACCOUNT_STATUS_TOKEN,
                resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
    }

    /**
     * Tests startUpdateCredentialsSession() with empty session bundle. An encrypted
     * session bundle, account password and status token should be included in
     * the result as session bundle is not inspected.
     */
    public void testStartUpdateCredentialsSessionWithEmptySessionBundle()
            throws IOException, AuthenticatorException, OperationCanceledException {
        Bundle options = new Bundle();
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
        options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, new Bundle());
        options.putAll(OPTIONS_BUNDLE);

        Bundle resultBundle = startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        validateStartUpdateCredentialsSessionParametersAndOptions(accountName, options);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
    }

    /**
     * Tests startUpdateCredentialsSession with authenticator activity started. When
     * Activity is provided, AccountManager would start the resolution Intent
     * and return the final result which contains an encrypted session bundle,
     * account password and status token.
     */
    public void testStartUpdateCredentialsSessionIntervene()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        Bundle resultBundle = startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                mActivity,
                null /* callback */,
                null /* handler */);

        validateStartUpdateCredentialsSessionParametersAndOptions(accountName, options);

        // Assert returned result
        assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
    }

    /**
     * Tests startUpdateCredentialsSession with KEY_INTENT returned but not
     * started automatically. When no Activity is provided and authenticator requires
     * additional data from user, KEY_INTENT will be returned by AccountManager.
     */
    public void testStartUpdateCredentialsSessionWithReturnIntent()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        Bundle resultBundle = startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        validateStartUpdateCredentialsSessionParametersAndOptions(accountName, options);

        // Assert returned result
        Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
        // Assert that KEY_INTENT is returned.
        assertNotNull(returnIntent);
        assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
        // Assert that no other data is returned.
        assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
        assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
        assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
    }

    /**
     * Tests startUpdateCredentialsSession error case. AuthenticatorException is
     * expected when authenticator return
     * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
     */
    public void testStartUpdateCredentialsSessionError()
            throws IOException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountNameAndError(accountName);

        try {
            startUpdateCredentialsSession(
                    am,
                    ACCOUNT,
                    AUTH_TOKEN_TYPE,
                    options,
                    null /* activity */,
                    null /* callback */,
                    null /* handler */);
            fail("startUpdateCredentialsSession should throw AuthenticatorException in error.");
        } catch (AuthenticatorException e) {
        }
    }

    /**
     * Tests startUpdateCredentialsSession() with callback and handler. An encrypted
     * session bundle, account password and status token should be included in
     * the result. Callback should be triggered with the result regardless of a
     * handler is provided or not.
     */
    public void testStartUpdateCredentialsSessionWithCallbackAndHandler()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testStartUpdateCredentialsSessionWithCallbackAndHandler(null /* handler */);
        testStartUpdateCredentialsSessionWithCallbackAndHandler(
                new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests startUpdateCredentialsSession() with callback and handler and
     * activity started. When Activity is provided, AccountManager would start the
     * resolution Intent and return the final result which contains an encrypted
     * session bundle, account password and status token. Callback should be
     * triggered with the result regardless of a handler is provided or not.
     */
    public void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
        testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene(
                new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests startUpdateCredentialsSession() with callback and handler with
     * KEY_INTENT returned. When no Activity is provided and authenticator requires
     * additional data from user, KEY_INTENT will be returned by AccountManager
     * in callback regardless of a handler is provided or not.
     */
    public void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
        testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent(
                new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests startUpdateCredentialsSession() error case with callback and
     * handler. AuthenticatorException is expected when authenticator return
     * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
     */
    public void testStartUpdateCredentialsSessionErrorWithCallbackAndHandler()
            throws IOException, OperationCanceledException {
        testStartUpdateCredentialsSessionErrorWithCallbackAndHandler(null /* handler */);
        testStartUpdateCredentialsSessionErrorWithCallbackAndHandler(
                new Handler(Looper.getMainLooper()));
    }

    private void testStartUpdateCredentialsSessionWithCallbackAndHandler(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                validateStartUpdateCredentialsSessionParametersAndOptions(accountName, options);

                // Assert returned result
                // Assert that auth token was stripped.
                assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
                validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);

                latch.countDown();
            }
        };

        startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                mActivity,
                callback,
                handler);

        waitForLatch(latch);
    }

    private void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene(
            Handler handler)
                    throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                validateStartUpdateCredentialsSessionParametersAndOptions(accountName, options);

                // Assert returned result
                assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
                // Assert that auth token was stripped.
                assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
                validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);

                latch.countDown();
            }
        };

        startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                mActivity,
                callback,
                handler);

        waitForLatch(latch);
    }

    private void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent(
            Handler handler)
                    throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountName(accountName);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                validateStartUpdateCredentialsSessionParametersAndOptions(accountName, options);

                // Assert returned result
                Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
                // Assert KEY_INTENT is returned.
                assertNotNull(returnIntent);
                assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));
                // Assert that no other data is returned.
                assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
                assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
                assertNull(resultBundle.getString(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
                assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));

                latch.countDown();
            }
        };

        startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                null,
                callback,
                handler);

        waitForLatch(latch);
    }

    private void testStartUpdateCredentialsSessionErrorWithCallbackAndHandler(Handler handler)
            throws IOException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        final Bundle options = createOptionsWithAccountNameAndError(accountName);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                try {
                    bundleFuture.getResult();
                    fail("should have thrown an AuthenticatorException");
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    latch.countDown();
                }
            }
        };

        try {
            startUpdateCredentialsSession(
                    am,
                    ACCOUNT,
                    AUTH_TOKEN_TYPE,
                    options,
                    mActivity,
                    callback,
                    handler);
            // AuthenticatorException should be thrown when authenticator
            // returns AccountManager.ERROR_CODE_INVALID_RESPONSE.
            fail("should have thrown an AuthenticatorException");
        } catch (AuthenticatorException e1) {
        }

        waitForLatch(latch);
    }

    private Bundle startUpdateCredentialsSession(AccountManager am,
            Account account,
            String authTokenType,
            Bundle options,
            Activity activity,
            AccountManagerCallback<Bundle> callback,
            Handler handler)
                    throws IOException, AuthenticatorException, OperationCanceledException {

        AccountManagerFuture<Bundle> futureBundle = am.startUpdateCredentialsSession(
                account,
                authTokenType,
                options,
                activity,
                callback,
                handler);

        Bundle resultBundle = futureBundle.getResult();
        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        return resultBundle;
    }

    private Bundle startAddAccountSession(AccountManager am,
            String accountType,
            String authTokenType,
            String[] requiredFeatures,
            Bundle options,
            Activity activity,
            AccountManagerCallback<Bundle> callback,
            Handler handler)
                    throws IOException, AuthenticatorException, OperationCanceledException {

        AccountManagerFuture<Bundle> futureBundle = am.startAddAccountSession(
                accountType,
                authTokenType,
                requiredFeatures,
                options,
                activity,
                callback,
                handler);

        Bundle resultBundle = futureBundle.getResult();
        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        return resultBundle;
    }

    private Bundle createOptionsWithAccountName(final String accountName) {
        SESSION_BUNDLE.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
        Bundle options = new Bundle();
        options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
        options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, SESSION_BUNDLE);
        options.putAll(OPTIONS_BUNDLE);
        return options;
    }

    private Bundle createOptionsWithAccountNameAndError(final String accountName) {
        Bundle options = createOptionsWithAccountName(accountName);
        options.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE);
        options.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);
        return options;
    }


    private void validateStartAddAccountSessionParametersAndOptions(
            String accountName, Bundle options) {
        // Assert parameters has been passed correctly
        validateAccountAndAuthTokenType();
        validateFeatures();

        // Validate options
        validateOptions(options, mockAuthenticator.mOptionsStartAddAccountSession);
        assertNotNull(mockAuthenticator.mOptionsStartAddAccountSession);
        assertEquals(accountName, mockAuthenticator.mOptionsStartAddAccountSession
                .getString(Fixtures.KEY_ACCOUNT_NAME));

        validateSystemOptions(mockAuthenticator.mOptionsStartAddAccountSession);
        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
        validateOptions(null, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
        validateOptions(null, mockAuthenticator.mOptionsFinishSession);
    }

    private void validateStartUpdateCredentialsSessionParametersAndOptions(
            String accountName, Bundle options) {
        // Assert parameters has been passed correctly
        assertEquals(AUTH_TOKEN_TYPE, mockAuthenticator.getAuthTokenType());
        assertEquals(ACCOUNT, mockAuthenticator.mAccount);

        // Validate options
        validateOptions(options, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
        assertNotNull(mockAuthenticator.mOptionsStartUpdateCredentialsSession);
        assertEquals(accountName, mockAuthenticator.mOptionsStartUpdateCredentialsSession
                .getString(Fixtures.KEY_ACCOUNT_NAME));

        // Validate system options
        assertNotNull(mockAuthenticator.mOptionsStartUpdateCredentialsSession
                .getString(AccountManager.KEY_ANDROID_PACKAGE_NAME));

        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
        validateOptions(null, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsStartAddAccountSession);
        validateOptions(null, mockAuthenticator.mOptionsFinishSession);
    }

    private void validateIsCredentialsUpdateSuggestedParametersAndOptions(Account account) {
        assertEquals(account, mockAuthenticator.getAccount());
        assertEquals(ACCOUNT_STATUS_TOKEN, mockAuthenticator.getStatusToken());

        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
        validateOptions(null, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
        validateOptions(null, mockAuthenticator.mOptionsStartAddAccountSession);
    }

    private void validateSessionBundleAndPasswordAndStatusTokenResult(Bundle resultBundle) {
        Bundle sessionBundle = resultBundle.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
        assertNotNull(sessionBundle);
        // Assert that session bundle is encrypted and hence data not visible.
        assertNull(sessionBundle.getString(SESSION_DATA_NAME_1));
        // Assert password is not returned since cts test is not signed with system key
        assertNull(resultBundle.getString(AccountManager.KEY_PASSWORD));
        assertEquals(ACCOUNT_STATUS_TOKEN,
                resultBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
    }

    private Bundle getResultExpectNoException(AccountManagerFuture<Bundle> bundleFuture) {
        try {
            return bundleFuture.getResult();
        } catch (OperationCanceledException e) {
            fail("should not throw an OperationCanceledException");
        } catch (IOException e) {
            fail("should not throw an IOException");
        } catch (AuthenticatorException e) {
            fail("should not throw an AuthenticatorException");
        }
        return null;
    }

    /**
     * Tests a basic finishSession() with session bundle created by
     * startAddAccountSession(...). A bundle containing account name and account
     * type is expected.
     */
    public void testFinishSessionWithStartAddAccountSession()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        resultBundle = finishSession(
                am,
                encryptedSessionBundle,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
        validateFinishSessionOptions(accountName, SESSION_BUNDLE);

        // Assert returned result containing account name, type but not auth token type.
        validateAccountAndNoAuthTokenResult(resultBundle);
    }

    /**
     * Tests a basic finishSession() with session bundle created by
     * startUpdateCredentialsSession(...). A bundle containing account name and account
     * type is expected.
     */
    public void testFinishSessionWithStartUpdateCredentialsSession()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startUpdateCredentialsSession(...)
        Bundle resultBundle = startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        resultBundle = finishSession(
                am,
                encryptedSessionBundle,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());
        validateFinishSessionOptions(accountName, SESSION_BUNDLE);

        // Assert returned result containing account name, type but not auth token type.
        validateAccountAndNoAuthTokenResult(resultBundle);
    }

    /**
     * Tests finishSession() with null session bundle. IllegalArgumentException
     * is expected as session bundle cannot be null.
     */
    public void testFinishSessionWithNullSessionBundle()
            throws IOException, AuthenticatorException, OperationCanceledException {
        try {
            finishSession(
                    am,
                    null /* sessionBundle */,
                    null /* activity */,
                    null /* callback */,
                    null /* handler */);
            fail("Should have thrown IllegalArgumentException when sessionBundle is null");
        } catch (IllegalArgumentException e) {

        }
    }

    /**
     * Tests finishSession() with empty session bundle. IllegalArgumentException
     * is expected as session bundle would always contain something if it was
     * processed properly by AccountManagerService.
     */
    public void testFinishSessionWithEmptySessionBundle()
            throws IOException, AuthenticatorException, OperationCanceledException {

        try {
            finishSession(am,
                    new Bundle(),
                    null /* activity */,
                    null /* callback */,
                    null /* handler */);
            fail("Should have thrown IllegalArgumentException when sessionBundle is empty");
        } catch (IllegalArgumentException e) {

        }
    }

    /**
     * Tests finishSession() with sessionBundle not encrypted by the right key.
     * AuthenticatorException is expected if AccountManagerService failed to
     * decrypt the session bundle because of wrong key or crypto data was
     * tampered.
     */
    public void testFinishSessionWithDecryptionError()
            throws IOException, OperationCanceledException {
        byte[] mac = new byte[] {
                1, 1, 0, 0
        };
        byte[] cipher = new byte[] {
                1, 0, 0, 1, 1
        };
        Bundle sessionBundle = new Bundle();
        sessionBundle.putByteArray(KEY_MAC, mac);
        sessionBundle.putByteArray(KEY_CIPHER, cipher);

        try {
            finishSession(am,
                    sessionBundle,
                    null /* activity */,
                    null /* callback */,
                    null /* handler */);
            fail("Should have thrown AuthenticatorException when failed to decrypt sessionBundle");
        } catch (AuthenticatorException e) {

        }
    }

    /**
     * Tests finishSession() with sessionBundle invalid contents.
     * AuthenticatorException is expected if AccountManagerService failed to
     * decrypt the session bundle because of wrong key or crypto data was
     * tampered.
     */
    public void testFinishSessionWithInvalidEncryptedContent()
            throws IOException, OperationCanceledException {
        byte[] mac = new byte[] {};
        Bundle sessionBundle = new Bundle();
        sessionBundle.putByteArray(KEY_MAC, mac);

        try {
            finishSession(am,
                    sessionBundle,
                    null /* activity */,
                    null /* callback */,
                    null /* handler */);
            fail("Should have thrown AuthenticatorException when failed to decrypt sessionBundle");
        } catch (AuthenticatorException e) {
        }
    }

    /**
     * Tests a finishSession() when account type is not added to session bundle
     * by startAddAccount(...) of authenticator. A bundle containing account
     * name and account type should still be returned as AccountManagerSerivce
     * will always add account type to the session bundle before encrypting it.
     */
    public void testFinishSessionFromStartAddAccountWithoutAccountType()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        // Create a session bundle without account type for MockAccountAuthenticator to return
        SESSION_BUNDLE.remove(AccountManager.KEY_ACCOUNT_TYPE);
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        resultBundle = finishSession(
                am,
                encryptedSessionBundle,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

        validateFinishSessionOptions(accountName, SESSION_BUNDLE);

        // Assert returned result containing account name, type but not auth token type.
        validateAccountAndNoAuthTokenResult(resultBundle);
    }

    /**
     * Tests a finishSession() when account type is not added to session bundle
     * by startUpdateCredentialsSession(...) of authenticator. A bundle
     * containing account name and account type should still be returned as
     * AccountManagerSerivce will always add account type to the session bundle
     * before encrypting it.
     */
    public void testFinishSessionFromStartUpdateCredentialsSessionWithoutAccountType()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        // Create a session bundle without account type for MockAccountAuthenticator to return
        SESSION_BUNDLE.remove(AccountManager.KEY_ACCOUNT_TYPE);
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        resultBundle = finishSession(
                am,
                encryptedSessionBundle,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

        validateFinishSessionOptions(accountName, SESSION_BUNDLE);

        // Assert returned result containing account name, type but not auth token type.
        validateAccountAndNoAuthTokenResult(resultBundle);
    }

    /**
     * Tests a finishSession() when a different account type is added to session bundle
     * by startAddAccount(...) of authenticator. A bundle containing account
     * name and the correct account type should be returned as AccountManagerSerivce
     * will always overrides account type to the session bundle before encrypting it.
     */
    public void testFinishSessionFromStartAddAccountAccountTypeOverriden()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        SESSION_BUNDLE.putString(AccountManager.KEY_ACCOUNT_TYPE, "randomAccountType");
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        resultBundle = finishSession(
                am,
                encryptedSessionBundle,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

        validateFinishSessionOptions(accountName, SESSION_BUNDLE);

        // Assert returned result containing account name, correct type but not auth token type.
        validateAccountAndNoAuthTokenResult(resultBundle);
    }

    /**
     * Tests a finishSession() when a different account type is added to session bundle
     * by startUpdateCredentialsSession(...) of authenticator. A bundle
     * containing account name and the correct account type should be returned as
     * AccountManagerSerivce will always override account type to the session bundle
     * before encrypting it.
     */
    public void testFinishSessionFromStartUpdateCredentialsSessionAccountTypeOverriden()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        // MockAccountAuthenticator to return
        SESSION_BUNDLE.putString(AccountManager.KEY_ACCOUNT_TYPE, "randomAccountType");
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startUpdateCredentialsSession(
                am,
                ACCOUNT,
                AUTH_TOKEN_TYPE,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        resultBundle = finishSession(
                am,
                encryptedSessionBundle,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

        validateFinishSessionOptions(accountName, SESSION_BUNDLE);

        // Assert returned result containing account name, correct type but not auth token type.
        validateAccountAndNoAuthTokenResult(resultBundle);
    }

    /**
     * Tests finishSession with authenticator activity started. When additional
     * info is needed from user for finishing the session and an Activity was
     * provided by caller, the resolution intent will be started automatically.
     * A bundle containing account name and type will be returned.
     */
    public void testFinishSessionIntervene()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                mActivity,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        resultBundle = finishSession(
                am,
                encryptedSessionBundle,
                mActivity,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

        validateFinishSessionOptions(accountName, SESSION_BUNDLE);

        // Assert returned result
        assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
        // Assert returned result containing account name, type but not auth token type.
        validateAccountAndNoAuthTokenResult(resultBundle);
    }

    /**
     * Tests finishSession with KEY_INTENT returned but not started
     * automatically. When additional info is needed from user for finishing the
     * session and no Activity was provided by caller, the resolution intent
     * will not be started automatically. A bundle containing KEY_INTENT will be
     * returned instead.
     */
    public void testFinishSessionWithReturnIntent()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                mActivity,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        resultBundle = finishSession(
                am,
                encryptedSessionBundle,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

        validateFinishSessionOptions(accountName, SESSION_BUNDLE);

        // Assert returned result
        Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
        assertNotNull(returnIntent);
        assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));

        assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_NAME));
        assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_TYPE));
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
    }

    /**
     * Tests finishSession error case. AuthenticatorException is expected when
     * AccountManager.ERROR_CODE_INVALID_RESPONSE is returned by authenticator.
     */
    public void testFinishSessionError()
            throws IOException, AuthenticatorException, OperationCanceledException {
        Bundle sessionBundle = new Bundle();
        String accountNameForFinish = Fixtures.PREFIX_NAME_ERROR + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        sessionBundle.putString(Fixtures.KEY_ACCOUNT_NAME, accountNameForFinish);
        sessionBundle.putInt(AccountManager.KEY_ERROR_CODE,
                AccountManager.ERROR_CODE_INVALID_RESPONSE);
        sessionBundle.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);

        Bundle options = new Bundle();
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
        options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
        options.putAll(OPTIONS_BUNDLE);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        try {
            finishSession(
                    am,
                    encryptedSessionBundle,
                    null /* activity */,
                    null /* callback */,
                    null /* handler */);
            fail("finishSession should throw AuthenticatorException in error case.");
        } catch (AuthenticatorException e) {
        }
    }

    /**
     * Tests finishSession() with callback and handler. A bundle containing
     * account name and type should be returned via the callback regardless of
     * whether a handler is provided.
     */
    public void testFinishSessionWithCallbackAndHandler()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testFinishSessionWithCallbackAndHandler(null /* handler */);
        testFinishSessionWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests finishSession() with callback and handler and activity started.
     * When additional info is needed from user for finishing the session and an
     * Activity was provided by caller, the resolution intent will be started
     * automatically. A bundle containing account name and type will be returned
     * via the callback regardless of if handler is provided or now.
     */
    public void testFinishSessionWithCallbackAndHandlerWithIntervene()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testFinishSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
        testFinishSessionWithCallbackAndHandlerWithIntervene(
                new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests finishSession() with callback and handler with KEY_INTENT
     * returned. When additional info is needed from user for finishing the
     * session and no Activity was provided by caller, the resolution intent
     * will not be started automatically. A bundle containing KEY_INTENT will be
     * returned instead via callback regardless of if handler is provided or not.
     */
    public void testFinishSessionWithCallbackAndHandlerWithReturnIntent()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testFinishSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
        testFinishSessionWithCallbackAndHandlerWithReturnIntent(
                new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests finishSession() error case with callback and handler.
     * AuthenticatorException is expected when
     * AccountManager.ERROR_CODE_INVALID_RESPONSE is returned by authenticator.
     */
    public void testFinishSessionErrorWithCallbackAndHandler()
            throws IOException, OperationCanceledException, AuthenticatorException {
        testFinishSessionErrorWithCallbackAndHandler(null /* handler */);
        testFinishSessionErrorWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
    }

    private void testFinishSessionWithCallbackAndHandler(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                // Assert parameters has been passed correctly
                assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

                validateFinishSessionOptions(accountName, SESSION_BUNDLE);

                // Assert returned result containing account name, type but not auth token type.
                validateAccountAndNoAuthTokenResult(resultBundle);

                latch.countDown();
            }
        };

        finishSession(am, encryptedSessionBundle, mActivity, callback, handler);

        // Wait with timeout for the callback to do its work
        waitForLatch(latch);
    }

    private void testFinishSessionWithCallbackAndHandlerWithIntervene(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                mActivity,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                // Assert parameters has been passed correctly
                assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

                validateFinishSessionOptions(accountName, SESSION_BUNDLE);

                // Assert returned result
                assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
                // Assert returned result containing account name, type but not auth token type.
                validateAccountAndNoAuthTokenResult(resultBundle);

                latch.countDown();
            }
        };

        finishSession(am, encryptedSessionBundle, mActivity, callback, handler);

        // Wait with timeout for the callback to do its work
        waitForLatch(latch);
    }

    private void testFinishSessionWithCallbackAndHandlerWithReturnIntent(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        Bundle options = createOptionsWithAccountName(accountName);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                mActivity,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        assertNull(resultBundle.getParcelable(AccountManager.KEY_INTENT));
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                Bundle resultBundle = getResultExpectNoException(bundleFuture);

                // Assert parameters has been passed correctly
                assertEquals(ACCOUNT_TYPE, mockAuthenticator.getAccountType());

                validateFinishSessionOptions(accountName, SESSION_BUNDLE);

                // Assert returned result
                Intent returnIntent = resultBundle.getParcelable(AccountManager.KEY_INTENT);
                assertNotNull(returnIntent);
                assertNotNull(returnIntent.getParcelableExtra(Fixtures.KEY_RESULT));

                assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_NAME));
                assertNull(resultBundle.get(AccountManager.KEY_ACCOUNT_TYPE));
                assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));

                latch.countDown();
            }
        };

        finishSession(am, encryptedSessionBundle, null, callback, handler);

        // Wait with timeout for the callback to do its work
        waitForLatch(latch);
    }

    private void testFinishSessionErrorWithCallbackAndHandler(Handler handler)
            throws IOException, OperationCanceledException, AuthenticatorException {
        Bundle sessionBundle = new Bundle();
        String accountNameForFinish = Fixtures.PREFIX_NAME_ERROR + "@"
                + Fixtures.SUFFIX_NAME_FIXTURE;
        sessionBundle.putString(Fixtures.KEY_ACCOUNT_NAME, accountNameForFinish);
        sessionBundle.putInt(AccountManager.KEY_ERROR_CODE,
                AccountManager.ERROR_CODE_INVALID_RESPONSE);
        sessionBundle.putString(AccountManager.KEY_ERROR_MESSAGE, ERROR_MESSAGE);

        Bundle options = new Bundle();
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        options.putString(Fixtures.KEY_ACCOUNT_NAME, accountName);
        options.putBundle(Fixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
        options.putAll(OPTIONS_BUNDLE);

        // First get an encrypted session bundle from startAddAccountSession(...)
        Bundle resultBundle = startAddAccountSession(
                am,
                ACCOUNT_TYPE,
                AUTH_TOKEN_TYPE,
                REQUIRED_FEATURES,
                options,
                null /* activity */,
                null /* callback */,
                null /* handler */);

        // Assert returned result
        // Assert that auth token was stripped.
        assertNull(resultBundle.get(AccountManager.KEY_AUTHTOKEN));
        validateSessionBundleAndPasswordAndStatusTokenResult(resultBundle);
        Bundle encryptedSessionBundle = resultBundle
                .getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
            @Override
            public void run(AccountManagerFuture<Bundle> bundleFuture) {
                try {
                    bundleFuture.getResult();
                    fail("should have thrown an AuthenticatorException");
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    latch.countDown();
                }
            }
        };

        try {
            finishSession(am, encryptedSessionBundle, mActivity, callback, handler);
            fail("should have thrown an AuthenticatorException");
        } catch (AuthenticatorException e1) {
        }

        // Wait with timeout for the callback to do its work
        waitForLatch(latch);
    }

    private Bundle finishSession(AccountManager am, Bundle sessionBundle, Activity activity,
            AccountManagerCallback<Bundle> callback, Handler handler)
                    throws IOException, AuthenticatorException, OperationCanceledException {
        // Cleanup before calling finishSession(...) with the encrypted session bundle.
        mockAuthenticator.clearData();

        AccountManagerFuture<Bundle> futureBundle = am.finishSession(
                sessionBundle,
                activity,
                callback,
                handler);

        Bundle resultBundle = futureBundle.getResult();
        assertTrue(futureBundle.isDone());
        assertNotNull(resultBundle);

        return resultBundle;
    }

    private void validateFinishSessionOptions(String accountName, Bundle options) {
        validateOptions(options, mockAuthenticator.mOptionsFinishSession);
        assertNotNull(mockAuthenticator.mOptionsFinishSession);
        assertEquals(ACCOUNT_TYPE, mockAuthenticator.mOptionsFinishSession
                .getString(AccountManager.KEY_ACCOUNT_TYPE));
        assertEquals(accountName,
                mockAuthenticator.mOptionsFinishSession.getString(Fixtures.KEY_ACCOUNT_NAME));

        validateSystemOptions(mockAuthenticator.mOptionsFinishSession);
        validateOptions(null, mockAuthenticator.mOptionsUpdateCredentials);
        validateOptions(null, mockAuthenticator.mOptionsConfirmCredentials);
        validateOptions(null, mockAuthenticator.mOptionsGetAuthToken);
        validateOptions(null, mockAuthenticator.mOptionsAddAccount);
        validateOptions(null, mockAuthenticator.mOptionsStartAddAccountSession);
        validateOptions(null, mockAuthenticator.mOptionsStartUpdateCredentialsSession);
    }

    /**
     * Tests a basic isCredentialsUpdateSuggested() which returns a bundle containing boolean true.
     */
    public void testIsCredentialsUpdateSuggested_Success()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Account account = new Account(accountName, ACCOUNT_TYPE);

        Boolean result = isCredentialsUpdateSuggested(
                am,
                account,
                ACCOUNT_STATUS_TOKEN,
                null /* callback */,
                null /* handler */);

        // Assert parameters has been passed correctly
        validateIsCredentialsUpdateSuggestedParametersAndOptions(account);

        // Assert returned result
        assertTrue(result);
    }

    /**
     * Tests isCredentialsUpdateSuggested() when account is null.
     * It should throw IllegalArgumentationException.
     */
    public void testIsCredentialsUpdateSuggestedNullAccount_IllegalArgumentationException()
            throws IOException, AuthenticatorException, OperationCanceledException {

        try {
            isCredentialsUpdateSuggested(
                    am,
                    null /* account */,
                    ACCOUNT_STATUS_TOKEN,
                    null /* callback */,
                    null /* handler */);
            fail("Should have thrown IllegalArgumentation when calling with null account!");
        } catch (IllegalArgumentException e) {
        }
    }

    /**
     * Tests isCredentialsUpdateSuggested() when statusToken is empty.
     * It should throw IllegalArgumentationException.
     */
    public void testIsCredentialsUpdateSuggestedEmptyToken_IllegalArgumentationException()
            throws IOException, AuthenticatorException, OperationCanceledException {

        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Account account = new Account(accountName, ACCOUNT_TYPE);
        try {
            isCredentialsUpdateSuggested(
                    am,
                    account,
                    "" /* statusToken */,
                    null /* callback */,
                    null /* handler */);
            fail("Should have thrown IllegalArgumentation when calling with empty statusToken!");
        } catch (IllegalArgumentException e) {
        }
    }

    /**
     * Tests isCredentialsUpdateSuggested() error case. AuthenticatorException is expected when
     * authenticator return {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
     */
    public void testIsCredentialsUpdateSuggested_Error()
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        Account account = new Account(accountName, ACCOUNT_TYPE);

        try {
            isCredentialsUpdateSuggested(
                    am,
                    account,
                    ACCOUNT_STATUS_TOKEN,
                    null /* callback */,
                    null /* handler */);
            fail("Should have thrown AuthenticatorException in error case.");
        } catch (AuthenticatorException e) {
        }
    }

    /**
     * Tests isCredentialsUpdateSuggested() with callback and handler. A boolean should be included
     * in the result. Callback should be triggered with the result regardless of a handler is
     * provided or not.
     */
    public void testIsCredentialsUpdateSuggestedWithCallbackAndHandler()
            throws IOException, AuthenticatorException, OperationCanceledException {
        testIsCredentialsUpdateSuggestedWithCallbackAndHandler(null /* handler */);
        testIsCredentialsUpdateSuggestedWithCallbackAndHandler(
                new Handler(Looper.getMainLooper()));
    }

    /**
     * Tests isCredentialsUpdateSuggested() error case with callback and handler.
     * AuthenticatorException is expected when authenticator return
     * {@link AccountManager#ERROR_CODE_INVALID_RESPONSE} error code.
     */
    public void testIsCredentialsUpdateSuggestedErrorWithCallbackAndHandler()
            throws IOException, OperationCanceledException, AuthenticatorException {
        testIsCredentialsUpdateSuggestedErrorWithCallbackAndHandler(null /* handler */);
        testIsCredentialsUpdateSuggestedErrorWithCallbackAndHandler(
                new Handler(Looper.getMainLooper()));
    }

    private void testIsCredentialsUpdateSuggestedWithCallbackAndHandler(Handler handler)
            throws IOException, AuthenticatorException, OperationCanceledException {
        String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        final Account account = new Account(accountName, ACCOUNT_TYPE);
        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Boolean> callback = new AccountManagerCallback<Boolean>() {
            @Override
            public void run(AccountManagerFuture<Boolean> booleanFuture) {
                Boolean result = false;
                try {
                    result = booleanFuture.getResult();
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    fail("should not throw an AuthenticatorException");
                }

                // Assert parameters has been passed correctly
                validateIsCredentialsUpdateSuggestedParametersAndOptions(account);

                // Assert returned result
                assertTrue(result);

                latch.countDown();
            }
        };

        isCredentialsUpdateSuggested(
                am,
                account,
                ACCOUNT_STATUS_TOKEN,
                callback,
                handler);

        // Wait with timeout for the callback to do its work
        waitForLatch(latch);
    }

    private void testIsCredentialsUpdateSuggestedErrorWithCallbackAndHandler(Handler handler)
            throws IOException, OperationCanceledException, AuthenticatorException {
        String accountName = Fixtures.PREFIX_NAME_ERROR + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
        final Account account = new Account(accountName, ACCOUNT_TYPE);

        final CountDownLatch latch = new CountDownLatch(1);

        AccountManagerCallback<Boolean> callback = new AccountManagerCallback<Boolean>() {
            @Override
            public void run(AccountManagerFuture<Boolean> booleanFuture) {
                try {
                    booleanFuture.getResult();
                    // AuthenticatorException should be thrown when authenticator
                    // returns AccountManager.ERROR_CODE_INVALID_RESPONSE.
                    fail("should have thrown an AuthenticatorException");
                } catch (OperationCanceledException e) {
                    fail("should not throw an OperationCanceledException");
                } catch (IOException e) {
                    fail("should not throw an IOException");
                } catch (AuthenticatorException e) {
                    // Test passed as AuthenticatorException is expected.
                } finally {
                    latch.countDown();
                }
            }
        };

        isCredentialsUpdateSuggested(
                am,
                account,
                ACCOUNT_STATUS_TOKEN,
                callback,
                handler);

        // Wait with timeout for the callback to do its work
        waitForLatch(latch);
    }

    private Boolean isCredentialsUpdateSuggested(
            AccountManager am,
            Account account,
            String statusToken,
            AccountManagerCallback<Boolean> callback,
            Handler handler)
                    throws IOException, AuthenticatorException, OperationCanceledException {

        AccountManagerFuture<Boolean> booleanFuture = am.isCredentialsUpdateSuggested(
                account,
                statusToken,
                callback,
                handler);

        Boolean result = false;
        if (callback == null) {
            result = booleanFuture.getResult();
            assertTrue(booleanFuture.isDone());
        }

        return result;
    }

    private void verifyAccountsGroupedByType(Account[] accounts) {

        Map<String, Integer> firstPositionForType = new HashMap<>();
        Map<String, Integer> lastPositionForType = new HashMap<>();
        Map<String, Integer> counterForType = new HashMap<>();
        for (int i = 0; i < accounts.length; i++) {
            String type = accounts[i].type;

            Integer first = firstPositionForType.get(type);
            first = first != null ? first : Integer.MAX_VALUE;
            firstPositionForType.put(type, Math.min(first, i));

            Integer last = lastPositionForType.get(type);
            last = last != null ? last : Integer.MIN_VALUE;
            lastPositionForType.put(type, Math.max(last, i));

            Integer counter = counterForType.get(type);
            counter = counter != null ? counter  : 0;
            counterForType.put(type, counter + 1);
        }
        for (String type : counterForType.keySet()) {
            assertEquals((int)lastPositionForType.get(type),
                firstPositionForType.get(type) + counterForType.get(type) - 1);
        }
    }
}
