Test: AccountManagerService APCT test.
Setup test authenticators, add tests for startAddAccountSession.
Bug: 31346530
Change-Id: I0fb460a8a1c35e2c88c624d0e291b20051110b34
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 1393615..375e4fa 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -18,6 +18,7 @@
package="com.android.frameworks.servicestests">
<uses-permission android:name="android.permission.READ_LOGS" />
+ <uses-permission android:name="android.permission.ACCOUNT_MANAGER" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
@@ -65,6 +66,24 @@
</intent-filter>
</service>
+ <service android:name="com.android.server.accounts.TestAccountType1AuthenticatorService"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator" />
+ </intent-filter>
+ <meta-data android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/test_account_type1_authenticator" />
+ </service>
+
+ <service android:name="com.android.server.accounts.TestAccountType2AuthenticatorService"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator" />
+ </intent-filter>
+ <meta-data android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/test_account_type2_authenticator" />
+ </service>
+
<receiver android:name="com.android.server.devicepolicy.ApplicationRestrictionsTest$AdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin"
@@ -117,7 +136,9 @@
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity3" />
<activity android:name="com.android.server.pm.ShortcutTestActivity"
- android:enabled="true" android:exported="true" />
+ android:enabled="true" android:exported="true" />
+
+ <activity android:name="com.android.server.accounts.AccountAuthenticatorDummyActivity" />
<activity-alias android:name="a.ShortcutEnabled"
android:targetActivity="com.android.server.pm.ShortcutTestActivity"
diff --git a/services/tests/servicestests/res/values/strings.xml b/services/tests/servicestests/res/values/strings.xml
index 2f9d06c..121c1de 100644
--- a/services/tests/servicestests/res/values/strings.xml
+++ b/services/tests/servicestests/res/values/strings.xml
@@ -21,4 +21,8 @@
<string name="shortcut_title2"></string>
<string name="shortcut_text2"></string>
<string name="shortcut_disabled_message2"></string>
+ <string name="test_account_type1_authenticator_label">AccountManagerService Test Account Type1</string>
+ <string name="test_account_type2_authenticator_label">AccountManagerService Test Account Type2</string>
+ <string name="test_account_type1">com.android.server.accounts.account_manager_service_test.account.type1</string>
+ <string name="test_account_type2">com.android.server.accounts.account_manager_service_test.account.type2</string>
</resources>
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 0000000..0c531de
--- /dev/null
+++ b/services/tests/servicestests/res/xml/test_account_type1_authenticator.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="@string/test_account_type1"
+ android:icon="@drawable/icon1"
+ android:smallIcon="@drawable/icon1"
+ android:label="@string/test_account_type1_authenticator_label" />
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 0000000..f88eeb9
--- /dev/null
+++ b/services/tests/servicestests/res/xml/test_account_type2_authenticator.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="@string/test_account_type2"
+ android:icon="@drawable/icon1"
+ android:smallIcon="@drawable/icon1"
+ android:label="@string/test_account_type2_authenticator_label" />
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 0000000..8a14e1b
--- /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 c74cda6..ee49a00 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.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 @@
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<Intent> mIntentCaptor;
+ @Captor private ArgumentCaptor<Bundle> 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 @@
@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 @@
@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 @@
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 @@
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 @@
@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 @@
@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 @@
@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 @@
@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 @@
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 @@
return intent;
}
- static class MockAccountAuthenticatorCache implements IAccountAuthenticatorCache {
- private ArrayList<ServiceInfo<AuthenticatorDescription>> 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<AuthenticatorDescription> getServiceInfo(
- AuthenticatorDescription type, int userId) {
- for (ServiceInfo<AuthenticatorDescription> service : mServices) {
- if (service.type.equals(type)) {
- return service;
- }
- }
- return null;
- }
-
- @Override
- public Collection<ServiceInfo<AuthenticatorDescription>> 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<AuthenticatorDescription> 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 @@
@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 @@
@Override
IAccountAuthenticatorCache getAccountAuthenticatorCache() {
- return new MockAccountAuthenticatorCache();
+ return new TestAccountAuthenticatorCache(mRealContext);
}
@Override
@@ -477,4 +823,31 @@
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 0000000..9a2c190
--- /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 97adbe6..38b3735 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 @@
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 0000000..0db11e0c
--- /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 0000000..acd1046
--- /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 0000000..4cbc8cb
--- /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 0000000..b80dc78
--- /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