/* * 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 com.android.server.accounts; import static android.database.sqlite.SQLiteDatabase.deleteDatabase; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.never; import static org.mockito.Mockito.nullable; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerInternal; import android.accounts.CantAddAccountActivity; import android.accounts.IAccountManagerResponse; import android.app.AppOpsManager; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.app.INotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.content.pm.UserInfo; import android.database.Cursor; import android.database.DatabaseErrorHandler; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.test.AndroidTestCase; import android.test.mock.MockContext; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import com.android.frameworks.servicestests.R; import com.android.server.LocalServices; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; /** * Tests for {@link AccountManagerService}. *

Run with:

 * mmma -j40 frameworks/base/services/tests/servicestests
 * adb install -r ${OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
 * adb shell am instrument -w -e package com.android.server.accounts \
 * com.android.frameworks.servicestests\
 * /android.support.test.runner.AndroidJUnitRunner
 * 
*/ public class AccountManagerServiceTest extends AndroidTestCase { private static final String TAG = AccountManagerServiceTest.class.getSimpleName(); private static final long ONE_DAY_IN_MILLISECOND = 86400000; @Mock private Context mMockContext; @Mock private AppOpsManager mMockAppOpsManager; @Mock private UserManager mMockUserManager; @Mock private PackageManager mMockPackageManager; @Mock private DevicePolicyManagerInternal mMockDevicePolicyManagerInternal; @Mock private DevicePolicyManager mMockDevicePolicyManager; @Mock private IAccountManagerResponse mMockAccountManagerResponse; @Mock private IBinder mMockBinder; @Mock private INotificationManager mMockNotificationManager; @Captor private ArgumentCaptor mIntentCaptor; @Captor private ArgumentCaptor mBundleCaptor; private int mVisibleAccountsChangedBroadcasts; private int mLoginAccountsChangedBroadcasts; private int mAccountRemovedBroadcasts; private static final int LATCH_TIMEOUT_MS = 500; private static final String PREN_DB = "pren.db"; private static final String DE_DB = "de.db"; private static final String CE_DB = "ce.db"; private PackageInfo mPackageInfo; private AccountManagerService mAms; private TestInjector mTestInjector; @Override protected void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mMockPackageManager.checkSignatures(anyInt(), anyInt())) .thenReturn(PackageManager.SIGNATURE_MATCH); final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0); when(mMockUserManager.getUserInfo(eq(ui.id))).thenReturn(ui); when(mMockContext.createPackageContextAsUser( anyString(), anyInt(), any(UserHandle.class))).thenReturn(mMockContext); when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); mPackageInfo = new PackageInfo(); mPackageInfo.signatures = new Signature[1]; mPackageInfo.signatures[0] = new Signature(new byte[] {'a', 'b', 'c', 'd'}); mPackageInfo.applicationInfo = new ApplicationInfo(); mPackageInfo.applicationInfo.privateFlags = ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(mPackageInfo); when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOpsManager); when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); when(mMockContext.getSystemServiceName(AppOpsManager.class)).thenReturn( Context.APP_OPS_SERVICE); when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_GRANTED); Bundle bundle = new Bundle(); when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle); when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( mMockDevicePolicyManager); when(mMockAccountManagerResponse.asBinder()).thenReturn(mMockBinder); Context realTestContext = getContext(); MyMockContext mockContext = new MyMockContext(realTestContext, mMockContext); setContext(mockContext); mTestInjector = new TestInjector(realTestContext, mockContext, mMockNotificationManager); mAms = new AccountManagerService(mTestInjector); } @Override protected void tearDown() throws Exception { // Let async logging tasks finish, otherwise they may crash due to db being removed CountDownLatch cdl = new CountDownLatch(1); mAms.mHandler.post(() -> { deleteDatabase(new File(mTestInjector.getCeDatabaseName(UserHandle.USER_SYSTEM))); deleteDatabase(new File(mTestInjector.getDeDatabaseName(UserHandle.USER_SYSTEM))); deleteDatabase(new File(mTestInjector.getPreNDatabaseName(UserHandle.USER_SYSTEM))); cdl.countDown(); }); cdl.await(1, TimeUnit.SECONDS); super.tearDown(); } class AccountSorter implements Comparator { public int compare(Account object1, Account object2) { if (object1 == object2) return 0; if (object1 == null) return 1; if (object2 == null) return -1; int result = object1.type.compareTo(object2.type); if (result != 0) return result; return object1.name.compareTo(object2.name); } } @SmallTest public void testCheckAddAccount() throws Exception { unlockSystemUser(); Account a11 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); Account a21 = new Account("account2", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); Account a31 = new Account("account3", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); Account a12 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); Account a22 = new Account("account2", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); Account a32 = new Account("account3", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); mAms.addAccountExplicitly(a11, "p11", null); mAms.addAccountExplicitly(a12, "p12", null); mAms.addAccountExplicitly(a21, "p21", null); mAms.addAccountExplicitly(a22, "p22", null); mAms.addAccountExplicitly(a31, "p31", null); mAms.addAccountExplicitly(a32, "p32", null); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName()); Arrays.sort(accounts, new AccountSorter()); assertEquals(6, accounts.length); assertEquals(a11, accounts[0]); assertEquals(a21, accounts[1]); assertEquals(a31, accounts[2]); assertEquals(a12, accounts[3]); assertEquals(a22, accounts[4]); assertEquals(a32, accounts[5]); accounts = mAms.getAccounts(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, mContext.getOpPackageName()); Arrays.sort(accounts, new AccountSorter()); assertEquals(3, accounts.length); assertEquals(a11, accounts[0]); assertEquals(a21, accounts[1]); assertEquals(a31, accounts[2]); mAms.removeAccountInternal(a21); accounts = mAms.getAccounts(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, mContext.getOpPackageName()); Arrays.sort(accounts, new AccountSorter()); assertEquals(2, accounts.length); assertEquals(a11, accounts[0]); assertEquals(a31, accounts[1]); } @SmallTest public void testPasswords() throws Exception { unlockSystemUser(); Account a11 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); Account a12 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); mAms.addAccountExplicitly(a11, "p11", null); mAms.addAccountExplicitly(a12, "p12", null); assertEquals("p11", mAms.getPassword(a11)); assertEquals("p12", mAms.getPassword(a12)); mAms.setPassword(a11, "p11b"); assertEquals("p11b", mAms.getPassword(a11)); assertEquals("p12", mAms.getPassword(a12)); } @SmallTest public void testUserdata() throws Exception { unlockSystemUser(); Account a11 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); Bundle u11 = new Bundle(); u11.putString("a", "a_a11"); u11.putString("b", "b_a11"); u11.putString("c", "c_a11"); Account a12 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); Bundle u12 = new Bundle(); u12.putString("a", "a_a12"); u12.putString("b", "b_a12"); u12.putString("c", "c_a12"); mAms.addAccountExplicitly(a11, "p11", u11); mAms.addAccountExplicitly(a12, "p12", u12); assertEquals("a_a11", mAms.getUserData(a11, "a")); assertEquals("b_a11", mAms.getUserData(a11, "b")); assertEquals("c_a11", mAms.getUserData(a11, "c")); assertEquals("a_a12", mAms.getUserData(a12, "a")); assertEquals("b_a12", mAms.getUserData(a12, "b")); assertEquals("c_a12", mAms.getUserData(a12, "c")); mAms.setUserData(a11, "b", "b_a11b"); mAms.setUserData(a12, "c", null); assertEquals("a_a11", mAms.getUserData(a11, "a")); assertEquals("b_a11b", mAms.getUserData(a11, "b")); assertEquals("c_a11", mAms.getUserData(a11, "c")); assertEquals("a_a12", mAms.getUserData(a12, "a")); assertEquals("b_a12", mAms.getUserData(a12, "b")); assertNull(mAms.getUserData(a12, "c")); } @SmallTest public void testAuthtokens() throws Exception { unlockSystemUser(); Account a11 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); Account a12 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); mAms.addAccountExplicitly(a11, "p11", null); mAms.addAccountExplicitly(a12, "p12", null); mAms.setAuthToken(a11, "att1", "a11_att1"); mAms.setAuthToken(a11, "att2", "a11_att2"); mAms.setAuthToken(a11, "att3", "a11_att3"); mAms.setAuthToken(a12, "att1", "a12_att1"); mAms.setAuthToken(a12, "att2", "a12_att2"); mAms.setAuthToken(a12, "att3", "a12_att3"); assertEquals("a11_att1", mAms.peekAuthToken(a11, "att1")); assertEquals("a11_att2", mAms.peekAuthToken(a11, "att2")); assertEquals("a11_att3", mAms.peekAuthToken(a11, "att3")); assertEquals("a12_att1", mAms.peekAuthToken(a12, "att1")); assertEquals("a12_att2", mAms.peekAuthToken(a12, "att2")); assertEquals("a12_att3", mAms.peekAuthToken(a12, "att3")); mAms.setAuthToken(a11, "att3", "a11_att3b"); mAms.invalidateAuthToken(a12.type, "a12_att2"); assertEquals("a11_att1", mAms.peekAuthToken(a11, "att1")); assertEquals("a11_att2", mAms.peekAuthToken(a11, "att2")); assertEquals("a11_att3b", mAms.peekAuthToken(a11, "att3")); assertEquals("a12_att1", mAms.peekAuthToken(a12, "att1")); assertNull(mAms.peekAuthToken(a12, "att2")); assertEquals("a12_att3", mAms.peekAuthToken(a12, "att3")); assertNull(mAms.peekAuthToken(a12, "att2")); } @SmallTest public void testRemovedAccountSync() throws Exception { String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); unlockSystemUser(); Account a1 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); Account a2 = new Account("account2", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); mAms.addAccountExplicitly(a1, "p1", null); mAms.addAccountExplicitly(a2, "p2", null); Context originalContext = ((MyMockContext)getContext()).mTestContext; // create a separate instance of AMS. It initially assumes that user0 is locked AccountManagerService ams2 = new AccountManagerService(mTestInjector); // Verify that account can be removed when user is locked ams2.removeAccountInternal(a1); Account[] accounts = ams2.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName()); assertEquals(1, accounts.length); assertEquals("Only a2 should be returned", a2, accounts[0]); // Verify that CE db file is unchanged and still has 2 accounts String ceDatabaseName = mTestInjector.getCeDatabaseName(UserHandle.USER_SYSTEM); int accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName); assertEquals("CE database should still have 2 accounts", 2, accountsNumber); // Unlock the user and verify that db has been updated ams2.onUserUnlocked(newIntentForUser(UserHandle.USER_SYSTEM)); accounts = ams2.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName()); assertEquals(1, accounts.length); assertEquals("Only a2 should be returned", a2, accounts[0]); accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName); assertEquals("CE database should now have 1 account", 1, accountsNumber); } @SmallTest public void testPreNDatabaseMigration() throws Exception { String preNDatabaseName = mTestInjector.getPreNDatabaseName(UserHandle.USER_SYSTEM); Context originalContext = ((MyMockContext) getContext()).mTestContext; PreNTestDatabaseHelper.createV4Database(originalContext, preNDatabaseName); // Assert that database was created with 1 account int n = readNumberOfAccountsFromDbFile(originalContext, preNDatabaseName); assertEquals("pre-N database should have 1 account", 1, n); // Start testing unlockSystemUser(); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName()); assertEquals("1 account should be migrated", 1, accounts.length); assertEquals(PreNTestDatabaseHelper.ACCOUNT_NAME, accounts[0].name); assertEquals(PreNTestDatabaseHelper.ACCOUNT_PASSWORD, mAms.getPassword(accounts[0])); assertEquals("Authtoken should be migrated", PreNTestDatabaseHelper.TOKEN_STRING, mAms.peekAuthToken(accounts[0], PreNTestDatabaseHelper.TOKEN_TYPE)); assertFalse("pre-N database file should be removed but was found at " + preNDatabaseName, new File(preNDatabaseName).exists()); // Verify that ce/de files are present String deDatabaseName = mTestInjector.getDeDatabaseName(UserHandle.USER_SYSTEM); String ceDatabaseName = mTestInjector.getCeDatabaseName(UserHandle.USER_SYSTEM); assertTrue("DE database file should be created at " + deDatabaseName, new File(deDatabaseName).exists()); assertTrue("CE database file should be created at " + ceDatabaseName, new File(ceDatabaseName).exists()); } @SmallTest public void testStartAddAccountSessionWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.startAddAccountSession( null, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null); // optionsIn fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testStartAddAccountSessionWithNullAccountType() throws Exception { unlockSystemUser(); try { mAms.startAddAccountSession( mMockAccountManagerResponse, // response null, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null); // optionsIn fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testStartAddAccountSessionUserCannotModifyAccountNoDPM() throws Exception { unlockSystemUser(); Bundle bundle = new Bundle(); bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true); when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); mAms.startAddAccountSession( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null); // optionsIn verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString()); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM)); // verify the intent for default CantAddAccountActivity is sent. Intent intent = mIntentCaptor.getValue(); assertEquals(intent.getComponent().getClassName(), CantAddAccountActivity.class.getName()); assertEquals(intent.getIntExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, 0), AccountManager.ERROR_CODE_USER_RESTRICTED); } @SmallTest public void testStartAddAccountSessionUserCannotModifyAccountWithDPM() throws Exception { unlockSystemUser(); Bundle bundle = new Bundle(); bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true); when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); LocalServices.addService( DevicePolicyManagerInternal.class, mMockDevicePolicyManagerInternal); when(mMockDevicePolicyManagerInternal.createUserRestrictionSupportIntent( anyInt(), anyString())).thenReturn(new Intent()); when(mMockDevicePolicyManagerInternal.createShowAdminSupportIntent( anyInt(), anyBoolean())).thenReturn(new Intent()); mAms.startAddAccountSession( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null); // optionsIn verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString()); verify(mMockContext).startActivityAsUser(any(Intent.class), eq(UserHandle.SYSTEM)); verify(mMockDevicePolicyManagerInternal).createUserRestrictionSupportIntent( anyInt(), anyString()); } @SmallTest public void testStartAddAccountSessionUserCannotModifyAccountForTypeNoDPM() throws Exception { unlockSystemUser(); when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt())) .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"}); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); mAms.startAddAccountSession( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null); // optionsIn verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString()); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM)); // verify the intent for default CantAddAccountActivity is sent. Intent intent = mIntentCaptor.getValue(); assertEquals(intent.getComponent().getClassName(), CantAddAccountActivity.class.getName()); assertEquals(intent.getIntExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, 0), AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE); } @SmallTest public void testStartAddAccountSessionUserCannotModifyAccountForTypeWithDPM() throws Exception { unlockSystemUser(); when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( mMockDevicePolicyManager); when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt())) .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"}); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); LocalServices.addService( DevicePolicyManagerInternal.class, mMockDevicePolicyManagerInternal); when(mMockDevicePolicyManagerInternal.createUserRestrictionSupportIntent( anyInt(), anyString())).thenReturn(new Intent()); when(mMockDevicePolicyManagerInternal.createShowAdminSupportIntent( anyInt(), anyBoolean())).thenReturn(new Intent()); mAms.startAddAccountSession( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null); // optionsIn verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString()); verify(mMockContext).startActivityAsUser(any(Intent.class), eq(UserHandle.SYSTEM)); verify(mMockDevicePolicyManagerInternal).createShowAdminSupportIntent( anyInt(), anyBoolean()); } @SmallTest public void testStartAddAccountSessionSuccessWithoutPasswordForwarding() throws Exception { unlockSystemUser(); when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_DENIED); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS); mAms.startAddAccountSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures false, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE); assertNotNull(sessionBundle); // Assert that session bundle is encrypted and hence data not visible. assertNull(sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1)); // Assert password is not returned assertNull(result.getString(AccountManager.KEY_PASSWORD)); assertNull(result.getString(AccountManager.KEY_AUTHTOKEN, null)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN, result.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN)); } @SmallTest public void testStartAddAccountSessionSuccessWithPasswordForwarding() throws Exception { unlockSystemUser(); when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_GRANTED); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS); mAms.startAddAccountSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures false, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE); assertNotNull(sessionBundle); // Assert that session bundle is encrypted and hence data not visible. assertNull(sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1)); // Assert password is returned assertEquals(result.getString(AccountManager.KEY_PASSWORD), AccountManagerServiceTestFixtures.ACCOUNT_PASSWORD); assertNull(result.getString(AccountManager.KEY_AUTHTOKEN)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN, result.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN)); } @SmallTest public void testStartAddAccountSessionReturnWithInvalidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE); mAms.startAddAccountSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString()); } @SmallTest public void testStartAddAccountSessionReturnWithValidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE); mAms.startAddAccountSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Intent intent = result.getParcelable(AccountManager.KEY_INTENT); assertNotNull(intent); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT)); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK)); } @SmallTest public void testStartAddAccountSessionError() throws Exception { unlockSystemUser(); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_ERROR); options.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE); options.putString(AccountManager.KEY_ERROR_MESSAGE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.startAddAccountSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures false, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testStartUpdateCredentialsSessionWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.startUpdateCredentialsSession( null, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", true, // expectActivityLaunch null); // optionsIn fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testStartUpdateCredentialsSessionWithNullAccount() throws Exception { unlockSystemUser(); try { mAms.startUpdateCredentialsSession( mMockAccountManagerResponse, // response null, "authTokenType", true, // expectActivityLaunch null); // optionsIn fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testStartUpdateCredentialsSessionSuccessWithoutPasswordForwarding() throws Exception { unlockSystemUser(); when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_DENIED); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS); mAms.startUpdateCredentialsSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", false, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE); assertNotNull(sessionBundle); // Assert that session bundle is encrypted and hence data not visible. assertNull(sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1)); // Assert password is not returned assertNull(result.getString(AccountManager.KEY_PASSWORD)); assertNull(result.getString(AccountManager.KEY_AUTHTOKEN, null)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN, result.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN)); } @SmallTest public void testStartUpdateCredentialsSessionSuccessWithPasswordForwarding() throws Exception { unlockSystemUser(); when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_GRANTED); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS); mAms.startUpdateCredentialsSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", false, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE); assertNotNull(sessionBundle); // Assert that session bundle is encrypted and hence data not visible. assertNull(sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1)); // Assert password is returned assertEquals(result.getString(AccountManager.KEY_PASSWORD), AccountManagerServiceTestFixtures.ACCOUNT_PASSWORD); assertNull(result.getString(AccountManager.KEY_AUTHTOKEN)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN, result.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN)); } @SmallTest public void testStartUpdateCredentialsSessionReturnWithInvalidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE); mAms.startUpdateCredentialsSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "authTokenType", true, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString()); } @SmallTest public void testStartUpdateCredentialsSessionReturnWithValidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE); mAms.startUpdateCredentialsSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "authTokenType", true, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Intent intent = result.getParcelable(AccountManager.KEY_INTENT); assertNotNull(intent); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT)); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK)); } @SmallTest public void testStartUpdateCredentialsSessionError() throws Exception { unlockSystemUser(); Bundle options = createOptionsWithAccountName( AccountManagerServiceTestFixtures.ACCOUNT_NAME_ERROR); options.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE); options.putString(AccountManager.KEY_ERROR_MESSAGE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.startUpdateCredentialsSession( response, // response AccountManagerServiceTestFixtures.ACCOUNT_ERROR, "authTokenType", true, // expectActivityLaunch options); // optionsIn waitForLatch(latch); verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testFinishSessionAsUserWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.finishSessionAsUser( null, // response createEncryptedSessionBundle( AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS), false, // expectActivityLaunch createAppBundle(), // appInfo UserHandle.USER_SYSTEM); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testFinishSessionAsUserWithNullSessionBundle() throws Exception { unlockSystemUser(); try { mAms.finishSessionAsUser( mMockAccountManagerResponse, // response null, // sessionBundle false, // expectActivityLaunch createAppBundle(), // appInfo UserHandle.USER_SYSTEM); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testFinishSessionAsUserUserCannotModifyAccountNoDPM() throws Exception { unlockSystemUser(); Bundle bundle = new Bundle(); bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true); when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); mAms.finishSessionAsUser( mMockAccountManagerResponse, // response createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS), false, // expectActivityLaunch createAppBundle(), // appInfo 2); // fake user id verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString()); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.of(2))); // verify the intent for default CantAddAccountActivity is sent. Intent intent = mIntentCaptor.getValue(); assertEquals(intent.getComponent().getClassName(), CantAddAccountActivity.class.getName()); assertEquals(intent.getIntExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, 0), AccountManager.ERROR_CODE_USER_RESTRICTED); } @SmallTest public void testFinishSessionAsUserUserCannotModifyAccountWithDPM() throws Exception { unlockSystemUser(); Bundle bundle = new Bundle(); bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true); when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); LocalServices.addService( DevicePolicyManagerInternal.class, mMockDevicePolicyManagerInternal); when(mMockDevicePolicyManagerInternal.createUserRestrictionSupportIntent( anyInt(), anyString())).thenReturn(new Intent()); when(mMockDevicePolicyManagerInternal.createShowAdminSupportIntent( anyInt(), anyBoolean())).thenReturn(new Intent()); mAms.finishSessionAsUser( mMockAccountManagerResponse, // response createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS), false, // expectActivityLaunch createAppBundle(), // appInfo 2); // fake user id verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString()); verify(mMockContext).startActivityAsUser(any(Intent.class), eq(UserHandle.of(2))); verify(mMockDevicePolicyManagerInternal).createUserRestrictionSupportIntent( anyInt(), anyString()); } @SmallTest public void testFinishSessionAsUserWithBadSessionBundle() throws Exception { unlockSystemUser(); Bundle badSessionBundle = new Bundle(); badSessionBundle.putString("any", "any"); mAms.finishSessionAsUser( mMockAccountManagerResponse, // response badSessionBundle, // sessionBundle false, // expectActivityLaunch createAppBundle(), // appInfo 2); // fake user id verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_BAD_REQUEST), anyString()); } @SmallTest public void testFinishSessionAsUserWithBadAccountType() throws Exception { unlockSystemUser(); mAms.finishSessionAsUser( mMockAccountManagerResponse, // response createEncryptedSessionBundleWithNoAccountType( AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS), false, // expectActivityLaunch createAppBundle(), // appInfo 2); // fake user id verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_BAD_ARGUMENTS), anyString()); } @SmallTest public void testFinishSessionAsUserUserCannotModifyAccountForTypeNoDPM() throws Exception { unlockSystemUser(); when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt())) .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"}); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); mAms.finishSessionAsUser( mMockAccountManagerResponse, // response createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS), false, // expectActivityLaunch createAppBundle(), // appInfo 2); // fake user id verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString()); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.of(2))); // verify the intent for default CantAddAccountActivity is sent. Intent intent = mIntentCaptor.getValue(); assertEquals(intent.getComponent().getClassName(), CantAddAccountActivity.class.getName()); assertEquals(intent.getIntExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, 0), AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE); } @SmallTest public void testFinishSessionAsUserUserCannotModifyAccountForTypeWithDPM() throws Exception { unlockSystemUser(); when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( mMockDevicePolicyManager); when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt())) .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"}); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); LocalServices.addService( DevicePolicyManagerInternal.class, mMockDevicePolicyManagerInternal); when(mMockDevicePolicyManagerInternal.createUserRestrictionSupportIntent( anyInt(), anyString())).thenReturn(new Intent()); when(mMockDevicePolicyManagerInternal.createShowAdminSupportIntent( anyInt(), anyBoolean())).thenReturn(new Intent()); mAms.finishSessionAsUser( mMockAccountManagerResponse, // response createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS), false, // expectActivityLaunch createAppBundle(), // appInfo 2); // fake user id verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString()); verify(mMockContext).startActivityAsUser(any(Intent.class), eq(UserHandle.of(2))); verify(mMockDevicePolicyManagerInternal).createShowAdminSupportIntent( anyInt(), anyBoolean()); } @SmallTest public void testFinishSessionAsUserSuccess() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.finishSessionAsUser( response, // response createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS), false, // expectActivityLaunch createAppBundle(), // appInfo UserHandle.USER_SYSTEM); waitForLatch(latch); // Verify notification is cancelled verify(mMockNotificationManager).cancelNotificationWithTag( anyString(), nullable(String.class), anyInt(), anyInt()); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE); assertNotNull(sessionBundle); // Assert that session bundle is decrypted and hence data is visible. assertEquals(AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1, sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1)); // Assert finishSessionAsUser added calling uid and pid into the sessionBundle assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_UID)); assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_PID)); assertEquals(sessionBundle.getString( AccountManager.KEY_ANDROID_PACKAGE_NAME), "APCT.package"); // Verify response data assertNull(result.getString(AccountManager.KEY_AUTHTOKEN, null)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME, result.getString(AccountManager.KEY_ACCOUNT_NAME)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE)); } @SmallTest public void testFinishSessionAsUserReturnWithInvalidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.finishSessionAsUser( response, // response createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE), true, // expectActivityLaunch createAppBundle(), // appInfo UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString()); } @SmallTest public void testFinishSessionAsUserReturnWithValidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.finishSessionAsUser( response, // response createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE), true, // expectActivityLaunch createAppBundle(), // appInfo UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Intent intent = result.getParcelable(AccountManager.KEY_INTENT); assertNotNull(intent); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT)); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK)); } @SmallTest public void testFinishSessionAsUserError() throws Exception { unlockSystemUser(); Bundle sessionBundle = createEncryptedSessionBundleWithError( AccountManagerServiceTestFixtures.ACCOUNT_NAME_ERROR); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.finishSessionAsUser( response, // response sessionBundle, false, // expectActivityLaunch createAppBundle(), // appInfo UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testIsCredentialsUpdatedSuggestedWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.isCredentialsUpdateSuggested( null, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testIsCredentialsUpdatedSuggestedWithNullAccount() throws Exception { unlockSystemUser(); try { mAms.isCredentialsUpdateSuggested( mMockAccountManagerResponse, null, // account AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testIsCredentialsUpdatedSuggestedWithEmptyStatusToken() throws Exception { unlockSystemUser(); try { mAms.isCredentialsUpdateSuggested( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, null); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testIsCredentialsUpdatedSuggestedError() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.isCredentialsUpdateSuggested( response, AccountManagerServiceTestFixtures.ACCOUNT_ERROR, AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN); waitForLatch(latch); verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testIsCredentialsUpdatedSuggestedSuccess() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.isCredentialsUpdateSuggested( response, AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); boolean needUpdate = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); assertTrue(needUpdate); } @SmallTest public void testHasFeaturesWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.hasFeatures( null, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, new String[] {"feature1", "feature2"}, // features "testPackage"); // opPackageName fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testHasFeaturesWithNullAccount() throws Exception { unlockSystemUser(); try { mAms.hasFeatures( mMockAccountManagerResponse, // response null, // account new String[] {"feature1", "feature2"}, // features "testPackage"); // opPackageName fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testHasFeaturesWithNullFeature() throws Exception { unlockSystemUser(); try { mAms.hasFeatures( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, // account null, // features "testPackage"); // opPackageName fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testHasFeaturesReturnNullResult() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.hasFeatures( response, // response AccountManagerServiceTestFixtures.ACCOUNT_ERROR, // account AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, // features "testPackage"); // opPackageName waitForLatch(latch); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString()); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testHasFeaturesSuccess() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.hasFeatures( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, // account AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, // features "testPackage"); // opPackageName waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); boolean hasFeatures = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); assertTrue(hasFeatures); } @SmallTest public void testRemoveAccountAsUserWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.removeAccountAsUser( null, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, true, // expectActivityLaunch UserHandle.USER_SYSTEM); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testRemoveAccountAsUserWithNullAccount() throws Exception { unlockSystemUser(); try { mAms.removeAccountAsUser( mMockAccountManagerResponse, // response null, // account true, // expectActivityLaunch UserHandle.USER_SYSTEM); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testRemoveAccountAsUserAccountNotManagedByCaller() throws Exception { unlockSystemUser(); when(mMockPackageManager.checkSignatures(anyInt(), anyInt())) .thenReturn(PackageManager.SIGNATURE_NO_MATCH); try { mAms.removeAccountAsUser( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, true, // expectActivityLaunch UserHandle.USER_SYSTEM); fail("SecurityException expected. But no exception was thrown."); } catch (SecurityException e) { // SecurityException is expected. } } @SmallTest public void testRemoveAccountAsUserUserCannotModifyAccount() throws Exception { unlockSystemUser(); Bundle bundle = new Bundle(); bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true); when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.removeAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString()); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testRemoveAccountAsUserUserCannotModifyAccountType() throws Exception { unlockSystemUser(); when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( mMockDevicePolicyManager); when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt())) .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"}); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.removeAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString()); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testRemoveAccountAsUserRemovalAllowed() throws Exception { String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p1", null); Account[] addedAccounts = mAms.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName()); assertEquals(1, addedAccounts.length); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.removeAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); boolean allowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); assertTrue(allowed); Account[] accounts = mAms.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName()); assertEquals(0, accounts.length); } @SmallTest public void testRemoveAccountAsUserRemovalNotAllowed() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.removeAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_ERROR, true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); boolean allowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); assertFalse(allowed); } @SmallTest public void testRemoveAccountAsUserReturnWithValidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.removeAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Intent intent = result.getParcelable(AccountManager.KEY_INTENT); assertNotNull(intent); } @SmallTest public void testGetAccountsByTypeForPackageWhenTypeIsNull() throws Exception { unlockSystemUser(); HashMap visibility1 = new HashMap<>(); visibility1.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE, AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); HashMap visibility2 = new HashMap<>(); visibility2.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE, AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE); mAms.addAccountExplicitlyWithVisibility( AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "P11", null, visibility1); mAms.addAccountExplicitlyWithVisibility( AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "P12", null, visibility2); Account[] accounts = mAms.getAccountsByTypeForPackage( null, "otherPackageName", AccountManagerServiceTestFixtures.CALLER_PACKAGE); // Only get the USER_MANAGED_NOT_VISIBLE account. assertEquals(1, accounts.length); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accounts[0].name); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accounts[0].type); } @SmallTest public void testGetAuthTokenLabelWithNullAccountType() throws Exception { unlockSystemUser(); try { mAms.getAuthTokenLabel( mMockAccountManagerResponse, // response null, // accountType "authTokenType"); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testGetAuthTokenLabelWithNullAuthTokenType() throws Exception { unlockSystemUser(); try { mAms.getAuthTokenLabel( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType null); // authTokenType fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testGetAuthTokenWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.getAuthToken( null, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", // authTokenType true, // notifyOnAuthFailure true, // expectActivityLaunch createGetAuthTokenOptions()); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testGetAuthTokenWithNullAccount() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAuthToken( response, // response null, // account "authTokenType", // authTokenType true, // notifyOnAuthFailure true, // expectActivityLaunch createGetAuthTokenOptions()); waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_BAD_ARGUMENTS), anyString()); } @SmallTest public void testGetAuthTokenWithNullAuthTokenType() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAuthToken( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, null, // authTokenType true, // notifyOnAuthFailure true, // expectActivityLaunch createGetAuthTokenOptions()); waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_BAD_ARGUMENTS), anyString()); } @SmallTest public void testGetAuthTokenWithInvalidPackage() throws Exception { unlockSystemUser(); String[] list = new String[]{"test"}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); try { mAms.getAuthToken( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", // authTokenType true, // notifyOnAuthFailure true, // expectActivityLaunch createGetAuthTokenOptions()); fail("SecurityException expected. But no exception was thrown."); } catch (SecurityException e) { // SecurityException is expected. } } @SmallTest public void testGetAuthTokenFromInternal() throws Exception { unlockSystemUser(); when(mMockContext.createPackageContextAsUser( anyString(), anyInt(), any(UserHandle.class))).thenReturn(mMockContext); when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.setAuthToken(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", AccountManagerServiceTestFixtures.AUTH_TOKEN); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAuthToken( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", // authTokenType true, // notifyOnAuthFailure true, // expectActivityLaunch createGetAuthTokenOptions()); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); assertEquals(result.getString(AccountManager.KEY_AUTHTOKEN), AccountManagerServiceTestFixtures.AUTH_TOKEN); assertEquals(result.getString(AccountManager.KEY_ACCOUNT_NAME), AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS); assertEquals(result.getString(AccountManager.KEY_ACCOUNT_TYPE), AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); } @SmallTest public void testGetAuthTokenSuccess() throws Exception { unlockSystemUser(); when(mMockContext.createPackageContextAsUser( anyString(), anyInt(), any(UserHandle.class))).thenReturn(mMockContext); when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAuthToken( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", // authTokenType true, // notifyOnAuthFailure false, // expectActivityLaunch createGetAuthTokenOptions()); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); assertEquals(result.getString(AccountManager.KEY_AUTHTOKEN), AccountManagerServiceTestFixtures.AUTH_TOKEN); assertEquals(result.getString(AccountManager.KEY_ACCOUNT_NAME), AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS); assertEquals(result.getString(AccountManager.KEY_ACCOUNT_TYPE), AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); } @SmallTest public void testGetAuthTokenReturnWithInvalidIntent() throws Exception { unlockSystemUser(); when(mMockContext.createPackageContextAsUser( anyString(), anyInt(), any(UserHandle.class))).thenReturn(mMockContext); when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAuthToken( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "authTokenType", // authTokenType true, // notifyOnAuthFailure false, // expectActivityLaunch createGetAuthTokenOptions()); waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString()); } @SmallTest public void testGetAuthTokenReturnWithValidIntent() throws Exception { unlockSystemUser(); when(mMockContext.createPackageContextAsUser( anyString(), anyInt(), any(UserHandle.class))).thenReturn(mMockContext); when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAuthToken( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "authTokenType", // authTokenType false, // notifyOnAuthFailure true, // expectActivityLaunch createGetAuthTokenOptions()); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Intent intent = result.getParcelable(AccountManager.KEY_INTENT); assertNotNull(intent); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT)); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK)); } @SmallTest public void testGetAuthTokenError() throws Exception { unlockSystemUser(); when(mMockContext.createPackageContextAsUser( anyString(), anyInt(), any(UserHandle.class))).thenReturn(mMockContext); when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAuthToken( response, // response AccountManagerServiceTestFixtures.ACCOUNT_ERROR, "authTokenType", // authTokenType true, // notifyOnAuthFailure false, // expectActivityLaunch createGetAuthTokenOptions()); waitForLatch(latch); verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testAddAccountAsUserWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.addAccountAsUser( null, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null, // optionsIn UserHandle.USER_SYSTEM); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testAddAccountAsUserWithNullAccountType() throws Exception { unlockSystemUser(); try { mAms.addAccountAsUser( mMockAccountManagerResponse, // response null, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null, // optionsIn UserHandle.USER_SYSTEM); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testAddAccountAsUserUserCannotModifyAccountNoDPM() throws Exception { unlockSystemUser(); Bundle bundle = new Bundle(); bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true); when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); mAms.addAccountAsUser( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null, // optionsIn UserHandle.USER_SYSTEM); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString()); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM)); // verify the intent for default CantAddAccountActivity is sent. Intent intent = mIntentCaptor.getValue(); assertEquals(intent.getComponent().getClassName(), CantAddAccountActivity.class.getName()); assertEquals(intent.getIntExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, 0), AccountManager.ERROR_CODE_USER_RESTRICTED); } @SmallTest public void testAddAccountAsUserUserCannotModifyAccountWithDPM() throws Exception { unlockSystemUser(); Bundle bundle = new Bundle(); bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true); when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); LocalServices.addService( DevicePolicyManagerInternal.class, mMockDevicePolicyManagerInternal); when(mMockDevicePolicyManagerInternal.createUserRestrictionSupportIntent( anyInt(), anyString())).thenReturn(new Intent()); when(mMockDevicePolicyManagerInternal.createShowAdminSupportIntent( anyInt(), anyBoolean())).thenReturn(new Intent()); mAms.addAccountAsUser( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null, // optionsIn UserHandle.USER_SYSTEM); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString()); verify(mMockContext).startActivityAsUser(any(Intent.class), eq(UserHandle.SYSTEM)); verify(mMockDevicePolicyManagerInternal).createUserRestrictionSupportIntent( anyInt(), anyString()); } @SmallTest public void testAddAccountAsUserUserCannotModifyAccountForTypeNoDPM() throws Exception { unlockSystemUser(); when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt())) .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"}); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); mAms.addAccountAsUser( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null, // optionsIn UserHandle.USER_SYSTEM); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString()); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM)); // verify the intent for default CantAddAccountActivity is sent. Intent intent = mIntentCaptor.getValue(); assertEquals(intent.getComponent().getClassName(), CantAddAccountActivity.class.getName()); assertEquals(intent.getIntExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, 0), AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE); } @SmallTest public void testAddAccountAsUserUserCannotModifyAccountForTypeWithDPM() throws Exception { unlockSystemUser(); when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( mMockDevicePolicyManager); when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt())) .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"}); LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); LocalServices.addService( DevicePolicyManagerInternal.class, mMockDevicePolicyManagerInternal); when(mMockDevicePolicyManagerInternal.createUserRestrictionSupportIntent( anyInt(), anyString())).thenReturn(new Intent()); when(mMockDevicePolicyManagerInternal.createShowAdminSupportIntent( anyInt(), anyBoolean())).thenReturn(new Intent()); mAms.addAccountAsUser( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch null, // optionsIn UserHandle.USER_SYSTEM); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString()); verify(mMockContext).startActivityAsUser(any(Intent.class), eq(UserHandle.SYSTEM)); verify(mMockDevicePolicyManagerInternal).createShowAdminSupportIntent( anyInt(), anyBoolean()); } @SmallTest public void testAddAccountAsUserSuccess() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.addAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch createAddAccountOptions(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS), UserHandle.USER_SYSTEM); waitForLatch(latch); // Verify notification is cancelled verify(mMockNotificationManager).cancelNotificationWithTag( anyString(), nullable(String.class), anyInt(), anyInt()); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); // Verify response data assertNull(result.getString(AccountManager.KEY_AUTHTOKEN, null)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, result.getString(AccountManager.KEY_ACCOUNT_NAME)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE)); Bundle optionBundle = result.getParcelable( AccountManagerServiceTestFixtures.KEY_OPTIONS_BUNDLE); // Assert addAccountAsUser added calling uid and pid into the option bundle assertTrue(optionBundle.containsKey(AccountManager.KEY_CALLER_UID)); assertTrue(optionBundle.containsKey(AccountManager.KEY_CALLER_PID)); } @SmallTest public void testAddAccountAsUserReturnWithInvalidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.addAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch createAddAccountOptions(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE), UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString()); } @SmallTest public void testAddAccountAsUserReturnWithValidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.addAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch createAddAccountOptions(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE), UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Intent intent = result.getParcelable(AccountManager.KEY_INTENT); assertNotNull(intent); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT)); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK)); } @SmallTest public void testAddAccountAsUserError() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.addAccountAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType "authTokenType", null, // requiredFeatures true, // expectActivityLaunch createAddAccountOptions(AccountManagerServiceTestFixtures.ACCOUNT_NAME_ERROR), UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testConfirmCredentialsAsUserWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.confirmCredentialsAsUser( null, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, new Bundle(), // options false, // expectActivityLaunch UserHandle.USER_SYSTEM); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testConfirmCredentialsAsUserWithNullAccount() throws Exception { unlockSystemUser(); try { mAms.confirmCredentialsAsUser( mMockAccountManagerResponse, // response null, // account new Bundle(), // options false, // expectActivityLaunch UserHandle.USER_SYSTEM); fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testConfirmCredentialsAsUserSuccess() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.confirmCredentialsAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, new Bundle(), // options true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); // Verify response data assertTrue(result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, result.getString(AccountManager.KEY_ACCOUNT_NAME)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE)); } @SmallTest public void testConfirmCredentialsAsUserReturnWithInvalidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.confirmCredentialsAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, new Bundle(), // options true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString()); } @SmallTest public void testConfirmCredentialsAsUserReturnWithValidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.confirmCredentialsAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, new Bundle(), // options true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Intent intent = result.getParcelable(AccountManager.KEY_INTENT); assertNotNull(intent); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT)); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK)); } @SmallTest public void testConfirmCredentialsAsUserError() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.confirmCredentialsAsUser( response, // response AccountManagerServiceTestFixtures.ACCOUNT_ERROR, new Bundle(), // options true, // expectActivityLaunch UserHandle.USER_SYSTEM); waitForLatch(latch); verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testUpdateCredentialsWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.updateCredentials( null, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", false, // expectActivityLaunch new Bundle()); // options fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testUpdateCredentialsWithNullAccount() throws Exception { unlockSystemUser(); try { mAms.updateCredentials( mMockAccountManagerResponse, // response null, // account "authTokenType", false, // expectActivityLaunch new Bundle()); // options fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testUpdateCredentialsSuccess() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.updateCredentials( response, // response AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "authTokenType", false, // expectActivityLaunch new Bundle()); // options waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); // Verify response data assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, result.getString(AccountManager.KEY_ACCOUNT_NAME)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE)); } @SmallTest public void testUpdateCredentialsReturnWithInvalidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.updateCredentials( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "authTokenType", true, // expectActivityLaunch new Bundle()); // options waitForLatch(latch); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString()); } @SmallTest public void testUpdateCredentialsReturnWithValidIntent() throws Exception { unlockSystemUser(); ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); when(mMockPackageManager.resolveActivityAsUser( any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo); when(mMockPackageManager.checkSignatures( anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.updateCredentials( response, // response AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "authTokenType", true, // expectActivityLaunch new Bundle()); // options waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Intent intent = result.getParcelable(AccountManager.KEY_INTENT); assertNotNull(intent); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT)); assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK)); } @SmallTest public void testUpdateCredentialsError() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.updateCredentials( response, // response AccountManagerServiceTestFixtures.ACCOUNT_ERROR, "authTokenType", false, // expectActivityLaunch new Bundle()); // options waitForLatch(latch); verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testEditPropertiesWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.editProperties( null, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, false); // expectActivityLaunch fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testEditPropertiesWithNullAccountType() throws Exception { unlockSystemUser(); try { mAms.editProperties( mMockAccountManagerResponse, // response null, // accountType false); // expectActivityLaunch fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testEditPropertiesAccountNotManagedByCaller() throws Exception { unlockSystemUser(); when(mMockPackageManager.checkSignatures(anyInt(), anyInt())) .thenReturn(PackageManager.SIGNATURE_NO_MATCH); try { mAms.editProperties( mMockAccountManagerResponse, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, false); // expectActivityLaunch fail("SecurityException expected. But no exception was thrown."); } catch (SecurityException e) { // SecurityException is expected. } } @SmallTest public void testEditPropertiesSuccess() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.editProperties( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, false); // expectActivityLaunch waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); // Verify response data assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, result.getString(AccountManager.KEY_ACCOUNT_NAME)); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE)); } @SmallTest public void testGetAccountByTypeAndFeaturesWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.getAccountByTypeAndFeatures( null, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); // opPackageName fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testGetAccountByTypeAndFeaturesWithNullAccountType() throws Exception { unlockSystemUser(); try { mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, // response null, // accountType AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); // opPackageName fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndNoAccount() throws Exception { unlockSystemUser(); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, null, "testpackage"); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME); String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE); assertEquals(null, accountName); assertEquals(null, accountType); } @SmallTest public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndOneVisibleAccount() throws Exception { unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, null, "testpackage"); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME); String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accountName); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accountType); } @SmallTest public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndOneNotVisibleAccount() throws Exception { unlockSystemUser(); HashMap visibility = new HashMap<>(); visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE, AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE); mAms.addAccountExplicitlyWithVisibility( AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, null, AccountManagerServiceTestFixtures.CALLER_PACKAGE); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM)); Intent intent = mIntentCaptor.getValue(); Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS); assertEquals(1, accounts.length); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]); } @SmallTest public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndTwoAccounts() throws Exception { unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, null, "testpackage"); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM)); Intent intent = mIntentCaptor.getValue(); Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS); assertEquals(2, accounts.length); if (accounts[0].equals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS)) { assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[1]); } else { assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[0]); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]); } } @SmallTest public void testGetAccountByTypeAndFeaturesWithFeaturesAndNoAccount() throws Exception { unlockSystemUser(); final CountDownLatch latch = new CountDownLatch(1); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME); String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE); assertEquals(null, accountName); assertEquals(null, accountType); } @SmallTest public void testGetAccountByTypeAndFeaturesWithFeaturesAndNoQualifiedAccount() throws Exception { unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null); final CountDownLatch latch = new CountDownLatch(1); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME); String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE); assertEquals(null, accountName); assertEquals(null, accountType); } @SmallTest public void testGetAccountByTypeAndFeaturesWithFeaturesAndOneQualifiedAccount() throws Exception { unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null); final CountDownLatch latch = new CountDownLatch(1); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME); String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accountName); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accountType); } @SmallTest public void testGetAccountByTypeAndFeaturesWithFeaturesAndOneQualifiedNotVisibleAccount() throws Exception { unlockSystemUser(); HashMap visibility = new HashMap<>(); visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE, AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE); mAms.addAccountExplicitlyWithVisibility( AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility); final CountDownLatch latch = new CountDownLatch(1); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, AccountManagerServiceTestFixtures.CALLER_PACKAGE); waitForLatch(latch); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM)); Intent intent = mIntentCaptor.getValue(); Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS); assertEquals(1, accounts.length); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]); } @SmallTest public void testGetAccountByTypeAndFeaturesWithFeaturesAndTwoQualifiedAccount() throws Exception { unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, "p12", null); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p13", null); final CountDownLatch latch = new CountDownLatch(1); mAms.getAccountByTypeAndFeatures( mMockAccountManagerResponse, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); waitForLatch(latch); verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM)); Intent intent = mIntentCaptor.getValue(); Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS); assertEquals(2, accounts.length); if (accounts[0].equals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS)) { assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, accounts[1]); } else { assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, accounts[0]); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]); } } @SmallTest public void testGetAccountsByFeaturesWithNullResponse() throws Exception { unlockSystemUser(); try { mAms.getAccountsByFeatures( null, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); // opPackageName fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testGetAccountsByFeaturesWithNullAccountType() throws Exception { unlockSystemUser(); try { mAms.getAccountsByFeatures( mMockAccountManagerResponse, // response null, // accountType AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); // opPackageName fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } @SmallTest public void testGetAccountsByFeaturesAccountNotVisible() throws Exception { unlockSystemUser(); when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_DENIED); when(mMockPackageManager.checkSignatures(anyInt(), anyInt())) .thenReturn(PackageManager.SIGNATURE_NO_MATCH); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAccountsByFeatures( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); // opPackageName waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Account[] accounts = (Account[]) result.getParcelableArray(AccountManager.KEY_ACCOUNTS); assertTrue(accounts.length == 0); } @SmallTest public void testGetAccountsByFeaturesNullFeatureReturnsAllAccounts() throws Exception { unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAccountsByFeatures( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType null, // features "testpackage"); // opPackageName waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Account[] accounts = (Account[]) result.getParcelableArray(AccountManager.KEY_ACCOUNTS); Arrays.sort(accounts, new AccountSorter()); assertEquals(2, accounts.length); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[0]); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]); } @SmallTest public void testGetAccountsByFeaturesReturnsAccountsWithFeaturesOnly() throws Exception { unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAccountsByFeatures( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); // opPackageName waitForLatch(latch); verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture()); Bundle result = mBundleCaptor.getValue(); Account[] accounts = (Account[]) result.getParcelableArray(AccountManager.KEY_ACCOUNTS); assertEquals(1, accounts.length); assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]); } @SmallTest public void testGetAccountsByFeaturesError() throws Exception { unlockSystemUser(); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_ERROR, "p12", null); final CountDownLatch latch = new CountDownLatch(1); Response response = new Response(latch, mMockAccountManagerResponse); mAms.getAccountsByFeatures( response, // response AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, // accountType AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, "testpackage"); // opPackageName waitForLatch(latch); verify(mMockAccountManagerResponse).onError( eq(AccountManager.ERROR_CODE_INVALID_RESPONSE), anyString()); verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class)); } @SmallTest public void testRegisterAccountListener() throws Exception { unlockSystemUser(); mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage"); // opPackageName mAms.registerAccountListener( null, //accountTypes "testpackage"); // opPackageName // Check that two previously registered receivers can be unregistered successfully. mAms.unregisterAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage"); // opPackageName mAms.unregisterAccountListener( null, //accountTypes "testpackage"); // opPackageName } @SmallTest public void testRegisterAccountListenerAndAddAccount() throws Exception { unlockSystemUser(); mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage"); // opPackageName mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); // Notification about new account updateBroadcastCounters(2); assertEquals(mVisibleAccountsChangedBroadcasts, 1); assertEquals(mLoginAccountsChangedBroadcasts, 1); } @SmallTest public void testRegisterAccountListenerAndAddAccountOfDifferentType() throws Exception { unlockSystemUser(); mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2}, "testpackage"); // opPackageName mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.addAccountExplicitly( AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p11", null); // Notification about new account updateBroadcastCounters(2); assertEquals(mVisibleAccountsChangedBroadcasts, 0); // broadcast was not sent assertEquals(mLoginAccountsChangedBroadcasts, 2); } @SmallTest public void testRegisterAccountListenerWithAddingTwoAccounts() throws Exception { unlockSystemUser(); HashMap visibility = new HashMap<>(); visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE, AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, AccountManagerServiceTestFixtures.CALLER_PACKAGE); mAms.addAccountExplicitlyWithVisibility( AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility); mAms.unregisterAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, AccountManagerServiceTestFixtures.CALLER_PACKAGE); addAccountRemovedReceiver(AccountManagerServiceTestFixtures.CALLER_PACKAGE); mAms.addAccountExplicitlyWithVisibility( AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p11", null, visibility); updateBroadcastCounters(3); assertEquals(mVisibleAccountsChangedBroadcasts, 1); assertEquals(mLoginAccountsChangedBroadcasts, 2); assertEquals(mAccountRemovedBroadcasts, 0); mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS); mAms.registerAccountListener( null /* accountTypes */, AccountManagerServiceTestFixtures.CALLER_PACKAGE); mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE); updateBroadcastCounters(8); assertEquals(mVisibleAccountsChangedBroadcasts, 2); assertEquals(mLoginAccountsChangedBroadcasts, 4); assertEquals(mAccountRemovedBroadcasts, 2); } @SmallTest public void testRegisterAccountListenerForThreePackages() throws Exception { unlockSystemUser(); addAccountRemovedReceiver("testpackage1"); HashMap visibility = new HashMap<>(); visibility.put("testpackage1", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); visibility.put("testpackage2", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); visibility.put("testpackage3", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage1"); // opPackageName mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage2"); // opPackageName mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage3"); // opPackageName mAms.addAccountExplicitlyWithVisibility( AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility); updateBroadcastCounters(4); assertEquals(mVisibleAccountsChangedBroadcasts, 3); assertEquals(mLoginAccountsChangedBroadcasts, 1); mAms.unregisterAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage3"); // opPackageName // Remove account with 2 active listeners. mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS); updateBroadcastCounters(8); assertEquals(mVisibleAccountsChangedBroadcasts, 5); assertEquals(mLoginAccountsChangedBroadcasts, 2); // 3 add, 2 remove assertEquals(mAccountRemovedBroadcasts, 1); // Add account of another type. mAms.addAccountExplicitly( AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_TYPE_2, "p11", null); updateBroadcastCounters(8); assertEquals(mVisibleAccountsChangedBroadcasts, 5); assertEquals(mLoginAccountsChangedBroadcasts, 3); assertEquals(mAccountRemovedBroadcasts, 1); } @SmallTest public void testRegisterAccountListenerForAddingAccountWithVisibility() throws Exception { unlockSystemUser(); HashMap visibility = new HashMap<>(); visibility.put("testpackage1", AccountManager.VISIBILITY_NOT_VISIBLE); visibility.put("testpackage2", AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE); visibility.put("testpackage3", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); addAccountRemovedReceiver("testpackage1"); mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage1"); // opPackageName mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage2"); // opPackageName mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage3"); // opPackageName mAms.addAccountExplicitlyWithVisibility( AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility); updateBroadcastCounters(2); assertEquals(mVisibleAccountsChangedBroadcasts, 1); assertEquals(mLoginAccountsChangedBroadcasts, 1); mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS); updateBroadcastCounters(4); assertEquals(mVisibleAccountsChangedBroadcasts, 2); assertEquals(mLoginAccountsChangedBroadcasts, 2); assertEquals(mAccountRemovedBroadcasts, 0); // account was never visible. } @SmallTest public void testRegisterAccountListenerCredentialsUpdate() throws Exception { unlockSystemUser(); mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage"); // opPackageName mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.setPassword(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "pwd"); updateBroadcastCounters(4); assertEquals(mVisibleAccountsChangedBroadcasts, 2); assertEquals(mLoginAccountsChangedBroadcasts, 2); } @SmallTest public void testUnregisterAccountListenerNotRegistered() throws Exception { unlockSystemUser(); try { mAms.unregisterAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage"); // opPackageName fail("IllegalArgumentException expected. But no exception was thrown."); } catch (IllegalArgumentException e) { // IllegalArgumentException is expected. } } private void updateBroadcastCounters (int expectedBroadcasts){ mVisibleAccountsChangedBroadcasts = 0; mLoginAccountsChangedBroadcasts = 0; mAccountRemovedBroadcasts = 0; ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); verify(mMockContext, atLeast(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(), any(UserHandle.class)); for (Intent intent : captor.getAllValues()) { if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) { mVisibleAccountsChangedBroadcasts++; } else if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) { mLoginAccountsChangedBroadcasts++; } else if (AccountManager.ACTION_ACCOUNT_REMOVED.equals(intent.getAction())) { mAccountRemovedBroadcasts++; } } } private void addAccountRemovedReceiver(String packageName) { ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.activityInfo = new ActivityInfo(); resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); resolveInfo.activityInfo.applicationInfo.packageName = packageName; List accountRemovedReceivers = new ArrayList<>(); accountRemovedReceivers.add(resolveInfo); when(mMockPackageManager.queryBroadcastReceiversAsUser(any(Intent.class), anyInt(), anyInt())).thenReturn(accountRemovedReceivers); } @SmallTest public void testConcurrencyReadWrite() throws Exception { // Test 2 threads calling getAccounts and 1 thread setAuthToken unlockSystemUser(); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); Account a1 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); mAms.addAccountExplicitly(a1, "p1", null); List errors = Collections.synchronizedList(new ArrayList<>()); int readerCount = 2; ExecutorService es = Executors.newFixedThreadPool(readerCount + 1); AtomicLong readTotalTime = new AtomicLong(0); AtomicLong writeTotalTime = new AtomicLong(0); final CyclicBarrier cyclicBarrier = new CyclicBarrier(readerCount + 1); final int loopSize = 20; for (int t = 0; t < readerCount; t++) { es.submit(() -> { for (int i = 0; i < loopSize; i++) { String logPrefix = Thread.currentThread().getName() + " " + i; waitForCyclicBarrier(cyclicBarrier); cyclicBarrier.reset(); SystemClock.sleep(1); // Ensure that writer wins Log.d(TAG, logPrefix + " getAccounts started"); long ti = System.currentTimeMillis(); try { Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName()); if (accounts == null || accounts.length != 1 || !AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1.equals( accounts[0].type)) { String msg = logPrefix + ": Unexpected accounts: " + Arrays .toString(accounts); Log.e(TAG, " " + msg); errors.add(msg); } Log.d(TAG, logPrefix + " getAccounts done"); } catch (Exception e) { String msg = logPrefix + ": getAccounts failed " + e; Log.e(TAG, msg, e); errors.add(msg); } ti = System.currentTimeMillis() - ti; readTotalTime.addAndGet(ti); } }); } es.submit(() -> { for (int i = 0; i < loopSize; i++) { String logPrefix = Thread.currentThread().getName() + " " + i; waitForCyclicBarrier(cyclicBarrier); long ti = System.currentTimeMillis(); Log.d(TAG, logPrefix + " setAuthToken started"); try { mAms.setAuthToken(a1, "t1", "v" + i); Log.d(TAG, logPrefix + " setAuthToken done"); } catch (Exception e) { errors.add(logPrefix + ": setAuthToken failed: " + e); } ti = System.currentTimeMillis() - ti; writeTotalTime.addAndGet(ti); } }); es.shutdown(); assertTrue("Time-out waiting for jobs to finish", es.awaitTermination(10, TimeUnit.SECONDS)); es.shutdownNow(); assertTrue("Errors: " + errors, errors.isEmpty()); Log.i(TAG, "testConcurrencyReadWrite: readTotalTime=" + readTotalTime + " avg=" + (readTotalTime.doubleValue() / readerCount / loopSize)); Log.i(TAG, "testConcurrencyReadWrite: writeTotalTime=" + writeTotalTime + " avg=" + (writeTotalTime.doubleValue() / loopSize)); } @SmallTest public void testConcurrencyRead() throws Exception { // Test 2 threads calling getAccounts unlockSystemUser(); String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE}; when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list); Account a1 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); mAms.addAccountExplicitly(a1, "p1", null); List errors = Collections.synchronizedList(new ArrayList<>()); int readerCount = 2; ExecutorService es = Executors.newFixedThreadPool(readerCount + 1); AtomicLong readTotalTime = new AtomicLong(0); final int loopSize = 20; for (int t = 0; t < readerCount; t++) { es.submit(() -> { for (int i = 0; i < loopSize; i++) { String logPrefix = Thread.currentThread().getName() + " " + i; Log.d(TAG, logPrefix + " getAccounts started"); long ti = System.currentTimeMillis(); try { Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName()); if (accounts == null || accounts.length != 1 || !AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1.equals( accounts[0].type)) { String msg = logPrefix + ": Unexpected accounts: " + Arrays .toString(accounts); Log.e(TAG, " " + msg); errors.add(msg); } Log.d(TAG, logPrefix + " getAccounts done"); } catch (Exception e) { String msg = logPrefix + ": getAccounts failed " + e; Log.e(TAG, msg, e); errors.add(msg); } ti = System.currentTimeMillis() - ti; readTotalTime.addAndGet(ti); } }); } es.shutdown(); assertTrue("Time-out waiting for jobs to finish", es.awaitTermination(10, TimeUnit.SECONDS)); es.shutdownNow(); assertTrue("Errors: " + errors, errors.isEmpty()); Log.i(TAG, "testConcurrencyRead: readTotalTime=" + readTotalTime + " avg=" + (readTotalTime.doubleValue() / readerCount / loopSize)); } private void waitForCyclicBarrier(CyclicBarrier cyclicBarrier) { try { cyclicBarrier.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS); } catch (Exception e) { throw new IllegalStateException("Should not throw " + e, e); } } private void waitForLatch(CountDownLatch latch) { try { latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new IllegalStateException("Should not throw an InterruptedException", e); } } private Bundle createAddAccountOptions(String accountName) { Bundle options = new Bundle(); options.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME, accountName); return options; } private Bundle createGetAuthTokenOptions() { Bundle options = new Bundle(); options.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, AccountManagerServiceTestFixtures.CALLER_PACKAGE); options.putLong(AccountManagerServiceTestFixtures.KEY_TOKEN_EXPIRY, System.currentTimeMillis() + ONE_DAY_IN_MILLISECOND); return options; } private Bundle encryptBundleWithCryptoHelper(Bundle sessionBundle) { Bundle encryptedBundle = null; try { CryptoHelper cryptoHelper = CryptoHelper.getInstance(); encryptedBundle = cryptoHelper.encryptBundle(sessionBundle); } catch (GeneralSecurityException e) { throw new IllegalStateException("Failed to encrypt session bundle.", e); } return encryptedBundle; } private Bundle createEncryptedSessionBundle(final String accountName) { Bundle sessionBundle = new Bundle(); sessionBundle.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME, accountName); sessionBundle.putString( AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1, AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1); sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); sessionBundle.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, "APCT.session.package"); return encryptBundleWithCryptoHelper(sessionBundle); } private Bundle createEncryptedSessionBundleWithError(final String accountName) { Bundle sessionBundle = new Bundle(); sessionBundle.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME, accountName); sessionBundle.putString( AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1, AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1); sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); sessionBundle.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, "APCT.session.package"); sessionBundle.putInt( AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE); sessionBundle.putString(AccountManager.KEY_ERROR_MESSAGE, AccountManagerServiceTestFixtures.ERROR_MESSAGE); return encryptBundleWithCryptoHelper(sessionBundle); } private Bundle createEncryptedSessionBundleWithNoAccountType(final String accountName) { Bundle sessionBundle = new Bundle(); sessionBundle.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME, accountName); sessionBundle.putString( AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1, AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1); sessionBundle.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, "APCT.session.package"); return encryptBundleWithCryptoHelper(sessionBundle); } private Bundle createAppBundle() { Bundle appBundle = new Bundle(); appBundle.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, "APCT.package"); return appBundle; } private Bundle createOptionsWithAccountName(final String accountName) { Bundle sessionBundle = new Bundle(); sessionBundle.putString( AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1, AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1); sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); Bundle options = new Bundle(); options.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME, accountName); options.putBundle(AccountManagerServiceTestFixtures.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle); options.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_PASSWORD, AccountManagerServiceTestFixtures.ACCOUNT_PASSWORD); return options; } private int readNumberOfAccountsFromDbFile(Context context, String dbName) { SQLiteDatabase ceDb = context.openOrCreateDatabase(dbName, 0, null); try (Cursor cursor = ceDb.rawQuery("SELECT count(*) FROM accounts", null)) { assertTrue(cursor.moveToNext()); return cursor.getInt(0); } } private void unlockSystemUser() { mAms.onUserUnlocked(newIntentForUser(UserHandle.USER_SYSTEM)); } private static Intent newIntentForUser(int userId) { Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); return intent; } static class MyMockContext extends MockContext { private Context mTestContext; private Context mMockContext; MyMockContext(Context testContext, Context mockContext) { this.mTestContext = testContext; this.mMockContext = mockContext; } @Override public int checkCallingOrSelfPermission(final String permission) { return mMockContext.checkCallingOrSelfPermission(permission); } @Override public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags, UserHandle user) { return mTestContext.bindServiceAsUser(service, conn, flags, user); } @Override public void unbindService(ServiceConnection conn) { mTestContext.unbindService(conn); } @Override public PackageManager getPackageManager() { return mMockContext.getPackageManager(); } @Override public String getPackageName() { return mTestContext.getPackageName(); } @Override public Object getSystemService(String name) { return mMockContext.getSystemService(name); } @Override public String getSystemServiceName(Class serviceClass) { return mMockContext.getSystemServiceName(serviceClass); } @Override public void startActivityAsUser(Intent intent, UserHandle user) { mMockContext.startActivityAsUser(intent, user); } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return mMockContext.registerReceiver(receiver, filter); } @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { return mMockContext.registerReceiverAsUser( receiver, user, filter, broadcastPermission, scheduler); } @Override public SQLiteDatabase openOrCreateDatabase(String file, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) { return mTestContext.openOrCreateDatabase(file, mode, factory,errorHandler); } @Override public void sendBroadcastAsUser(Intent intent, UserHandle user) { mMockContext.sendBroadcastAsUser(intent, user); } @Override public String getOpPackageName() { return mMockContext.getOpPackageName(); } @Override public Context createPackageContextAsUser(String packageName, int flags, UserHandle user) throws PackageManager.NameNotFoundException { return mMockContext.createPackageContextAsUser(packageName, flags, user); } } static class TestAccountAuthenticatorCache extends AccountAuthenticatorCache { public TestAccountAuthenticatorCache(Context realContext) { super(realContext); } @Override protected File getUserSystemDirectory(int userId) { return new File(mContext.getCacheDir(), "authenticator"); } } static class TestInjector extends AccountManagerService.Injector { private Context mRealContext; private INotificationManager mMockNotificationManager; TestInjector(Context realContext, Context mockContext, INotificationManager mockNotificationManager) { super(mockContext); mRealContext = realContext; mMockNotificationManager = mockNotificationManager; } @Override Looper getMessageHandlerLooper() { return Looper.getMainLooper(); } @Override void addLocalService(AccountManagerInternal service) { } @Override IAccountAuthenticatorCache getAccountAuthenticatorCache() { return new TestAccountAuthenticatorCache(mRealContext); } @Override protected String getCeDatabaseName(int userId) { return new File(mRealContext.getCacheDir(), CE_DB).getPath(); } @Override protected String getDeDatabaseName(int userId) { return new File(mRealContext.getCacheDir(), DE_DB).getPath(); } @Override String getPreNDatabaseName(int userId) { return new File(mRealContext.getCacheDir(), PREN_DB).getPath(); } @Override INotificationManager getNotificationManager() { return mMockNotificationManager; } } class Response extends IAccountManagerResponse.Stub { private CountDownLatch mLatch; private IAccountManagerResponse mMockResponse; public Response(CountDownLatch latch, IAccountManagerResponse mockResponse) { mLatch = latch; mMockResponse = mockResponse; } @Override public void onResult(Bundle bundle) { try { mMockResponse.onResult(bundle); } catch (RemoteException e) { } mLatch.countDown(); } @Override public void onError(int code, String message) { try { mMockResponse.onError(code, message); } catch (RemoteException e) { } mLatch.countDown(); } } }