From 81c4c8af206624f902efbd913fc3b26bb6842307 Mon Sep 17 00:00:00 2001 From: Hongming Jin Date: Tue, 10 Jan 2017 13:31:36 -0800 Subject: [PATCH] Test: AccountManagerService APCT test. Setup test authenticators, add tests for startAddAccountSession. Bug: 31346530 Change-Id: I0fb460a8a1c35e2c88c624d0e291b20051110b34 --- .../tests/servicestests/AndroidManifest.xml | 23 +- .../servicestests/res/values/strings.xml | 4 + .../xml/test_account_type1_authenticator.xml | 21 + .../xml/test_account_type2_authenticator.xml | 21 + .../AccountAuthenticatorDummyActivity.java | 42 ++ .../accounts/AccountManagerServiceTest.java | 563 +++++++++++++++--- .../AccountManagerServiceTestFixtures.java | 70 +++ .../accounts/PreNTestDatabaseHelper.java | 2 +- .../TestAccountType1Authenticator.java | 312 ++++++++++ .../TestAccountType1AuthenticatorService.java | 33 + .../TestAccountType2Authenticator.java | 147 +++++ .../TestAccountType2AuthenticatorService.java | 33 + 12 files changed, 1174 insertions(+), 97 deletions(-) create mode 100644 services/tests/servicestests/res/xml/test_account_type1_authenticator.xml create mode 100644 services/tests/servicestests/res/xml/test_account_type2_authenticator.xml create mode 100644 services/tests/servicestests/src/com/android/server/accounts/AccountAuthenticatorDummyActivity.java create mode 100644 services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java create mode 100644 services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java create mode 100644 services/tests/servicestests/src/com/android/server/accounts/TestAccountType1AuthenticatorService.java create mode 100644 services/tests/servicestests/src/com/android/server/accounts/TestAccountType2Authenticator.java create mode 100644 services/tests/servicestests/src/com/android/server/accounts/TestAccountType2AuthenticatorService.java diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 1393615b5623b..375e4fae06979 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -18,6 +18,7 @@ package="com.android.frameworks.servicestests"> + @@ -65,6 +66,24 @@ + + + + + + + + + + + + + + + android:enabled="true" android:exported="true" /> + + + AccountManagerService Test Account Type1 + AccountManagerService Test Account Type2 + com.android.server.accounts.account_manager_service_test.account.type1 + com.android.server.accounts.account_manager_service_test.account.type2 diff --git a/services/tests/servicestests/res/xml/test_account_type1_authenticator.xml b/services/tests/servicestests/res/xml/test_account_type1_authenticator.xml new file mode 100644 index 0000000000000..0c531de1827e8 --- /dev/null +++ b/services/tests/servicestests/res/xml/test_account_type1_authenticator.xml @@ -0,0 +1,21 @@ + + + + diff --git a/services/tests/servicestests/res/xml/test_account_type2_authenticator.xml b/services/tests/servicestests/res/xml/test_account_type2_authenticator.xml new file mode 100644 index 0000000000000..f88eeb94d41cf --- /dev/null +++ b/services/tests/servicestests/res/xml/test_account_type2_authenticator.xml @@ -0,0 +1,21 @@ + + + + diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountAuthenticatorDummyActivity.java b/services/tests/servicestests/src/com/android/server/accounts/AccountAuthenticatorDummyActivity.java new file mode 100644 index 0000000000000..8a14e1be0ce84 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accounts/AccountAuthenticatorDummyActivity.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.accounts; + +import android.accounts.AccountAuthenticatorResponse; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +/** + * Activity used by {@link com.android.server.accounts.TestAccountAuthenticator} to test the + * behavior of {@link AccountManagerService} when authenticator returns intent. + */ +public class AccountAuthenticatorDummyActivity extends Activity { + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + Intent intent = getIntent(); + AccountAuthenticatorResponse response = + intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK); + Intent result = intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT); + if (response != null) { + response.onResult(result.getExtras()); + } + setResult(RESULT_OK, result); + finish(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java index c74cda66abdcc..ee49a00c7f40e 100644 --- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java @@ -17,30 +17,47 @@ 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.mock; +import static org.mockito.Mockito.never; +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.AuthenticatorDescription; +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.PackageManager; -import android.content.pm.RegisteredServicesCache.ServiceInfo; import android.content.pm.RegisteredServicesCacheListener; +import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; +import android.content.pm.RegisteredServicesCache.ServiceInfo; 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.UserHandle; import android.os.UserManager; import android.test.AndroidTestCase; @@ -48,6 +65,14 @@ 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.io.FileDescriptor; import java.io.PrintWriter; @@ -61,6 +86,19 @@ import java.util.concurrent.TimeUnit; public class AccountManagerServiceTest extends AndroidTestCase { private static final String TAG = AccountManagerServiceTest.class.getSimpleName(); + @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; + + @Captor private ArgumentCaptor mIntentCaptor; + @Captor private ArgumentCaptor mBundleCaptor; + + 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"; @@ -69,8 +107,27 @@ public class AccountManagerServiceTest extends AndroidTestCase { @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.getPackageManager()).thenReturn(mMockPackageManager); + 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); + MyMockContext mockContext = new MyMockContext(realTestContext, mMockContext); setContext(mockContext); mTestInjector = new TestInjector(realTestContext, mockContext); mAms = new AccountManagerService(mTestInjector); @@ -104,12 +161,12 @@ public class AccountManagerServiceTest extends AndroidTestCase { @SmallTest public void testCheckAddAccount() throws Exception { unlockSystemUser(); - Account a11 = new Account("account1", "type1"); - Account a21 = new Account("account2", "type1"); - Account a31 = new Account("account3", "type1"); - Account a12 = new Account("account1", "type2"); - Account a22 = new Account("account2", "type2"); - Account a32 = new Account("account3", "type2"); + 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); @@ -127,7 +184,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { assertEquals(a22, accounts[4]); assertEquals(a32, accounts[5]); - accounts = mAms.getAccounts("type1", mContext.getOpPackageName()); + accounts = mAms.getAccounts(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, + mContext.getOpPackageName()); Arrays.sort(accounts, new AccountSorter()); assertEquals(3, accounts.length); assertEquals(a11, accounts[0]); @@ -136,7 +194,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { mAms.removeAccountInternal(a21); - accounts = mAms.getAccounts("type1", mContext.getOpPackageName()); + accounts = mAms.getAccounts(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, + mContext.getOpPackageName()); Arrays.sort(accounts, new AccountSorter()); assertEquals(2, accounts.length); assertEquals(a11, accounts[0]); @@ -146,8 +205,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { @SmallTest public void testPasswords() throws Exception { unlockSystemUser(); - Account a11 = new Account("account1", "type1"); - Account a12 = new Account("account1", "type2"); + 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); @@ -163,12 +222,12 @@ public class AccountManagerServiceTest extends AndroidTestCase { @SmallTest public void testUserdata() throws Exception { unlockSystemUser(); - Account a11 = new Account("account1", "type1"); + 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", "type2"); + Account a12 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); Bundle u12 = new Bundle(); u12.putString("a", "a_a12"); u12.putString("b", "b_a12"); @@ -197,8 +256,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { @SmallTest public void testAuthtokens() throws Exception { unlockSystemUser(); - Account a11 = new Account("account1", "type1"); - Account a12 = new Account("account1", "type2"); + 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); @@ -232,8 +291,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { @SmallTest public void testRemovedAccountSync() throws Exception { unlockSystemUser(); - Account a1 = new Account("account1", "type1"); - Account a2 = new Account("account2", "type2"); + 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); @@ -292,6 +351,329 @@ public class AccountManagerServiceTest extends AndroidTestCase { 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) { + } catch(Exception e){ + fail(String.format("Expect IllegalArgumentException, but got %s.", e)); + } + } + + @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) { + } catch(Exception e){ + fail(String.format("Expect IllegalArgumentException, but got %s.", e)); + } + } + + @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 testStartAddAccountSessionUserSuccessWithoutPasswordForwarding() 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 testStartAddAccountSessionUserSuccessWithPasswordForwarding() 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 testStartAddAccountSessionUserReturnWithInvalidIntent() 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 testStartAddAccountSessionUserReturnWithValidIntent() 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 testStartAddAccountSessionUserError() 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)); + } + + private void waitForLatch(CountDownLatch latch) { + try { + latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + fail("should not throw an InterruptedException"); + } + } + + 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)) { @@ -310,78 +692,34 @@ public class AccountManagerServiceTest extends AndroidTestCase { return intent; } - static class MockAccountAuthenticatorCache implements IAccountAuthenticatorCache { - private ArrayList> mServices; - - MockAccountAuthenticatorCache() { - mServices = new ArrayList<>(); - AuthenticatorDescription d1 = new AuthenticatorDescription("type1", "p1", 0, 0, 0, 0); - AuthenticatorDescription d2 = new AuthenticatorDescription("type2", "p2", 0, 0, 0, 0); - mServices.add(new ServiceInfo<>(d1, null, null)); - mServices.add(new ServiceInfo<>(d2, null, null)); - } - - @Override - public ServiceInfo getServiceInfo( - AuthenticatorDescription type, int userId) { - for (ServiceInfo service : mServices) { - if (service.type.equals(type)) { - return service; - } - } - return null; - } - - @Override - public Collection> getAllServices(int userId) { - return mServices; - } - - @Override - public void dump( - final FileDescriptor fd, final PrintWriter fout, final String[] args, int userId) { - } - - @Override - public void setListener( - final RegisteredServicesCacheListener listener, - final Handler handler) { - } - - @Override - public void invalidateCache(int userId) { - } - - @Override - public void updateServices(int userId) { - } - } - static class MyMockContext extends MockContext { private Context mTestContext; - private AppOpsManager mAppOpsManager; - private UserManager mUserManager; - private PackageManager mPackageManager; + private Context mMockContext; - MyMockContext(Context testContext) { + MyMockContext(Context testContext, Context mockContext) { this.mTestContext = testContext; - this.mAppOpsManager = mock(AppOpsManager.class); - this.mUserManager = mock(UserManager.class); - this.mPackageManager = mock(PackageManager.class); - when(mPackageManager.checkSignatures(anyInt(), anyInt())) - .thenReturn(PackageManager.SIGNATURE_MATCH); - final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0); - when(mUserManager.getUserInfo(eq(ui.id))).thenReturn(ui); + this.mMockContext = mockContext; } @Override public int checkCallingOrSelfPermission(final String permission) { - return PackageManager.PERMISSION_GRANTED; + 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 mPackageManager; + return mMockContext.getPackageManager(); } @Override @@ -391,54 +729,62 @@ public class AccountManagerServiceTest extends AndroidTestCase { @Override public Object getSystemService(String name) { - if (Context.APP_OPS_SERVICE.equals(name)) { - return mAppOpsManager; - } else if( Context.USER_SERVICE.equals(name)) { - return mUserManager; - } - return null; + return mMockContext.getSystemService(name); } @Override public String getSystemServiceName(Class serviceClass) { - if (AppOpsManager.class.equals(serviceClass)) { - return Context.APP_OPS_SERVICE; - } - return null; + 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 null; + return mMockContext.registerReceiver(receiver, filter); } @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { - return null; + return mMockContext.registerReceiverAsUser( + receiver, user, filter, broadcastPermission, scheduler); } @Override public SQLiteDatabase openOrCreateDatabase(String file, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) { - Log.i(TAG, "openOrCreateDatabase " + file + " mode " + mode); return mTestContext.openOrCreateDatabase(file, mode, factory,errorHandler); } @Override public void sendBroadcastAsUser(Intent intent, UserHandle user) { - Log.i(TAG, "sendBroadcastAsUser " + intent + " " + user); + mMockContext.sendBroadcastAsUser(intent, user); } @Override public String getOpPackageName() { - return null; + return mMockContext.getOpPackageName(); + } + } + + 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; - TestInjector(Context realContext, MyMockContext mockContext) { + TestInjector(Context realContext, Context mockContext) { super(mockContext); mRealContext = realContext; } @@ -454,7 +800,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { @Override IAccountAuthenticatorCache getAccountAuthenticatorCache() { - return new MockAccountAuthenticatorCache(); + return new TestAccountAuthenticatorCache(mRealContext); } @Override @@ -477,4 +823,31 @@ public class AccountManagerServiceTest extends AndroidTestCase { return mock(INotificationManager.class); } } + + 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(); + } + } } diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java new file mode 100644 index 0000000000000..9a2c1903fd21e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.accounts; + +import android.accounts.Account; + +import java.util.ArrayList; +import java.util.List; + +/** + * Constants shared between test AccountAuthenticators and AccountManagerServiceTest. + */ +public final class AccountManagerServiceTestFixtures { + public static final String KEY_ACCOUNT_NAME = "account_manager_service_test:account_name_key"; + public static final String KEY_ACCOUNT_SESSION_BUNDLE = + "account_manager_service_test:account_session_bundle_key"; + public static final String KEY_ACCOUNT_STATUS_TOKEN = + "account_manager_service_test:account_status_token_key"; + public static final String KEY_ACCOUNT_PASSWORD = + "account_manager_service_test:account_password_key"; + + public static final String ACCOUNT_NAME_SUCCESS = "success_on_return@fixture.com"; + public static final String ACCOUNT_NAME_INTERVENE = "intervene@fixture.com"; + public static final String ACCOUNT_NAME_ERROR = "error@fixture.com"; + + public static final String ACCOUNT_NAME = + "com.android.server.accounts.account_manager_service_test.account.name"; + public static final String ACCOUNT_TYPE_1 = + "com.android.server.accounts.account_manager_service_test.account.type1"; + public static final String ACCOUNT_TYPE_2 = + "com.android.server.accounts.account_manager_service_test.account.type2"; + public static final String ACCOUNT_FAKE_TYPE = + "com.android.server.accounts.account_manager_service_test.account.type.fake"; + + public static final String ACCOUNT_STATUS_TOKEN = + "com.android.server.accounts.account_manager_service_test.account.status.token"; + + public static final String ACCOUNT_PASSWORD = + "com.android.server.accounts.account_manager_service_test.account.password"; + public static final String KEY_RESULT = "account_manager_service_test:result"; + public static final String KEY_CALLBACK = "account_manager_service_test:callback"; + + public static final Account ACCOUNT_SUCCESS = + new Account(ACCOUNT_NAME_SUCCESS, ACCOUNT_TYPE_1); + public static final Account ACCOUNT_INTERVENE = + new Account(ACCOUNT_NAME_INTERVENE, ACCOUNT_TYPE_1); + public static final Account ACCOUNT_ERROR = + new Account(ACCOUNT_NAME_ERROR, ACCOUNT_TYPE_1); + + public static final String SESSION_DATA_NAME_1 = "session.data.name.1"; + public static final String SESSION_DATA_VALUE_1 = "session.data.value.1"; + + public static final String ERROR_MESSAGE = + "com.android.server.accounts.account_manager_service_test.error.message"; + + private AccountManagerServiceTestFixtures() {} +} \ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/accounts/PreNTestDatabaseHelper.java b/services/tests/servicestests/src/com/android/server/accounts/PreNTestDatabaseHelper.java index 97adbe6417b30..38b37352c00cd 100644 --- a/services/tests/servicestests/src/com/android/server/accounts/PreNTestDatabaseHelper.java +++ b/services/tests/servicestests/src/com/android/server/accounts/PreNTestDatabaseHelper.java @@ -26,7 +26,7 @@ import android.database.sqlite.SQLiteOpenHelper; class PreNTestDatabaseHelper extends SQLiteOpenHelper { public static final String TOKEN_STRING = "token-string-123"; - public static final String ACCOUNT_TYPE = "type1"; + public static final String ACCOUNT_TYPE = AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2; public static final String ACCOUNT_NAME = "account@" + ACCOUNT_TYPE; public static final String ACCOUNT_PASSWORD = "Password"; public static final String TOKEN_TYPE = "SID"; diff --git a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java new file mode 100644 index 0000000000000..0db11e0cecd38 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.accounts; + +import android.accounts.AbstractAccountAuthenticator; +import android.accounts.Account; +import android.accounts.AccountAuthenticatorResponse; +import android.accounts.AccountManager; +import android.accounts.NetworkErrorException; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import com.android.frameworks.servicestests.R; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * This authenticator is to mock account authenticator to test AccountManagerService. + */ +public class TestAccountType1Authenticator extends AbstractAccountAuthenticator { + private final AtomicInteger mTokenCounter = new AtomicInteger(0); + + private final String mAccountType; + private final Context mContext; + + public TestAccountType1Authenticator(Context context, String accountType) { + super(context); + mAccountType = accountType; + mContext = context; + } + + @Override + public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) { + throw new UnsupportedOperationException( + "editProperties is not yet supported by the TestAccountAuthenticator"); + } + + @Override + public Bundle addAccount( + AccountAuthenticatorResponse response, + String accountType, + String authTokenType, + String[] requiredFeatures, + Bundle options) throws NetworkErrorException { + if (!mAccountType.equals(accountType)) { + throw new IllegalArgumentException("Request to the wrong authenticator!"); + } + + Bundle result = new Bundle(); + result.putString(AccountManager.KEY_ACCOUNT_NAME, "test_account@test.com"); + result.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccountType); + return result; + } + + @Override + public Bundle confirmCredentials( + AccountAuthenticatorResponse response, + Account account, + Bundle options) throws NetworkErrorException { + throw new UnsupportedOperationException( + "confirmCredentials is not yet supported by the TestAccountAuthenticator"); + } + + @Override + public Bundle getAuthToken( + AccountAuthenticatorResponse response, + Account account, + String authTokenType, + Bundle options) throws NetworkErrorException { + throw new UnsupportedOperationException( + "getAuthToken is not yet supported by the TestAccountAuthenticator"); + } + + @Override + public String getAuthTokenLabel(String authTokenType) { + throw new UnsupportedOperationException( + "getAuthTokenLabel is not yet supported by the TestAccountAuthenticator"); + } + + @Override + public Bundle updateCredentials( + AccountAuthenticatorResponse response, + Account account, + String authTokenType, + Bundle options) throws NetworkErrorException { + if (!mAccountType.equals(account.type)) { + throw new IllegalArgumentException("Request to the wrong authenticator!"); + } + Bundle result = new Bundle(); + result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); + result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type); + return result; + } + + @Override + public Bundle hasFeatures( + AccountAuthenticatorResponse response, + Account account, + String[] features) throws NetworkErrorException { + throw new UnsupportedOperationException( + "hasFeatures is not yet supported by the TestAccountAuthenticator"); + } + + @Override + public Bundle startAddAccountSession( + AccountAuthenticatorResponse response, + String accountType, + String authTokenType, + String[] requiredFeatures, + Bundle options) throws NetworkErrorException { + if (!mAccountType.equals(accountType)) { + throw new IllegalArgumentException("Request to the wrong authenticator!"); + } + + String accountName = null; + Bundle sessionBundle = null; + String password = null; + if (options != null) { + accountName = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME); + sessionBundle = options.getBundle( + AccountManagerServiceTestFixtures.KEY_ACCOUNT_SESSION_BUNDLE); + password = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_PASSWORD); + } + + Bundle result = new Bundle(); + if (accountName.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) { + // fill bundle with a success result. + result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle); + result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN, + AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN); + result.putString(AccountManager.KEY_PASSWORD, password); + result.putString(AccountManager.KEY_AUTHTOKEN, + Integer.toString(mTokenCounter.incrementAndGet())); + } else if (accountName.equals( + AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) { + // Specify data to be returned by the eventual activity. + Intent eventualActivityResultData = new Intent(); + eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN, + Integer.toString(mTokenCounter.incrementAndGet())); + eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_STATUS_TOKEN, + AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN); + eventualActivityResultData.putExtra(AccountManager.KEY_PASSWORD, password); + eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, + sessionBundle); + // Fill result with Intent. + Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class); + intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT, + eventualActivityResultData); + intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response); + + result.putParcelable(AccountManager.KEY_INTENT, intent); + } else { + // fill with error + fillResultWithError(result, options); + } + + return result; + } + + @Override + public Bundle startUpdateCredentialsSession( + AccountAuthenticatorResponse response, + Account account, + String authTokenType, + Bundle options) + throws NetworkErrorException { + + if (!mAccountType.equals(account.type)) { + throw new IllegalArgumentException("Request to the wrong authenticator!"); + } + + String accountName = null; + Bundle sessionBundle = null; + if (options != null) { + accountName = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME); + sessionBundle = options.getBundle( + AccountManagerServiceTestFixtures.KEY_ACCOUNT_SESSION_BUNDLE); + } + + Bundle result = new Bundle(); + if (accountName.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) { + // fill bundle with a success result. + result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle); + result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN, + AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN); + result.putString(AccountManager.KEY_PASSWORD, "doesn't matter"); + result.putString(AccountManager.KEY_AUTHTOKEN, + Integer.toString(mTokenCounter.incrementAndGet())); + } else if (accountName.equals( + AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) { + // Specify data to be returned by the eventual activity. + Intent eventualActivityResultData = new Intent(); + eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN, + Integer.toString(mTokenCounter.incrementAndGet())); + eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_STATUS_TOKEN, + AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN); + eventualActivityResultData.putExtra(AccountManager.KEY_PASSWORD, + AccountManagerServiceTestFixtures.ACCOUNT_PASSWORD); + eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, + sessionBundle); + // Fill result with Intent. + Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class); + intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT, + eventualActivityResultData); + intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response); + + result.putParcelable(AccountManager.KEY_INTENT, intent); + } else { + // fill with error + fillResultWithError(result, options); + } + return result; + } + + @Override + public Bundle finishSession(AccountAuthenticatorResponse response, + String accountType, + Bundle sessionBundle) throws NetworkErrorException { + + if (!mAccountType.equals(accountType)) { + throw new IllegalArgumentException("Request to the wrong authenticator!"); + } + + String accountName = null; + if (sessionBundle != null) { + accountName = sessionBundle.getString( + AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME); + } + + Bundle result = new Bundle(); + if (accountName.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) { + // fill bundle with a success result. + result.putString(AccountManager.KEY_ACCOUNT_NAME, + AccountManagerServiceTestFixtures.ACCOUNT_NAME); + result.putString(AccountManager.KEY_ACCOUNT_TYPE, + AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); + result.putString(AccountManager.KEY_AUTHTOKEN, + Integer.toString(mTokenCounter.incrementAndGet())); + } else if (accountName.equals( + AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) { + // Specify data to be returned by the eventual activity. + Intent eventualActivityResultData = new Intent(); + eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_NAME, + AccountManagerServiceTestFixtures.ACCOUNT_NAME); + eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_TYPE, + AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); + eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN, + Integer.toString(mTokenCounter.incrementAndGet())); + + // Fill result with Intent. + Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class); + intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT, + eventualActivityResultData); + intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response); + + result.putParcelable(AccountManager.KEY_INTENT, intent); + } else { + // fill with error + fillResultWithError(result, sessionBundle); + } + return result; + } + + @Override + public Bundle isCredentialsUpdateSuggested( + final AccountAuthenticatorResponse response, + Account account, + String statusToken) throws NetworkErrorException { + + Bundle result = new Bundle(); + if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) { + // fill bundle with a success result. + result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true); + } else { + // fill with error + fillResultWithError( + result, AccountManager.ERROR_CODE_INVALID_RESPONSE, "Default Error Message"); + } + + response.onResult(result); + return null; + } + + private void fillResultWithError(Bundle result, Bundle options) { + int errorCode = AccountManager.ERROR_CODE_INVALID_RESPONSE; + String errorMsg = "Default Error Message"; + if (options != null) { + errorCode = options.getInt(AccountManager.KEY_ERROR_CODE); + errorMsg = options.getString(AccountManager.KEY_ERROR_MESSAGE); + } + fillResultWithError(result, errorCode, errorMsg); + } + + private void fillResultWithError(Bundle result, int errorCode, String errorMsg) { + result.putInt(AccountManager.KEY_ERROR_CODE, errorCode); + result.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg); + } +} \ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1AuthenticatorService.java b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1AuthenticatorService.java new file mode 100644 index 0000000000000..acd1046bec50d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1AuthenticatorService.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.accounts; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +/** + * a test Mock Service for wrapping the TestAccountType1Authenticator + */ +public class TestAccountType1AuthenticatorService extends Service { + + @Override + public IBinder onBind(Intent intent) { + TestAccountType1Authenticator authenticator = new TestAccountType1Authenticator( + this, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1); + return authenticator.getIBinder(); + } +} \ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType2Authenticator.java b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType2Authenticator.java new file mode 100644 index 0000000000000..4cbc8cbf9a73a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType2Authenticator.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.accounts; + +import android.accounts.AbstractAccountAuthenticator; +import android.accounts.Account; +import android.accounts.AccountAuthenticatorResponse; +import android.accounts.AccountManager; +import android.accounts.NetworkErrorException; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import com.android.frameworks.servicestests.R; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * This authenticator is to mock account authenticator to test AccountManagerService. + */ +public class TestAccountType2Authenticator extends AbstractAccountAuthenticator { + private final AtomicInteger mTokenCounter = new AtomicInteger(0); + + private final String mAccountType; + private final Context mContext; + + public TestAccountType2Authenticator(Context context, String accountType) { + super(context); + mAccountType = accountType; + mContext = context; + } + + @Override + public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) { + throw new UnsupportedOperationException( + "editProperties is not supported by the TestAccountType2Authenticator"); + } + + @Override + public Bundle addAccount( + AccountAuthenticatorResponse response, + String accountType, + String authTokenType, + String[] requiredFeatures, + Bundle options) throws NetworkErrorException { + throw new UnsupportedOperationException( + "addAccount is not supported by the TestAccountType2Authenticator"); + } + + @Override + public Bundle confirmCredentials( + AccountAuthenticatorResponse response, + Account account, + Bundle options) throws NetworkErrorException { + throw new UnsupportedOperationException( + "confirmCredentials is not supported by the TestAccountType2Authenticator"); + } + + @Override + public Bundle getAuthToken( + AccountAuthenticatorResponse response, + Account account, + String authTokenType, + Bundle options) throws NetworkErrorException { + throw new UnsupportedOperationException( + "getAuthToken is not supported by the TestAccountType2Authenticator"); + } + + @Override + public String getAuthTokenLabel(String authTokenType) { + throw new UnsupportedOperationException( + "getAuthTokenLabel is not supported by the TestAccountType2Authenticator"); + } + + @Override + public Bundle updateCredentials( + AccountAuthenticatorResponse response, + Account account, + String authTokenType, + Bundle options) throws NetworkErrorException { + throw new UnsupportedOperationException( + "updateCredentials is not supported by the TestAccountType2Authenticator"); + } + + @Override + public Bundle hasFeatures( + AccountAuthenticatorResponse response, + Account account, + String[] features) throws NetworkErrorException { + throw new UnsupportedOperationException( + "hasFeatures is not supported by the TestAccountType2Authenticator"); + } + + @Override + public Bundle startAddAccountSession( + AccountAuthenticatorResponse response, + String accountType, + String authTokenType, + String[] requiredFeatures, + Bundle options) throws NetworkErrorException { + throw new UnsupportedOperationException( + "startAddAccountSession is not supported by the TestAccountType2Authenticator"); + } + + @Override + public Bundle startUpdateCredentialsSession( + AccountAuthenticatorResponse response, + Account account, + String authTokenType, + Bundle options) + throws NetworkErrorException { + throw new UnsupportedOperationException( + "startUpdateCredentialsSession is not supported " + + "by the TestAccountType2Authenticator"); + } + + @Override + public Bundle finishSession(AccountAuthenticatorResponse response, + String accountType, + Bundle sessionBundle) throws NetworkErrorException { + throw new UnsupportedOperationException( + "finishSession is not supported by the TestAccountType2Authenticator"); + } + + @Override + public Bundle isCredentialsUpdateSuggested( + final AccountAuthenticatorResponse response, + Account account, + String statusToken) throws NetworkErrorException { + throw new UnsupportedOperationException( + "isCredentialsUpdateSuggested is not supported " + + "by the TestAccountType2Authenticator"); + } +} \ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType2AuthenticatorService.java b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType2AuthenticatorService.java new file mode 100644 index 0000000000000..b80dc788d7518 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType2AuthenticatorService.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.accounts; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +/** + * a test Mock Service for wrapping the TestAccountType2Authenticator + */ +public class TestAccountType2AuthenticatorService extends Service { + + @Override + public IBinder onBind(Intent intent) { + TestAccountType2Authenticator authenticator = new TestAccountType2Authenticator( + this, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2); + return authenticator.getIBinder(); + } +} \ No newline at end of file