1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.accounts;
17
18import android.accounts.AbstractAccountAuthenticator;
19import android.accounts.Account;
20import android.accounts.AccountAuthenticatorResponse;
21import android.accounts.AccountManager;
22import android.accounts.NetworkErrorException;
23import android.content.Context;
24import android.content.Intent;
25import android.os.Bundle;
26
27import com.android.frameworks.servicestests.R;
28
29import java.util.concurrent.atomic.AtomicInteger;
30
31/**
32 * This authenticator is to mock account authenticator to test AccountManagerService.
33 */
34public class TestAccountType1Authenticator extends AbstractAccountAuthenticator {
35    private final AtomicInteger mTokenCounter  = new AtomicInteger(0);
36
37    private final String mAccountType;
38    private final Context mContext;
39
40    public TestAccountType1Authenticator(Context context, String accountType) {
41        super(context);
42        mAccountType = accountType;
43        mContext = context;
44    }
45
46    @Override
47    public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
48        Bundle result = new Bundle();
49        result.putString(AccountManager.KEY_ACCOUNT_NAME,
50                AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS);
51        result.putString(AccountManager.KEY_ACCOUNT_TYPE,
52                AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
53        result.putString(
54                AccountManager.KEY_AUTHTOKEN,
55                Integer.toString(mTokenCounter.incrementAndGet()));
56        return result;
57    }
58
59    @Override
60    public Bundle addAccount(
61            AccountAuthenticatorResponse response,
62            String accountType,
63            String authTokenType,
64            String[] requiredFeatures,
65            Bundle options) throws NetworkErrorException {
66        if (!mAccountType.equals(accountType)) {
67            throw new IllegalArgumentException("Request to the wrong authenticator!");
68        }
69        String accountName = null;
70
71        if (options != null) {
72            accountName = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME);
73        }
74
75        Bundle result = new Bundle();
76        if (accountName.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
77            // fill bundle with a success result.
78            result.putString(AccountManager.KEY_ACCOUNT_NAME, accountName);
79            result.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccountType);
80            result.putString(AccountManager.KEY_AUTHTOKEN,
81                    Integer.toString(mTokenCounter.incrementAndGet()));
82            result.putParcelable(AccountManagerServiceTestFixtures.KEY_OPTIONS_BUNDLE, options);
83        } else if (accountName.equals(
84                AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
85            // Specify data to be returned by the eventual activity.
86            Intent eventualActivityResultData = new Intent();
87            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_NAME, accountName);
88            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_TYPE, accountType);
89            // Fill result with Intent.
90            Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
91            intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT, eventualActivityResultData);
92            intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response);
93
94            result.putParcelable(AccountManager.KEY_INTENT, intent);
95        } else {
96            fillResultWithError(
97                    result,
98                    AccountManager.ERROR_CODE_INVALID_RESPONSE,
99                    AccountManagerServiceTestFixtures.ERROR_MESSAGE);
100        }
101        return result;
102    }
103
104    @Override
105    public Bundle confirmCredentials(
106            AccountAuthenticatorResponse response,
107            Account account,
108            Bundle options) throws NetworkErrorException {
109        if (!mAccountType.equals(account.type)) {
110            throw new IllegalArgumentException("Request to the wrong authenticator!");
111        }
112        Bundle result = new Bundle();
113
114        if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
115            // fill bundle with a success result.
116            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
117            result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
118            result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
119        } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
120            // Specify data to be returned by the eventual activity.
121            Intent eventualActivityResultData = new Intent();
122            eventualActivityResultData.putExtra(AccountManager.KEY_BOOLEAN_RESULT, true);
123            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
124            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_TYPE, account.type);
125
126            // Fill result with Intent.
127            Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
128            intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT,
129                    eventualActivityResultData);
130            intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response);
131
132            result.putParcelable(AccountManager.KEY_INTENT, intent);
133        } else {
134            // fill with error
135            fillResultWithError(
136                    result,
137                    AccountManager.ERROR_CODE_INVALID_RESPONSE,
138                    AccountManagerServiceTestFixtures.ERROR_MESSAGE);
139        }
140        return result;
141    }
142
143    @Override
144    public Bundle getAuthToken(
145            AccountAuthenticatorResponse response,
146            Account account,
147            String authTokenType,
148            Bundle options) throws NetworkErrorException {
149        if (!mAccountType.equals(account.type)) {
150            throw new IllegalArgumentException("Request to the wrong authenticator!");
151        }
152        Bundle result = new Bundle();
153
154        long expiryMillis = (options == null)
155                ? 0 : options.getLong(AccountManagerServiceTestFixtures.KEY_TOKEN_EXPIRY);
156        if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
157            // fill bundle with a success result.
158            result.putString(
159                    AccountManager.KEY_AUTHTOKEN, AccountManagerServiceTestFixtures.AUTH_TOKEN);
160            result.putLong(
161                    AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY,
162                    expiryMillis);
163            result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
164            result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
165        } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
166            // Specify data to be returned by the eventual activity.
167            Intent eventualActivityResultData = new Intent();
168            eventualActivityResultData.putExtra(
169                    AccountManager.KEY_AUTHTOKEN, AccountManagerServiceTestFixtures.AUTH_TOKEN);
170            eventualActivityResultData.putExtra(
171                    AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY,
172                    expiryMillis);
173            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
174            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_TYPE, account.type);
175
176            // Fill result with Intent.
177            Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
178            intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT,
179                    eventualActivityResultData);
180            intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response);
181
182            result.putParcelable(AccountManager.KEY_INTENT, intent);
183
184        } else {
185            fillResultWithError(
186                    result,
187                    AccountManager.ERROR_CODE_INVALID_RESPONSE,
188                    AccountManagerServiceTestFixtures.ERROR_MESSAGE);
189        }
190        return result;
191    }
192
193    @Override
194    public String getAuthTokenLabel(String authTokenType) {
195        return AccountManagerServiceTestFixtures.AUTH_TOKEN_LABEL;
196    }
197
198    @Override
199    public Bundle updateCredentials(
200            AccountAuthenticatorResponse response,
201            Account account,
202            String authTokenType,
203            Bundle options) throws NetworkErrorException {
204        if (!mAccountType.equals(account.type)) {
205            throw new IllegalArgumentException("Request to the wrong authenticator!");
206        }
207        Bundle result = new Bundle();
208
209        if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
210            // fill bundle with a success result.
211            result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
212            result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
213        } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
214            // Specify data to be returned by the eventual activity.
215            Intent eventualActivityResultData = new Intent();
216            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
217            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_TYPE, account.type);
218
219            // Fill result with Intent.
220            Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
221            intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT,
222                    eventualActivityResultData);
223            intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response);
224
225            result.putParcelable(AccountManager.KEY_INTENT, intent);
226        } else {
227            // fill with error
228            fillResultWithError(
229                    result,
230                    AccountManager.ERROR_CODE_INVALID_RESPONSE,
231                    AccountManagerServiceTestFixtures.ERROR_MESSAGE);
232        }
233        return result;
234    }
235
236    @Override
237    public Bundle hasFeatures(
238            AccountAuthenticatorResponse response,
239            Account account,
240            String[] features) throws NetworkErrorException {
241        Bundle result = new Bundle();
242        if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
243            // fill bundle with true.
244            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
245        } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS_2)) {
246            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
247        } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
248            // fill bundle with false.
249            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
250        } else {
251            // return null for error
252            result = null;
253        }
254
255        response.onResult(result);
256        return null;
257    }
258
259    @Override
260    public Bundle startAddAccountSession(
261            AccountAuthenticatorResponse response,
262            String accountType,
263            String authTokenType,
264            String[] requiredFeatures,
265            Bundle options) throws NetworkErrorException {
266        if (!mAccountType.equals(accountType)) {
267            throw new IllegalArgumentException("Request to the wrong authenticator!");
268        }
269
270        String accountName = null;
271        Bundle sessionBundle = null;
272        String password = null;
273        if (options != null) {
274            accountName = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME);
275            sessionBundle = options.getBundle(
276                    AccountManagerServiceTestFixtures.KEY_ACCOUNT_SESSION_BUNDLE);
277            password = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_PASSWORD);
278        }
279
280        Bundle result = new Bundle();
281        if (accountName.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
282            // fill bundle with a success result.
283            result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
284            result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
285                    AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
286            result.putString(AccountManager.KEY_PASSWORD, password);
287            result.putString(AccountManager.KEY_AUTHTOKEN,
288                    Integer.toString(mTokenCounter.incrementAndGet()));
289        } else if (accountName.equals(
290                AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
291            // Specify data to be returned by the eventual activity.
292            Intent eventualActivityResultData = new Intent();
293            eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN,
294                    Integer.toString(mTokenCounter.incrementAndGet()));
295            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
296                    AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
297            eventualActivityResultData.putExtra(AccountManager.KEY_PASSWORD, password);
298            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE,
299                    sessionBundle);
300            // Fill result with Intent.
301            Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
302            intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT,
303                    eventualActivityResultData);
304            intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response);
305
306            result.putParcelable(AccountManager.KEY_INTENT, intent);
307        } else {
308            // fill with error
309            fillResultWithError(result, options);
310        }
311
312        return result;
313    }
314
315    @Override
316    public Bundle startUpdateCredentialsSession(
317            AccountAuthenticatorResponse response,
318            Account account,
319            String authTokenType,
320            Bundle options)
321            throws NetworkErrorException {
322
323        if (!mAccountType.equals(account.type)) {
324            throw new IllegalArgumentException("Request to the wrong authenticator!");
325        }
326
327        String accountName = null;
328        Bundle sessionBundle = null;
329        if (options != null) {
330            accountName = options.getString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME);
331            sessionBundle = options.getBundle(
332            AccountManagerServiceTestFixtures.KEY_ACCOUNT_SESSION_BUNDLE);
333        }
334
335        Bundle result = new Bundle();
336        if (accountName.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
337            // fill bundle with a success result.
338            result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
339            result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
340                    AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
341            result.putString(AccountManager.KEY_PASSWORD,
342                    AccountManagerServiceTestFixtures.ACCOUNT_PASSWORD);
343            result.putString(AccountManager.KEY_AUTHTOKEN,
344                    Integer.toString(mTokenCounter.incrementAndGet()));
345        } else if (accountName.equals(
346                AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
347            // Specify data to be returned by the eventual activity.
348            Intent eventualActivityResultData = new Intent();
349            eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN,
350                    Integer.toString(mTokenCounter.incrementAndGet()));
351            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
352                    AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
353            eventualActivityResultData.putExtra(AccountManager.KEY_PASSWORD,
354                    AccountManagerServiceTestFixtures.ACCOUNT_PASSWORD);
355            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE,
356                    sessionBundle);
357            // Fill result with Intent.
358            Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
359            intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT,
360                    eventualActivityResultData);
361            intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response);
362
363            result.putParcelable(AccountManager.KEY_INTENT, intent);
364        } else {
365            // fill with error
366            fillResultWithError(result, options);
367        }
368        return result;
369    }
370
371    @Override
372    public Bundle finishSession(AccountAuthenticatorResponse response,
373            String accountType,
374            Bundle sessionBundle) throws NetworkErrorException {
375
376        if (!mAccountType.equals(accountType)) {
377            throw new IllegalArgumentException("Request to the wrong authenticator!");
378        }
379
380        String accountName = null;
381        if (sessionBundle != null) {
382            accountName = sessionBundle.getString(
383            AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME);
384        }
385
386        Bundle result = new Bundle();
387        if (accountName.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
388            // add sessionBundle into result for verification purpose
389            result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
390            // fill bundle with a success result.
391            result.putString(AccountManager.KEY_ACCOUNT_NAME,
392                    AccountManagerServiceTestFixtures.ACCOUNT_NAME);
393            result.putString(AccountManager.KEY_ACCOUNT_TYPE,
394                    AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
395            result.putString(AccountManager.KEY_AUTHTOKEN,
396                    Integer.toString(mTokenCounter.incrementAndGet()));
397        } else if (accountName.equals(
398                AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
399            // Specify data to be returned by the eventual activity.
400            Intent eventualActivityResultData = new Intent();
401            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_NAME,
402                    AccountManagerServiceTestFixtures.ACCOUNT_NAME);
403            eventualActivityResultData.putExtra(AccountManager.KEY_ACCOUNT_TYPE,
404                    AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
405            eventualActivityResultData.putExtra(AccountManager.KEY_AUTHTOKEN,
406                    Integer.toString(mTokenCounter.incrementAndGet()));
407
408            // Fill result with Intent.
409            Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
410            intent.putExtra(AccountManagerServiceTestFixtures.KEY_RESULT,
411                    eventualActivityResultData);
412            intent.putExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK, response);
413
414            result.putParcelable(AccountManager.KEY_INTENT, intent);
415        } else {
416            // fill with error
417            fillResultWithError(result, sessionBundle);
418        }
419        return result;
420    }
421
422    @Override
423    public Bundle isCredentialsUpdateSuggested(
424            final AccountAuthenticatorResponse response,
425            Account account,
426            String statusToken) throws NetworkErrorException {
427
428        Bundle result = new Bundle();
429        if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
430            // fill bundle with a success result.
431            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
432        } else {
433            // fill with error
434            fillResultWithError(
435                    result,
436                    AccountManager.ERROR_CODE_INVALID_RESPONSE,
437                    AccountManagerServiceTestFixtures.ERROR_MESSAGE);
438        }
439
440        response.onResult(result);
441        return null;
442    }
443
444    @Override
445    public Bundle getAccountRemovalAllowed(
446            AccountAuthenticatorResponse response, Account account) throws NetworkErrorException {
447        Bundle result = new Bundle();
448        if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
449            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
450        } else if (account.name.equals(
451                AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
452            Intent intent = new Intent(mContext, AccountAuthenticatorDummyActivity.class);
453            result.putParcelable(AccountManager.KEY_INTENT, intent);
454        } else {
455            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
456        }
457        return result;
458    }
459
460    private void fillResultWithError(Bundle result, Bundle options) {
461        int errorCode = AccountManager.ERROR_CODE_INVALID_RESPONSE;
462        String errorMsg = "Default Error Message";
463        if (options != null) {
464            errorCode = options.getInt(AccountManager.KEY_ERROR_CODE);
465            errorMsg = options.getString(AccountManager.KEY_ERROR_MESSAGE);
466        }
467        fillResultWithError(result, errorCode, errorMsg);
468    }
469
470    private void fillResultWithError(Bundle result, int errorCode, String errorMsg) {
471        result.putInt(AccountManager.KEY_ERROR_CODE, errorCode);
472        result.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
473    }
474}