blob: 1ad43fa7cfea8f427ad02c41ed45ac5600e743ea [file] [log] [blame]
Fred Quintana60307342009-03-24 22:48:12 -07001/*
2 * Copyright (C) 2009 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 */
16
17package android.accounts;
18
Sandra Kwan390c9d22016-01-12 14:13:37 -080019import static android.Manifest.permission.GET_ACCOUNTS;
20
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -070021import android.annotation.NonNull;
Tor Norbye80b530a2015-04-23 16:36:09 -070022import android.annotation.RequiresPermission;
23import android.annotation.Size;
Sandra Kwana578d112015-12-16 16:01:43 -080024import android.annotation.SystemApi;
Fred Quintana60307342009-03-24 22:48:12 -070025import android.app.Activity;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080026import android.content.BroadcastReceiver;
Amith Yamasani12b8e132013-03-14 10:48:07 -070027import android.content.ComponentName;
Fred Quintana60307342009-03-24 22:48:12 -070028import android.content.Context;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080029import android.content.Intent;
Fred Quintanad9d2f112009-04-23 13:36:27 -070030import android.content.IntentFilter;
Svetoslav Ganov5cb29732016-07-11 19:32:30 -070031import android.content.IntentSender;
Amith Yamasani12b8e132013-03-14 10:48:07 -070032import android.content.res.Resources;
Costin Manolacheb6437242009-09-10 16:14:12 -070033import android.database.SQLException;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080034import android.os.Build;
Fred Quintanaa698f422009-04-08 19:14:54 -070035import android.os.Bundle;
36import android.os.Handler;
37import android.os.Looper;
Fred Quintana33269202009-04-20 16:05:10 -070038import android.os.Parcelable;
Amith Yamasani2c7bc262012-11-05 16:46:02 -080039import android.os.Process;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080040import android.os.RemoteException;
Amith Yamasani2c7bc262012-11-05 16:46:02 -080041import android.os.UserHandle;
Fred Quintanaf0fd8432010-03-08 12:48:05 -080042import android.text.TextUtils;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080043import android.util.Log;
44
45import com.android.internal.R;
46import com.google.android.collect.Maps;
Fred Quintana60307342009-03-24 22:48:12 -070047
Fred Quintanaa698f422009-04-08 19:14:54 -070048import java.io.IOException;
Fred Quintana1121bb52011-09-14 23:19:35 -070049import java.util.ArrayList;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080050import java.util.HashMap;
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -070051import java.util.List;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080052import java.util.Map;
Fred Quintanaa698f422009-04-08 19:14:54 -070053import java.util.concurrent.Callable;
54import java.util.concurrent.CancellationException;
55import java.util.concurrent.ExecutionException;
56import java.util.concurrent.FutureTask;
Fred Quintanaa698f422009-04-08 19:14:54 -070057import java.util.concurrent.TimeUnit;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080058import java.util.concurrent.TimeoutException;
Fred Quintana60307342009-03-24 22:48:12 -070059
60/**
Dan Egnor661f0132010-02-19 11:23:00 -080061 * This class provides access to a centralized registry of the user's
Dan Egnor8e4378b2010-08-02 18:22:09 -070062 * online accounts. The user enters credentials (username and password) once
63 * per account, granting applications access to online resources with
64 * "one-click" approval.
Fred Quintana60307342009-03-24 22:48:12 -070065 *
Dan Egnor661f0132010-02-19 11:23:00 -080066 * <p>Different online services have different ways of handling accounts and
67 * authentication, so the account manager uses pluggable <em>authenticator</em>
Dan Egnor8e4378b2010-08-02 18:22:09 -070068 * modules for different <em>account types</em>. Authenticators (which may be
69 * written by third parties) handle the actual details of validating account
70 * credentials and storing account information. For example, Google, Facebook,
71 * and Microsoft Exchange each have their own authenticator.
Dan Egnor661f0132010-02-19 11:23:00 -080072 *
73 * <p>Many servers support some notion of an <em>authentication token</em>,
74 * which can be used to authenticate a request to the server without sending
75 * the user's actual password. (Auth tokens are normally created with a
76 * separate request which does include the user's credentials.) AccountManager
Dan Egnor8e4378b2010-08-02 18:22:09 -070077 * can generate auth tokens for applications, so the application doesn't need to
78 * handle passwords directly. Auth tokens are normally reusable and cached by
79 * AccountManager, but must be refreshed periodically. It's the responsibility
80 * of applications to <em>invalidate</em> auth tokens when they stop working so
81 * the AccountManager knows it needs to regenerate them.
Dan Egnor661f0132010-02-19 11:23:00 -080082 *
83 * <p>Applications accessing a server normally go through these steps:
84 *
85 * <ul>
86 * <li>Get an instance of AccountManager using {@link #get(Context)}.
87 *
88 * <li>List the available accounts using {@link #getAccountsByType} or
89 * {@link #getAccountsByTypeAndFeatures}. Normally applications will only
90 * be interested in accounts with one particular <em>type</em>, which
91 * identifies the authenticator. Account <em>features</em> are used to
92 * identify particular account subtypes and capabilities. Both the account
93 * type and features are authenticator-specific strings, and must be known by
94 * the application in coordination with its preferred authenticators.
95 *
96 * <li>Select one or more of the available accounts, possibly by asking the
97 * user for their preference. If no suitable accounts are available,
98 * {@link #addAccount} may be called to prompt the user to create an
99 * account of the appropriate type.
100 *
Dan Egnor8e4378b2010-08-02 18:22:09 -0700101 * <li><b>Important:</b> If the application is using a previously remembered
102 * account selection, it must make sure the account is still in the list
103 * of accounts returned by {@link #getAccountsByType}. Requesting an auth token
104 * for an account no longer on the device results in an undefined failure.
105 *
Dan Egnor661f0132010-02-19 11:23:00 -0800106 * <li>Request an auth token for the selected account(s) using one of the
107 * {@link #getAuthToken} methods or related helpers. Refer to the description
108 * of each method for exact usage and error handling details.
109 *
110 * <li>Make the request using the auth token. The form of the auth token,
111 * the format of the request, and the protocol used are all specific to the
Dan Egnor8e4378b2010-08-02 18:22:09 -0700112 * service you are accessing. The application may use whatever network and
113 * protocol libraries are useful.
Dan Egnor661f0132010-02-19 11:23:00 -0800114 *
115 * <li><b>Important:</b> If the request fails with an authentication error,
116 * it could be that a cached auth token is stale and no longer honored by
117 * the server. The application must call {@link #invalidateAuthToken} to remove
118 * the token from the cache, otherwise requests will continue failing! After
119 * invalidating the auth token, immediately go back to the "Request an auth
120 * token" step above. If the process fails the second time, then it can be
121 * treated as a "genuine" authentication failure and the user notified or other
122 * appropriate actions taken.
123 * </ul>
124 *
Dan Egnor8e4378b2010-08-02 18:22:09 -0700125 * <p>Some AccountManager methods may need to interact with the user to
Dan Egnor661f0132010-02-19 11:23:00 -0800126 * prompt for credentials, present options, or ask the user to add an account.
127 * The caller may choose whether to allow AccountManager to directly launch the
128 * necessary user interface and wait for the user, or to return an Intent which
129 * the caller may use to launch the interface, or (in some cases) to install a
130 * notification which the user can select at any time to launch the interface.
131 * To have AccountManager launch the interface directly, the caller must supply
132 * the current foreground {@link Activity} context.
133 *
134 * <p>Many AccountManager methods take {@link AccountManagerCallback} and
Dan Egnor8e4378b2010-08-02 18:22:09 -0700135 * {@link Handler} as parameters. These methods return immediately and
Dan Egnor661f0132010-02-19 11:23:00 -0800136 * run asynchronously. If a callback is provided then
137 * {@link AccountManagerCallback#run} will be invoked on the Handler's
138 * thread when the request completes, successfully or not.
Dan Egnor8e4378b2010-08-02 18:22:09 -0700139 * The result is retrieved by calling {@link AccountManagerFuture#getResult()}
140 * on the {@link AccountManagerFuture} returned by the method (and also passed
141 * to the callback). This method waits for the operation to complete (if
142 * necessary) and either returns the result or throws an exception if an error
143 * occurred during the operation. To make the request synchronously, call
Dan Egnor661f0132010-02-19 11:23:00 -0800144 * {@link AccountManagerFuture#getResult()} immediately on receiving the
Dan Egnor8e4378b2010-08-02 18:22:09 -0700145 * future from the method; no callback need be supplied.
Dan Egnor661f0132010-02-19 11:23:00 -0800146 *
147 * <p>Requests which may block, including
148 * {@link AccountManagerFuture#getResult()}, must never be called on
149 * the application's main event thread. These operations throw
150 * {@link IllegalStateException} if they are used on the main thread.
Fred Quintana60307342009-03-24 22:48:12 -0700151 */
152public class AccountManager {
153 private static final String TAG = "AccountManager";
154
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700155 public static final int ERROR_CODE_REMOTE_EXCEPTION = 1;
156 public static final int ERROR_CODE_NETWORK_ERROR = 3;
157 public static final int ERROR_CODE_CANCELED = 4;
158 public static final int ERROR_CODE_INVALID_RESPONSE = 5;
159 public static final int ERROR_CODE_UNSUPPORTED_OPERATION = 6;
160 public static final int ERROR_CODE_BAD_ARGUMENTS = 7;
161 public static final int ERROR_CODE_BAD_REQUEST = 8;
Jatin Lodhia3df7d692013-03-27 10:57:23 -0700162 public static final int ERROR_CODE_BAD_AUTHENTICATION = 9;
Fred Quintana756b7352009-10-21 13:43:10 -0700163
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800164 /** @hide */
165 public static final int ERROR_CODE_USER_RESTRICTED = 100;
Alexandra Gherghina999d3942014-07-03 11:40:08 +0100166 /** @hide */
167 public static final int ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE = 101;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800168
Dan Egnor661f0132010-02-19 11:23:00 -0800169 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700170 * Bundle key used for the {@link String} account name in results
Dan Egnor661f0132010-02-19 11:23:00 -0800171 * from methods which return information about a particular account.
172 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700173 public static final String KEY_ACCOUNT_NAME = "authAccount";
Dan Egnor661f0132010-02-19 11:23:00 -0800174
175 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700176 * Bundle key used for the {@link String} account type in results
Dan Egnor661f0132010-02-19 11:23:00 -0800177 * from methods which return information about a particular account.
178 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700179 public static final String KEY_ACCOUNT_TYPE = "accountType";
Dan Egnor661f0132010-02-19 11:23:00 -0800180
181 /**
Svet Ganovd4696122016-09-24 13:57:45 -0700182 * Bundle key used for the account access id used for noting the
183 * account was accessed when unmarshaled from a parcel.
Svet Ganovf6d424f12016-09-20 20:18:53 -0700184 *
185 * @hide
186 */
Svet Ganovd4696122016-09-24 13:57:45 -0700187 public static final String KEY_ACCOUNT_ACCESS_ID = "accountAccessId";
Svet Ganovf6d424f12016-09-20 20:18:53 -0700188
189 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700190 * Bundle key used for the auth token value in results
Dan Egnor661f0132010-02-19 11:23:00 -0800191 * from {@link #getAuthToken} and friends.
192 */
193 public static final String KEY_AUTHTOKEN = "authtoken";
194
195 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700196 * Bundle key used for an {@link Intent} in results from methods that
Dan Egnor661f0132010-02-19 11:23:00 -0800197 * may require the caller to interact with the user. The Intent can
198 * be used to start the corresponding user interface activity.
199 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700200 public static final String KEY_INTENT = "intent";
Dan Egnor661f0132010-02-19 11:23:00 -0800201
202 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700203 * Bundle key used to supply the password directly in options to
Dan Egnor661f0132010-02-19 11:23:00 -0800204 * {@link #confirmCredentials}, rather than prompting the user with
205 * the standard password prompt.
206 */
207 public static final String KEY_PASSWORD = "password";
208
209 public static final String KEY_ACCOUNTS = "accounts";
Brian Carlstrom46703b02011-04-06 15:41:29 -0700210
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700211 public static final String KEY_ACCOUNT_AUTHENTICATOR_RESPONSE = "accountAuthenticatorResponse";
212 public static final String KEY_ACCOUNT_MANAGER_RESPONSE = "accountManagerResponse";
Dan Egnor661f0132010-02-19 11:23:00 -0800213 public static final String KEY_AUTHENTICATOR_TYPES = "authenticator_types";
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700214 public static final String KEY_AUTH_FAILED_MESSAGE = "authFailedMessage";
215 public static final String KEY_AUTH_TOKEN_LABEL = "authTokenLabelKey";
Dan Egnor661f0132010-02-19 11:23:00 -0800216 public static final String KEY_BOOLEAN_RESULT = "booleanResult";
217 public static final String KEY_ERROR_CODE = "errorCode";
218 public static final String KEY_ERROR_MESSAGE = "errorMessage";
219 public static final String KEY_USERDATA = "userdata";
Costin Manolacheb61e8fb2011-09-08 11:26:09 -0700220
Costin Manolachea40c6302010-12-13 14:50:45 -0800221 /**
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800222 * Bundle key used to supply the last time the credentials of the account
223 * were authenticated successfully. Time is specified in milliseconds since
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700224 * epoch. Associated time is updated on successful authentication of account
225 * on adding account, confirming credentials, or updating credentials.
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800226 */
Simranjit Singh Kohli1663b442015-04-28 11:11:12 -0700227 public static final String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime";
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800228
229 /**
Costin Manolachea40c6302010-12-13 14:50:45 -0800230 * Authenticators using 'customTokens' option will also get the UID of the
231 * caller
232 */
233 public static final String KEY_CALLER_UID = "callerUid";
234 public static final String KEY_CALLER_PID = "callerPid";
Dan Egnor661f0132010-02-19 11:23:00 -0800235
Costin Manolached6060452011-01-24 16:11:36 -0800236 /**
Fred Quintanaad93a322011-09-08 13:21:01 -0700237 * The Android package of the caller will be set in the options bundle by the
238 * {@link AccountManager} and will be passed to the AccountManagerService and
239 * to the AccountAuthenticators. The uid of the caller will be known by the
240 * AccountManagerService as well as the AccountAuthenticators so they will be able to
241 * verify that the package is consistent with the uid (a uid might be shared by many
242 * packages).
243 */
244 public static final String KEY_ANDROID_PACKAGE_NAME = "androidPackageName";
245
246 /**
Costin Manolached6060452011-01-24 16:11:36 -0800247 * Boolean, if set and 'customTokens' the authenticator is responsible for
248 * notifications.
249 * @hide
250 */
251 public static final String KEY_NOTIFY_ON_FAILURE = "notifyOnAuthFailure";
252
Sandra Kwan78812282015-11-04 11:19:47 -0800253 /**
254 * Bundle key used for a {@link Bundle} in result from
255 * {@link #startAddAccountSession} and friends which returns session data
256 * for installing an account later.
257 */
258 public static final String KEY_ACCOUNT_SESSION_BUNDLE = "accountSessionBundle";
259
260 /**
261 * Bundle key used for the {@link String} account status token in result
262 * from {@link #startAddAccountSession} and friends which returns
263 * information about a particular account.
264 */
265 public static final String KEY_ACCOUNT_STATUS_TOKEN = "accountStatusToken";
266
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700267 public static final String ACTION_AUTHENTICATOR_INTENT =
268 "android.accounts.AccountAuthenticator";
269 public static final String AUTHENTICATOR_META_DATA_NAME =
Dan Egnor661f0132010-02-19 11:23:00 -0800270 "android.accounts.AccountAuthenticator";
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700271 public static final String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
272
Svetoslav Ganov5cb29732016-07-11 19:32:30 -0700273 /**
Svet Ganovf6d424f12016-09-20 20:18:53 -0700274 * Token type for the special case where a UID has access only to an account
275 * but no authenticator specific auth token types.
Svetoslav Ganov5cb29732016-07-11 19:32:30 -0700276 *
277 * @hide
278 */
Svet Ganovf6d424f12016-09-20 20:18:53 -0700279 public static final String ACCOUNT_ACCESS_TOKEN_TYPE =
280 "com.android.AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE";
Svetoslav Ganov5cb29732016-07-11 19:32:30 -0700281
Fred Quintana60307342009-03-24 22:48:12 -0700282 private final Context mContext;
283 private final IAccountManager mService;
Fred Quintanad9d2f112009-04-23 13:36:27 -0700284 private final Handler mMainHandler;
Dan Egnor661f0132010-02-19 11:23:00 -0800285
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700286 /**
287 * Action sent as a broadcast Intent by the AccountsService
Dan Egnor661f0132010-02-19 11:23:00 -0800288 * when accounts are added, accounts are removed, or an
289 * account's credentials (saved password, etc) are changed.
290 *
291 * @see #addOnAccountsUpdatedListener
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700292 */
293 public static final String LOGIN_ACCOUNTS_CHANGED_ACTION =
294 "android.accounts.LOGIN_ACCOUNTS_CHANGED";
Fred Quintana60307342009-03-24 22:48:12 -0700295
Fred Quintana33269202009-04-20 16:05:10 -0700296 /**
297 * @hide
298 */
Fred Quintana60307342009-03-24 22:48:12 -0700299 public AccountManager(Context context, IAccountManager service) {
300 mContext = context;
301 mService = service;
Fred Quintanad9d2f112009-04-23 13:36:27 -0700302 mMainHandler = new Handler(mContext.getMainLooper());
Fred Quintana60307342009-03-24 22:48:12 -0700303 }
304
Fred Quintana0eabf022009-04-27 15:08:17 -0700305 /**
306 * @hide used for testing only
307 */
308 public AccountManager(Context context, IAccountManager service, Handler handler) {
309 mContext = context;
310 mService = service;
311 mMainHandler = handler;
312 }
313
Fred Quintana756b7352009-10-21 13:43:10 -0700314 /**
Fred Quintanaf0fd8432010-03-08 12:48:05 -0800315 * @hide for internal use only
316 */
317 public static Bundle sanitizeResult(Bundle result) {
Fred Quintana382601f2010-03-25 12:25:10 -0700318 if (result != null) {
319 if (result.containsKey(KEY_AUTHTOKEN)
320 && !TextUtils.isEmpty(result.getString(KEY_AUTHTOKEN))) {
321 final Bundle newResult = new Bundle(result);
322 newResult.putString(KEY_AUTHTOKEN, "<omitted for logging purposes>");
323 return newResult;
324 }
Fred Quintanaf0fd8432010-03-08 12:48:05 -0800325 }
326 return result;
327 }
328
329 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800330 * Gets an AccountManager instance associated with a Context.
331 * The {@link Context} will be used as long as the AccountManager is
332 * active, so make sure to use a {@link Context} whose lifetime is
333 * commensurate with any listeners registered to
334 * {@link #addOnAccountsUpdatedListener} or similar methods.
335 *
336 * <p>It is safe to call this method from the main thread.
337 *
338 * <p>No permission is required to call this method.
339 *
Fred Quintana756b7352009-10-21 13:43:10 -0700340 * @param context The {@link Context} to use when necessary
Dan Egnor661f0132010-02-19 11:23:00 -0800341 * @return An {@link AccountManager} instance
Fred Quintana756b7352009-10-21 13:43:10 -0700342 */
Fred Quintanaa698f422009-04-08 19:14:54 -0700343 public static AccountManager get(Context context) {
Fred Quintana382601f2010-03-25 12:25:10 -0700344 if (context == null) throw new IllegalArgumentException("context is null");
Fred Quintanaa698f422009-04-08 19:14:54 -0700345 return (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
346 }
347
Fred Quintana756b7352009-10-21 13:43:10 -0700348 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800349 * Gets the saved password associated with the account.
350 * This is intended for authenticators and related code; applications
351 * should get an auth token instead.
352 *
353 * <p>It is safe to call this method from the main thread.
354 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700355 * <p>This method requires the caller to have a signature match with the
356 * authenticator that owns the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -0800357 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -0700358 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
359 * AUTHENTICATE_ACCOUNTS permission is needed for those platforms. See docs for
360 * this function in API level 22.
361 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700362 * @param account The account to query for a password. Must not be {@code null}.
Dan Egnor661f0132010-02-19 11:23:00 -0800363 * @return The account's password, null if none or if the account doesn't exist
Fred Quintana756b7352009-10-21 13:43:10 -0700364 */
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700365 public String getPassword(final Account account) {
Fred Quintana382601f2010-03-25 12:25:10 -0700366 if (account == null) throw new IllegalArgumentException("account is null");
Fred Quintana60307342009-03-24 22:48:12 -0700367 try {
368 return mService.getPassword(account);
369 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700370 throw e.rethrowFromSystemServer();
Fred Quintana60307342009-03-24 22:48:12 -0700371 }
372 }
373
Fred Quintana756b7352009-10-21 13:43:10 -0700374 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800375 * Gets the user data named by "key" associated with the account.
376 * This is intended for authenticators and related code to store
377 * arbitrary metadata along with accounts. The meaning of the keys
378 * and values is up to the authenticator for the account.
379 *
380 * <p>It is safe to call this method from the main thread.
381 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700382 * <p>This method requires the caller to have a signature match with the
383 * authenticator that owns the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -0800384 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -0700385 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
386 * AUTHENTICATE_ACCOUNTS permission is needed for those platforms. See docs
387 * for this function in API level 22.
388 *
Dan Egnor661f0132010-02-19 11:23:00 -0800389 * @param account The account to query for user data
390 * @return The user data, null if the account or key doesn't exist
Fred Quintana756b7352009-10-21 13:43:10 -0700391 */
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700392 public String getUserData(final Account account, final String key) {
Fred Quintana382601f2010-03-25 12:25:10 -0700393 if (account == null) throw new IllegalArgumentException("account is null");
394 if (key == null) throw new IllegalArgumentException("key is null");
Fred Quintana60307342009-03-24 22:48:12 -0700395 try {
396 return mService.getUserData(account, key);
397 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700398 throw e.rethrowFromSystemServer();
Fred Quintana60307342009-03-24 22:48:12 -0700399 }
400 }
401
Fred Quintana756b7352009-10-21 13:43:10 -0700402 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800403 * Lists the currently registered authenticators.
404 *
405 * <p>It is safe to call this method from the main thread.
406 *
407 * <p>No permission is required to call this method.
408 *
409 * @return An array of {@link AuthenticatorDescription} for every
410 * authenticator known to the AccountManager service. Empty (never
411 * null) if no authenticators are known.
Fred Quintana756b7352009-10-21 13:43:10 -0700412 */
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700413 public AuthenticatorDescription[] getAuthenticatorTypes() {
Fred Quintanaa698f422009-04-08 19:14:54 -0700414 try {
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100415 return mService.getAuthenticatorTypes(UserHandle.getCallingUserId());
416 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700417 throw e.rethrowFromSystemServer();
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100418 }
419 }
420
421 /**
422 * @hide
423 * Lists the currently registered authenticators for a given user id.
424 *
425 * <p>It is safe to call this method from the main thread.
426 *
427 * <p>The caller has to be in the same user or have the permission
428 * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
429 *
430 * @return An array of {@link AuthenticatorDescription} for every
431 * authenticator known to the AccountManager service. Empty (never
432 * null) if no authenticators are known.
433 */
434 public AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) {
435 try {
436 return mService.getAuthenticatorTypes(userId);
Fred Quintanaa698f422009-04-08 19:14:54 -0700437 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700438 throw e.rethrowFromSystemServer();
Fred Quintanaa698f422009-04-08 19:14:54 -0700439 }
440 }
441
Fred Quintana756b7352009-10-21 13:43:10 -0700442 /**
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000443 * Lists all accounts of any type registered on the device.
444 * Equivalent to getAccountsByType(null).
Dan Egnor661f0132010-02-19 11:23:00 -0800445 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000446 * <p>It is safe to call this method from the main thread.
Dan Egnor661f0132010-02-19 11:23:00 -0800447 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000448 * <p>Clients of this method that have not been granted the
449 * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
450 * will only see those accounts managed by AbstractAccountAuthenticators whose
451 * signature matches the client.
Dan Egnor661f0132010-02-19 11:23:00 -0800452 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000453 * @return An array of {@link Account}, one for each account. Empty
454 * (never null) if no accounts have been added.
Fred Quintana756b7352009-10-21 13:43:10 -0700455 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700456 @NonNull
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000457 @RequiresPermission(GET_ACCOUNTS)
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700458 public Account[] getAccounts() {
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000459 try {
460 return mService.getAccounts(null, mContext.getOpPackageName());
461 } catch (RemoteException e) {
462 throw e.rethrowFromSystemServer();
463 }
Fred Quintana60307342009-03-24 22:48:12 -0700464 }
465
Fred Quintana756b7352009-10-21 13:43:10 -0700466 /**
Amith Yamasani27db4682013-03-30 17:07:47 -0700467 * @hide
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000468 * Lists all accounts of any type registered on the device for a given
469 * user id. Equivalent to getAccountsByType(null).
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100470 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000471 * <p>It is safe to call this method from the main thread.
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100472 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000473 * <p>Clients of this method that have not been granted the
474 * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
475 * will only see those accounts managed by AbstractAccountAuthenticators whose
476 * signature matches the client.
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100477 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000478 * @return An array of {@link Account}, one for each account. Empty
479 * (never null) if no accounts have been added.
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100480 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700481 @NonNull
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000482 @RequiresPermission(GET_ACCOUNTS)
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100483 public Account[] getAccountsAsUser(int userId) {
484 try {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700485 return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName());
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100486 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700487 throw e.rethrowFromSystemServer();
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100488 }
489 }
490
491 /**
492 * @hide
Amith Yamasani27db4682013-03-30 17:07:47 -0700493 * For use by internal activities. Returns the list of accounts that the calling package
494 * is authorized to use, particularly for shared accounts.
495 * @param packageName package name of the calling app.
496 * @param uid the uid of the calling app.
497 * @return the accounts that are available to this package and user.
498 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700499 @NonNull
Amith Yamasani27db4682013-03-30 17:07:47 -0700500 public Account[] getAccountsForPackage(String packageName, int uid) {
501 try {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700502 return mService.getAccountsForPackage(packageName, uid, mContext.getOpPackageName());
Amith Yamasani27db4682013-03-30 17:07:47 -0700503 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700504 throw re.rethrowFromSystemServer();
Amith Yamasani27db4682013-03-30 17:07:47 -0700505 }
506 }
507
508 /**
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700509 * Returns the accounts visible to the specified package, in an environment where some apps
510 * are not authorized to view all accounts. This method can only be called by system apps.
511 * @param type The type of accounts to return, null to retrieve all accounts
512 * @param packageName The package name of the app for which the accounts are to be returned
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000513 * @return An array of {@link Account}, one per matching account. Empty
514 * (never null) if no accounts of the specified type have been added.
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700515 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700516 @NonNull
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700517 public Account[] getAccountsByTypeForPackage(String type, String packageName) {
518 try {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700519 return mService.getAccountsByTypeForPackage(type, packageName,
520 mContext.getOpPackageName());
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700521 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700522 throw re.rethrowFromSystemServer();
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700523 }
524 }
525
526 /**
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000527 * Lists all accounts of a particular type. The account type is a
528 * string token corresponding to the authenticator and useful domain
529 * of the account. For example, there are types corresponding to Google
530 * and Facebook. The exact string token to use will be published somewhere
531 * associated with the authenticator in question.
Dan Egnor661f0132010-02-19 11:23:00 -0800532 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000533 * <p>It is safe to call this method from the main thread.
Dan Egnor661f0132010-02-19 11:23:00 -0800534 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000535 * <p>Clients of this method that have not been granted the
536 * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
537 * will only see those accounts managed by AbstractAccountAuthenticators whose
538 * signature matches the client.
Dan Egnor661f0132010-02-19 11:23:00 -0800539 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000540 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
541 * GET_ACCOUNTS permission is needed for those platforms, irrespective of uid
542 * or signature match. See docs for this function in API level 22.
543 *
544 * @param type The type of accounts to return, null to retrieve all accounts
545 * @return An array of {@link Account}, one per matching account. Empty
546 * (never null) if no accounts of the specified type have been added.
Fred Quintana756b7352009-10-21 13:43:10 -0700547 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700548 @NonNull
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000549 @RequiresPermission(GET_ACCOUNTS)
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700550 public Account[] getAccountsByType(String type) {
Amith Yamasani2c7bc262012-11-05 16:46:02 -0800551 return getAccountsByTypeAsUser(type, Process.myUserHandle());
552 }
553
554 /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700555 @NonNull
Amith Yamasani2c7bc262012-11-05 16:46:02 -0800556 public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
Fred Quintana60307342009-03-24 22:48:12 -0700557 try {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700558 return mService.getAccountsAsUser(type, userHandle.getIdentifier(),
559 mContext.getOpPackageName());
Fred Quintana60307342009-03-24 22:48:12 -0700560 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700561 throw e.rethrowFromSystemServer();
Fred Quintana60307342009-03-24 22:48:12 -0700562 }
563 }
564
Fred Quintana756b7352009-10-21 13:43:10 -0700565 /**
Fred Quintanad9640ec2012-05-23 12:37:00 -0700566 * Change whether or not an app (identified by its uid) is allowed to retrieve an authToken
567 * for an account.
568 * <p>
569 * This is only meant to be used by system activities and is not in the SDK.
570 * @param account The account whose permissions are being modified
571 * @param authTokenType The type of token whose permissions are being modified
572 * @param uid The uid that identifies the app which is being granted or revoked permission.
573 * @param value true is permission is being granted, false for revoked
574 * @hide
575 */
576 public void updateAppPermission(Account account, String authTokenType, int uid, boolean value) {
577 try {
578 mService.updateAppPermission(account, authTokenType, uid, value);
579 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700580 throw e.rethrowFromSystemServer();
Fred Quintanad9640ec2012-05-23 12:37:00 -0700581 }
582 }
583
584 /**
585 * Get the user-friendly label associated with an authenticator's auth token.
586 * @param accountType the type of the authenticator. must not be null.
587 * @param authTokenType the token type. must not be null.
588 * @param callback callback to invoke when the result is available. may be null.
589 * @param handler the handler on which to invoke the callback, or null for the main thread
590 * @return a future containing the label string
591 * @hide
592 */
593 public AccountManagerFuture<String> getAuthTokenLabel(
594 final String accountType, final String authTokenType,
595 AccountManagerCallback<String> callback, Handler handler) {
596 if (accountType == null) throw new IllegalArgumentException("accountType is null");
597 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
598 return new Future2Task<String>(handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -0800599 @Override
Fred Quintanad9640ec2012-05-23 12:37:00 -0700600 public void doWork() throws RemoteException {
601 mService.getAuthTokenLabel(mResponse, accountType, authTokenType);
602 }
603
604 @Override
605 public String bundleToResult(Bundle bundle) throws AuthenticatorException {
606 if (!bundle.containsKey(KEY_AUTH_TOKEN_LABEL)) {
607 throw new AuthenticatorException("no result in response");
608 }
609 return bundle.getString(KEY_AUTH_TOKEN_LABEL);
610 }
611 }.start();
612 }
613
614 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800615 * Finds out whether a particular account has all the specified features.
616 * Account features are authenticator-specific string tokens identifying
617 * boolean account properties. For example, features are used to tell
618 * whether Google accounts have a particular service (such as Google
619 * Calendar or Google Talk) enabled. The feature names and their meanings
620 * are published somewhere associated with the authenticator in question.
621 *
622 * <p>This method may be called from any thread, but the returned
623 * {@link AccountManagerFuture} must not be used on the main thread.
624 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000625 * <p>This method requires the caller to hold the permission
626 * {@link android.Manifest.permission#GET_ACCOUNTS} or be a signature
627 * match with the AbstractAccountAuthenticator that manages the account.
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800628 *
629 * @param account The {@link Account} to test
Dan Egnor661f0132010-02-19 11:23:00 -0800630 * @param features An array of the account features to check
631 * @param callback Callback to invoke when the request completes,
632 * null for no callback
633 * @param handler {@link Handler} identifying the callback thread,
634 * null for the main thread
635 * @return An {@link AccountManagerFuture} which resolves to a Boolean,
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000636 * true if the account exists and has all of the specified features.
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800637 */
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000638 @RequiresPermission(GET_ACCOUNTS)
Fred Quintana3084a6f2010-01-14 18:02:03 -0800639 public AccountManagerFuture<Boolean> hasFeatures(final Account account,
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800640 final String[] features,
641 AccountManagerCallback<Boolean> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -0700642 if (account == null) throw new IllegalArgumentException("account is null");
643 if (features == null) throw new IllegalArgumentException("features is null");
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800644 return new Future2Task<Boolean>(handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -0800645 @Override
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800646 public void doWork() throws RemoteException {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700647 mService.hasFeatures(mResponse, account, features, mContext.getOpPackageName());
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800648 }
Sandra Kwan0b84b452016-01-20 15:25:42 -0800649 @Override
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800650 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
651 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
652 throw new AuthenticatorException("no result in response");
653 }
654 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
655 }
656 }.start();
657 }
658
659 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800660 * Lists all accounts of a type which have certain features. The account
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000661 * type identifies the authenticator (see {@link #getAccountsByType}).
662 * Account features are authenticator-specific string tokens identifying
663 * boolean account properties (see {@link #hasFeatures}).
Fred Quintana756b7352009-10-21 13:43:10 -0700664 *
Dan Egnor661f0132010-02-19 11:23:00 -0800665 * <p>Unlike {@link #getAccountsByType}, this method calls the authenticator,
666 * which may contact the server or do other work to check account features,
667 * so the method returns an {@link AccountManagerFuture}.
Fred Quintanaa698f422009-04-08 19:14:54 -0700668 *
Dan Egnor661f0132010-02-19 11:23:00 -0800669 * <p>This method may be called from any thread, but the returned
670 * {@link AccountManagerFuture} must not be used on the main thread.
Fred Quintana756b7352009-10-21 13:43:10 -0700671 *
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000672 * <p>Clients of this method that have not been granted the
673 * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
674 * will only see those accounts managed by AbstractAccountAuthenticators whose
675 * signature matches the client.
Fred Quintana756b7352009-10-21 13:43:10 -0700676 *
Dan Egnor661f0132010-02-19 11:23:00 -0800677 * @param type The type of accounts to return, must not be null
678 * @param features An array of the account features to require,
679 * may be null or empty
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000680 *
681 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
682 * GET_ACCOUNTS permission is needed for those platforms, irrespective of uid
683 * or signature match. See docs for this function in API level 22.
684 *
Dan Egnor661f0132010-02-19 11:23:00 -0800685 * @param callback Callback to invoke when the request completes,
686 * null for no callback
687 * @param handler {@link Handler} identifying the callback thread,
688 * null for the main thread
689 * @return An {@link AccountManagerFuture} which resolves to an array of
690 * {@link Account}, one per account of the specified type which
691 * matches the requested features.
Fred Quintana8570f742010-02-18 10:32:54 -0800692 */
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000693 @RequiresPermission(GET_ACCOUNTS)
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700694 public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
695 final String type, final String[] features,
696 AccountManagerCallback<Account[]> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -0700697 if (type == null) throw new IllegalArgumentException("type is null");
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700698 return new Future2Task<Account[]>(handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -0800699 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700700 public void doWork() throws RemoteException {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700701 mService.getAccountsByFeatures(mResponse, type, features,
702 mContext.getOpPackageName());
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700703 }
Sandra Kwan0b84b452016-01-20 15:25:42 -0800704 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700705 public Account[] bundleToResult(Bundle bundle) throws AuthenticatorException {
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700706 if (!bundle.containsKey(KEY_ACCOUNTS)) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700707 throw new AuthenticatorException("no result in response");
708 }
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700709 final Parcelable[] parcelables = bundle.getParcelableArray(KEY_ACCOUNTS);
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700710 Account[] descs = new Account[parcelables.length];
711 for (int i = 0; i < parcelables.length; i++) {
712 descs[i] = (Account) parcelables[i];
713 }
714 return descs;
715 }
716 }.start();
717 }
718
Fred Quintana756b7352009-10-21 13:43:10 -0700719 /**
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700720 * Adds an account directly to the AccountManager. Normally used by sign-up
Dan Egnor661f0132010-02-19 11:23:00 -0800721 * wizards associated with authenticators, not directly by applications.
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700722 * <p>Calling this method does not update the last authenticated timestamp,
723 * referred by {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
724 * {@link #notifyAccountAuthenticated(Account)} after getting success.
725 * However, if this method is called when it is triggered by addAccount() or
726 * addAccountAsUser() or similar functions, then there is no need to update
727 * timestamp manually as it is updated automatically by framework on
728 * successful completion of the mentioned functions.
Dan Egnor661f0132010-02-19 11:23:00 -0800729 * <p>It is safe to call this method from the main thread.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700730 * <p>This method requires the caller to have a signature match with the
731 * authenticator that owns the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -0800732 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -0700733 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
734 * AUTHENTICATE_ACCOUNTS permission is needed for those platforms. See docs
735 * for this function in API level 22.
736 *
Dan Egnor661f0132010-02-19 11:23:00 -0800737 * @param account The {@link Account} to add
738 * @param password The password to associate with the account, null for none
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700739 * @param userdata String values to use for the account's userdata, null for
740 * none
Dan Egnor8e4378b2010-08-02 18:22:09 -0700741 * @return True if the account was successfully added, false if the account
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700742 * already exists, the account is null, or another error occurs.
Dan Egnor661f0132010-02-19 11:23:00 -0800743 */
744 public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
Fred Quintana382601f2010-03-25 12:25:10 -0700745 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -0800746 try {
Amith Yamasani27db4682013-03-30 17:07:47 -0700747 return mService.addAccountExplicitly(account, password, userdata);
Dan Egnor661f0132010-02-19 11:23:00 -0800748 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700749 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -0800750 }
751 }
752
753 /**
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700754 * Adds an account directly to the AccountManager. Additionally this
755 * makes the Account visible to desired UIDs of applications on the device,
756 * and sends directed broadcasts to these individual applications.
757 * <p>Normally used by sign-up wizards associated with authenticators, not
758 * directly by applications.
759 * <p>Calling this method does not update the last authenticated timestamp,
760 * referred by {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
761 * {@link #notifyAccountAuthenticated(Account)} after getting success.
762 * <p>It is safe to call this method from the main thread.
763 * <p>This method requires the caller to have a signature match with the
764 * authenticator that owns the specified account.
765 *
766 * @param account The {@link Account} to add
767 * @param password The password to associate with the account, null for none
768 * @param extras String values to use for the account's userdata, null for
769 * none
770 * @param selectedUids Array of uids whose associated applications can access
771 * this account without any additional user approval.
772 *
773 * @return True if the account was successfully added, false if the account
774 * already exists, the account is null, or another error occurs.
775 */
776 public boolean addAccountExplicitly(Account account, String password, Bundle extras,
777 int[] selectedUids) {
778 if (account == null) throw new IllegalArgumentException("account is null");
779 try {
780 return mService.addAccountExplicitlyWithUid(account, password, extras, selectedUids);
781 } catch (RemoteException e) {
782 throw e.rethrowFromSystemServer();
783 }
784 }
785
786 /**
787 * Returns all UIDs for applications that requested the account type.
788 * <p>This method requires the caller to have a signature match with the authenticator
789 * that owns the specified account.
790 *
791 * @param accountType The account type to be authenticated.
792 *
793 * @return array of all UIDs that support accounts of this
794 * account type that seek approval (to be used to know which accounts for
795 * the authenticator to include in addAccountExplicitly). Null if none.
796 */
797 public int[] getRequestingUidsForType(String accountType) {
798 try {
799 return mService.getRequestingUidsForType(accountType);
800 } catch (RemoteException re) {
801 throw re.rethrowFromSystemServer();
802 }
803 }
804
805 /**
806 * Gives a certain UID, represented a application, access to an account
807 * <p>This method requires the caller to have a signature match with the authenticator
808 * that owns the specified account.
809 *
810 * @param account Account to make visible.
811 * @param uid The UID of the application to add account access.
812 *
813 * @return True if account made visible to application and was not previously visible.
814 */
815 public boolean makeAccountVisible(Account account, int uid) {
816 try {
817 return mService.makeAccountVisible(account, uid);
818 } catch (RemoteException re) {
819 throw re.rethrowFromSystemServer();
820 }
821 }
822
823 /**
824 * Removes visibility of certain account of a process identified
825 * by a given UID to an application.
826 * This is called by the Authenticator.
827 * <p>This method requires the caller to have a signature match with the authenticator
828 * that owns the specified account.
829 *
830 * @param account Remove visibility of this account..
831 * @param uid The UID of the application to remove account access.
832 *
833 * @return True if application access to account removed and was previously visible.
834 */
835 public boolean removeAccountVisibility(Account account, int uid) {
836 try {
837 return mService.removeAccountVisibility(account, uid);
838 } catch (RemoteException re) {
839 throw re.rethrowFromSystemServer();
840 }
841 }
842
843 /**
844 * Checks visibility of certain account of a process identified
845 * by a given UID. This is called by the Authenticator.
846 * <p>This method requires the caller to have a signature match with the authenticator
847 * that owns the specified account.
848 *
849 * @param account Account to check visibility.
850 * @param uid The UID of the application to check account access.
851 *
852 * @return True if application has access to the account
853 */
854 public boolean isAccountVisible(Account account, int uid) {
855 try {
856 return mService.isAccountVisible(account, uid);
857 } catch (RemoteException re) {
858 throw re.rethrowFromSystemServer();
859 }
860 }
861
862 /**
Simranjit Singh Kohli1663b442015-04-28 11:11:12 -0700863 * Notifies the system that the account has just been authenticated. This
864 * information may be used by other applications to verify the account. This
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800865 * should be called only when the user has entered correct credentials for
866 * the account.
867 * <p>
868 * It is not safe to call this method from the main thread. As such, call it
869 * from another thread.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700870 * <p>This method requires the caller to have a signature match with the
871 * authenticator that owns the specified account.
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800872 *
873 * @param account The {@link Account} to be updated.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700874 * @return boolean {@code true} if the authentication of the account has been successfully
875 * acknowledged. Otherwise {@code false}.
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800876 */
Simranjit Singh Kohli1663b442015-04-28 11:11:12 -0700877 public boolean notifyAccountAuthenticated(Account account) {
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800878 if (account == null)
879 throw new IllegalArgumentException("account is null");
880 try {
881 return mService.accountAuthenticated(account);
882 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700883 throw e.rethrowFromSystemServer();
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800884 }
885 }
886
887 /**
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -0700888 * Rename the specified {@link Account}. This is equivalent to removing
889 * the existing account and adding a new renamed account with the old
890 * account's user data.
891 *
892 * <p>It is safe to call this method from the main thread.
893 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700894 * <p>This method requires the caller to have a signature match with the
895 * authenticator that manages the specified account.
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -0700896 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -0700897 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
898 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
899 * is needed for those platforms. See docs for this function in API level 22.
900 *
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -0700901 * @param account The {@link Account} to rename
902 * @param newName String name to be associated with the account.
903 * @param callback Callback to invoke when the request completes, null for
904 * no callback
905 * @param handler {@link Handler} identifying the callback thread, null for
906 * the main thread
907 * @return An {@link AccountManagerFuture} which resolves to the Account
908 * after the name change. If successful the account's name will be the
909 * specified new name.
910 */
911 public AccountManagerFuture<Account> renameAccount(
912 final Account account,
Tor Norbye80b530a2015-04-23 16:36:09 -0700913 @Size(min = 1) final String newName,
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -0700914 AccountManagerCallback<Account> callback,
915 Handler handler) {
916 if (account == null) throw new IllegalArgumentException("account is null.");
917 if (TextUtils.isEmpty(newName)) {
918 throw new IllegalArgumentException("newName is empty or null.");
919 }
920 return new Future2Task<Account>(handler, callback) {
921 @Override
922 public void doWork() throws RemoteException {
923 mService.renameAccount(mResponse, account, newName);
924 }
925 @Override
926 public Account bundleToResult(Bundle bundle) throws AuthenticatorException {
927 String name = bundle.getString(KEY_ACCOUNT_NAME);
928 String type = bundle.getString(KEY_ACCOUNT_TYPE);
Svet Ganovc1c0d1c2016-09-23 19:15:47 -0700929 String accessId = bundle.getString(KEY_ACCOUNT_ACCESS_ID);
930 return new Account(name, type, accessId);
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -0700931 }
932 }.start();
933 }
934
935 /**
936 * Gets the previous name associated with the account or {@code null}, if
937 * none. This is intended so that clients of {@link
938 * #LOGIN_ACCOUNTS_CHANGED_ACTION} broadcasts can determine if an
939 * authenticator has renamed an account.
940 *
941 * <p>It is safe to call this method from the main thread.
942 *
943 * @param account The account to query for a previous name.
944 * @return The account's previous name, null if the account has never been
945 * renamed.
946 */
947 public String getPreviousName(final Account account) {
948 if (account == null) throw new IllegalArgumentException("account is null");
949 try {
950 return mService.getPreviousName(account);
951 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700952 throw e.rethrowFromSystemServer();
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -0700953 }
954 }
955
956 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800957 * Removes an account from the AccountManager. Does nothing if the account
958 * does not exist. Does not delete the account from the server.
959 * The authenticator may have its own policies preventing account
960 * deletion, in which case the account will not be deleted.
961 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700962 * <p>This method requires the caller to have a signature match with the
963 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -0800964 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -0700965 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
966 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
967 * this function in API level 22.
968 *
Dan Egnor661f0132010-02-19 11:23:00 -0800969 * @param account The {@link Account} to remove
970 * @param callback Callback to invoke when the request completes,
971 * null for no callback
972 * @param handler {@link Handler} identifying the callback thread,
973 * null for the main thread
974 * @return An {@link AccountManagerFuture} which resolves to a Boolean,
Alexandra Gherghina999d3942014-07-03 11:40:08 +0100975 * true if the account has been successfully removed
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -0800976 * @deprecated use
977 * {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)}
978 * instead
Dan Egnor661f0132010-02-19 11:23:00 -0800979 */
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -0800980 @Deprecated
Dan Egnor661f0132010-02-19 11:23:00 -0800981 public AccountManagerFuture<Boolean> removeAccount(final Account account,
982 AccountManagerCallback<Boolean> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -0700983 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -0800984 return new Future2Task<Boolean>(handler, callback) {
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700985 @Override
Dan Egnor661f0132010-02-19 11:23:00 -0800986 public void doWork() throws RemoteException {
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -0800987 mService.removeAccount(mResponse, account, false);
Dan Egnor661f0132010-02-19 11:23:00 -0800988 }
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700989 @Override
Dan Egnor661f0132010-02-19 11:23:00 -0800990 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
991 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
992 throw new AuthenticatorException("no result in response");
993 }
994 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
995 }
996 }.start();
997 }
998
999 /**
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001000 * Removes an account from the AccountManager. Does nothing if the account
1001 * does not exist. Does not delete the account from the server.
1002 * The authenticator may have its own policies preventing account
1003 * deletion, in which case the account will not be deleted.
1004 *
1005 * <p>This method may be called from any thread, but the returned
1006 * {@link AccountManagerFuture} must not be used on the main thread.
1007 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001008 * <p>This method requires the caller to have a signature match with the
1009 * authenticator that manages the specified account.
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001010 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001011 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1012 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
1013 * this function in API level 22.
1014 *
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001015 * @param account The {@link Account} to remove
1016 * @param activity The {@link Activity} context to use for launching a new
1017 * authenticator-defined sub-Activity to prompt the user to delete an
1018 * account; used only to call startActivity(); if null, the prompt
1019 * will not be launched directly, but the {@link Intent} may be
1020 * returned to the caller instead
1021 * @param callback Callback to invoke when the request completes,
1022 * null for no callback
1023 * @param handler {@link Handler} identifying the callback thread,
1024 * null for the main thread
1025 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
1026 * {@link #KEY_BOOLEAN_RESULT} if activity was specified and an account
1027 * was removed or if active. If no activity was specified, the returned
1028 * Bundle contains only {@link #KEY_INTENT} with the {@link Intent}
1029 * needed to launch the actual account removal process, if authenticator
1030 * needs the activity launch. If an error occurred,
1031 * {@link AccountManagerFuture#getResult()} throws:
1032 * <ul>
1033 * <li> {@link AuthenticatorException} if no authenticator was registered for
1034 * this account type or the authenticator failed to respond
1035 * <li> {@link OperationCanceledException} if the operation was canceled for
1036 * any reason, including the user canceling the creation process or
1037 * adding accounts (of this type) has been disabled by policy
1038 * </ul>
1039 */
1040 public AccountManagerFuture<Bundle> removeAccount(final Account account,
1041 final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
1042 if (account == null) throw new IllegalArgumentException("account is null");
1043 return new AmsTask(activity, handler, callback) {
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001044 @Override
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001045 public void doWork() throws RemoteException {
1046 mService.removeAccount(mResponse, account, activity != null);
1047 }
1048 }.start();
1049 }
1050
1051 /**
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001052 * @see #removeAccount(Account, AccountManagerCallback, Handler)
1053 * @hide
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001054 * @deprecated use
1055 * {@link #removeAccountAsUser(Account, Activity, AccountManagerCallback, Handler)}
1056 * instead
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001057 */
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001058 @Deprecated
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001059 public AccountManagerFuture<Boolean> removeAccountAsUser(final Account account,
1060 AccountManagerCallback<Boolean> callback, Handler handler,
1061 final UserHandle userHandle) {
1062 if (account == null) throw new IllegalArgumentException("account is null");
1063 if (userHandle == null) throw new IllegalArgumentException("userHandle is null");
1064 return new Future2Task<Boolean>(handler, callback) {
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001065 @Override
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001066 public void doWork() throws RemoteException {
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001067 mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier());
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001068 }
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001069 @Override
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001070 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
1071 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
1072 throw new AuthenticatorException("no result in response");
1073 }
1074 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
1075 }
1076 }.start();
1077 }
1078
1079 /**
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001080 * @see #removeAccount(Account, Activity, AccountManagerCallback, Handler)
1081 * @hide
1082 */
1083 public AccountManagerFuture<Bundle> removeAccountAsUser(final Account account,
1084 final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler,
1085 final UserHandle userHandle) {
1086 if (account == null)
1087 throw new IllegalArgumentException("account is null");
1088 if (userHandle == null)
1089 throw new IllegalArgumentException("userHandle is null");
1090 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001091 @Override
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001092 public void doWork() throws RemoteException {
1093 mService.removeAccountAsUser(mResponse, account, activity != null,
1094 userHandle.getIdentifier());
1095 }
1096 }.start();
1097 }
1098
1099 /**
1100 * Removes an account directly. Normally used by authenticators, not
1101 * directly by applications. Does not delete the account from the server.
1102 * The authenticator may have its own policies preventing account deletion,
1103 * in which case the account will not be deleted.
1104 * <p>
1105 * It is safe to call this method from the main thread.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001106 * <p>This method requires the caller to have a signature match with the
1107 * authenticator that manages the specified account.
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001108 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001109 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1110 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1111 * is needed for those platforms. See docs for this function in API level 22.
1112 *
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001113 * @param account The {@link Account} to delete.
1114 * @return True if the account was successfully deleted, false if the
1115 * account did not exist, the account is null, or another error
1116 * occurs.
1117 */
1118 public boolean removeAccountExplicitly(Account account) {
1119 if (account == null) throw new IllegalArgumentException("account is null");
1120 try {
1121 return mService.removeAccountExplicitly(account);
1122 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001123 throw e.rethrowFromSystemServer();
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001124 }
1125 }
1126
1127 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001128 * Removes an auth token from the AccountManager's cache. Does nothing if
1129 * the auth token is not currently in the cache. Applications must call this
1130 * method when the auth token is found to have expired or otherwise become
1131 * invalid for authenticating requests. The AccountManager does not validate
1132 * or expire cached auth tokens otherwise.
1133 *
1134 * <p>It is safe to call this method from the main thread.
1135 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001136 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1137 * MANAGE_ACCOUNTS or USE_CREDENTIALS permission is needed for those
1138 * platforms. See docs for this function in API level 22.
1139 *
Fred Quintanaf35b68f2010-04-01 11:36:00 -07001140 * @param accountType The account type of the auth token to invalidate, must not be null
1141 * @param authToken The auth token to invalidate, may be null
Dan Egnor661f0132010-02-19 11:23:00 -08001142 */
1143 public void invalidateAuthToken(final String accountType, final String authToken) {
Fred Quintana382601f2010-03-25 12:25:10 -07001144 if (accountType == null) throw new IllegalArgumentException("accountType is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001145 try {
Fred Quintanaf35b68f2010-04-01 11:36:00 -07001146 if (authToken != null) {
1147 mService.invalidateAuthToken(accountType, authToken);
1148 }
Dan Egnor661f0132010-02-19 11:23:00 -08001149 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001150 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001151 }
1152 }
1153
1154 /**
1155 * Gets an auth token from the AccountManager's cache. If no auth
1156 * token is cached for this account, null will be returned -- a new
1157 * auth token will not be generated, and the server will not be contacted.
1158 * Intended for use by the authenticator, not directly by applications.
1159 *
1160 * <p>It is safe to call this method from the main thread.
1161 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001162 * <p>This method requires the caller to have a signature match with the
1163 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001164 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001165 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1166 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1167 * is needed for those platforms. See docs for this function in API level 22.
1168 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001169 * @param account The account for which an auth token is to be fetched. Cannot be {@code null}.
Sandra Kwan0b84b452016-01-20 15:25:42 -08001170 * @param authTokenType The type of auth token to fetch. Cannot be {@code null}.
Dan Egnor661f0132010-02-19 11:23:00 -08001171 * @return The cached auth token for this account and type, or null if
1172 * no auth token is cached or the account does not exist.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001173 * @see #getAuthToken
Dan Egnor661f0132010-02-19 11:23:00 -08001174 */
1175 public String peekAuthToken(final Account account, final String authTokenType) {
Fred Quintana382601f2010-03-25 12:25:10 -07001176 if (account == null) throw new IllegalArgumentException("account is null");
1177 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001178 try {
1179 return mService.peekAuthToken(account, authTokenType);
1180 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001181 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001182 }
1183 }
1184
1185 /**
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -07001186 * Sets or forgets a saved password. This modifies the local copy of the
1187 * password used to automatically authenticate the user; it does not change
1188 * the user's account password on the server. Intended for use by the
1189 * authenticator, not directly by applications.
1190 * <p>Calling this method does not update the last authenticated timestamp,
1191 * referred by {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
1192 * {@link #notifyAccountAuthenticated(Account)} after getting success.
Dan Egnor661f0132010-02-19 11:23:00 -08001193 * <p>It is safe to call this method from the main thread.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001194 * <p>This method requires the caller to have a signature match with the
1195 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001196 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001197 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1198 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1199 * is needed for those platforms. See docs for this function in API level 22.
1200 *
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -07001201 * @param account The account whose password is to be set. Cannot be
1202 * {@code null}.
Dan Egnor661f0132010-02-19 11:23:00 -08001203 * @param password The password to set, null to clear the password
1204 */
1205 public void setPassword(final Account account, final String password) {
Fred Quintana382601f2010-03-25 12:25:10 -07001206 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001207 try {
1208 mService.setPassword(account, password);
1209 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001210 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001211 }
1212 }
1213
1214 /**
1215 * Forgets a saved password. This erases the local copy of the password;
1216 * it does not change the user's account password on the server.
1217 * Has the same effect as setPassword(account, null) but requires fewer
1218 * permissions, and may be used by applications or management interfaces
1219 * to "sign out" from an account.
1220 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001221 * <p>This method only successfully clear the account's password when the
1222 * caller has the same signature as the authenticator that owns the
1223 * specified account. Otherwise, this method will silently fail.
Dan Egnor661f0132010-02-19 11:23:00 -08001224 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001225 * <p>It is safe to call this method from the main thread.
Carlos Valdiviadcddc472015-06-11 20:04:04 +00001226 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001227 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1228 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
1229 * this function in API level 22.
1230 *
Dan Egnor661f0132010-02-19 11:23:00 -08001231 * @param account The account whose password to clear
1232 */
1233 public void clearPassword(final Account account) {
Fred Quintana382601f2010-03-25 12:25:10 -07001234 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001235 try {
1236 mService.clearPassword(account);
1237 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001238 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001239 }
1240 }
1241
1242 /**
1243 * Sets one userdata key for an account. Intended by use for the
1244 * authenticator to stash state for itself, not directly by applications.
1245 * The meaning of the keys and values is up to the authenticator.
1246 *
1247 * <p>It is safe to call this method from the main thread.
1248 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001249 * <p>This method requires the caller to have a signature match with the
1250 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001251 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001252 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1253 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1254 * is needed for those platforms. See docs for this function in API level 22.
1255 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001256 * @param account Account whose user data is to be set. Must not be {@code null}.
1257 * @param key String user data key to set. Must not be null
1258 * @param value String value to set, {@code null} to clear this user data key
Dan Egnor661f0132010-02-19 11:23:00 -08001259 */
1260 public void setUserData(final Account account, final String key, final String value) {
Fred Quintana382601f2010-03-25 12:25:10 -07001261 if (account == null) throw new IllegalArgumentException("account is null");
1262 if (key == null) throw new IllegalArgumentException("key is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001263 try {
1264 mService.setUserData(account, key, value);
1265 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001266 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001267 }
1268 }
1269
1270 /**
1271 * Adds an auth token to the AccountManager cache for an account.
1272 * If the account does not exist then this call has no effect.
1273 * Replaces any previous auth token for this account and auth token type.
1274 * Intended for use by the authenticator, not directly by applications.
1275 *
1276 * <p>It is safe to call this method from the main thread.
1277 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001278 * <p>This method requires the caller to have a signature match with the
1279 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001280 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001281 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1282 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1283 * is needed for those platforms. See docs for this function in API level 22.
1284 *
Dan Egnor661f0132010-02-19 11:23:00 -08001285 * @param account The account to set an auth token for
1286 * @param authTokenType The type of the auth token, see {#getAuthToken}
1287 * @param authToken The auth token to add to the cache
1288 */
1289 public void setAuthToken(Account account, final String authTokenType, final String authToken) {
Fred Quintana382601f2010-03-25 12:25:10 -07001290 if (account == null) throw new IllegalArgumentException("account is null");
1291 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001292 try {
1293 mService.setAuthToken(account, authTokenType, authToken);
1294 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001295 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001296 }
1297 }
1298
1299 /**
1300 * This convenience helper synchronously gets an auth token with
1301 * {@link #getAuthToken(Account, String, boolean, AccountManagerCallback, Handler)}.
1302 *
1303 * <p>This method may block while a network request completes, and must
1304 * never be made from the main thread.
1305 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001306 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1307 * USE_CREDENTIALS permission is needed for those platforms. See docs for
1308 * this function in API level 22.
1309 *
Dan Egnor661f0132010-02-19 11:23:00 -08001310 * @param account The account to fetch an auth token for
Joe Malinb6a35262013-06-03 09:49:04 -07001311 * @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()}
Dan Egnor661f0132010-02-19 11:23:00 -08001312 * @param notifyAuthFailure If true, display a notification and return null
1313 * if authentication fails; if false, prompt and wait for the user to
1314 * re-enter correct credentials before returning
1315 * @return An auth token of the specified type for this account, or null
1316 * if authentication fails or none can be fetched.
1317 * @throws AuthenticatorException if the authenticator failed to respond
1318 * @throws OperationCanceledException if the request was canceled for any
1319 * reason, including the user canceling a credential request
1320 * @throws java.io.IOException if the authenticator experienced an I/O problem
1321 * creating a new auth token, usually because of network trouble
1322 */
1323 public String blockingGetAuthToken(Account account, String authTokenType,
1324 boolean notifyAuthFailure)
1325 throws OperationCanceledException, IOException, AuthenticatorException {
Fred Quintana382601f2010-03-25 12:25:10 -07001326 if (account == null) throw new IllegalArgumentException("account is null");
1327 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001328 Bundle bundle = getAuthToken(account, authTokenType, notifyAuthFailure, null /* callback */,
1329 null /* handler */).getResult();
Fred Quintana96580e02010-03-04 13:42:42 -08001330 if (bundle == null) {
1331 // This should never happen, but it does, occasionally. If it does return null to
1332 // signify that we were not able to get the authtoken.
1333 // TODO: remove this when the bug is found that sometimes causes a null bundle to be
1334 // returned
1335 Log.e(TAG, "blockingGetAuthToken: null was returned from getResult() for "
1336 + account + ", authTokenType " + authTokenType);
1337 return null;
1338 }
Dan Egnor661f0132010-02-19 11:23:00 -08001339 return bundle.getString(KEY_AUTHTOKEN);
1340 }
1341
1342 /**
1343 * Gets an auth token of the specified type for a particular account,
1344 * prompting the user for credentials if necessary. This method is
1345 * intended for applications running in the foreground where it makes
1346 * sense to ask the user directly for a password.
1347 *
1348 * <p>If a previously generated auth token is cached for this account and
Dan Egnor8e4378b2010-08-02 18:22:09 -07001349 * type, then it is returned. Otherwise, if a saved password is
1350 * available, it is sent to the server to generate a new auth token.
1351 * Otherwise, the user is prompted to enter a password.
Dan Egnor661f0132010-02-19 11:23:00 -08001352 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001353 * <p>Some authenticators have auth token <em>types</em>, whose value
1354 * is authenticator-dependent. Some services use different token types to
1355 * access different functionality -- for example, Google uses different auth
1356 * tokens to access Gmail and Google Calendar for the same account.
Dan Egnor661f0132010-02-19 11:23:00 -08001357 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001358 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
Sandra Kwan0b84b452016-01-20 15:25:42 -08001359 * USE_CREDENTIALS permission is needed for those platforms. See docs for
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001360 * this function in API level 22.
1361 *
Dan Egnor661f0132010-02-19 11:23:00 -08001362 * <p>This method may be called from any thread, but the returned
1363 * {@link AccountManagerFuture} must not be used on the main thread.
1364 *
Dan Egnor661f0132010-02-19 11:23:00 -08001365 * @param account The account to fetch an auth token for
1366 * @param authTokenType The auth token type, an authenticator-dependent
1367 * string token, must not be null
1368 * @param options Authenticator-specific options for the request,
1369 * may be null or empty
1370 * @param activity The {@link Activity} context to use for launching a new
1371 * authenticator-defined sub-Activity to prompt the user for a password
1372 * if necessary; used only to call startActivity(); must not be null.
1373 * @param callback Callback to invoke when the request completes,
1374 * null for no callback
1375 * @param handler {@link Handler} identifying the callback thread,
1376 * null for the main thread
1377 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
1378 * at least the following fields:
Fred Quintana756b7352009-10-21 13:43:10 -07001379 * <ul>
Dan Egnor661f0132010-02-19 11:23:00 -08001380 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account you supplied
1381 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1382 * <li> {@link #KEY_AUTHTOKEN} - the auth token you wanted
Fred Quintana756b7352009-10-21 13:43:10 -07001383 * </ul>
Dan Egnor661f0132010-02-19 11:23:00 -08001384 *
1385 * (Other authenticator-specific values may be returned.) If an auth token
1386 * could not be fetched, {@link AccountManagerFuture#getResult()} throws:
1387 * <ul>
1388 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1389 * <li> {@link OperationCanceledException} if the operation is canceled for
1390 * any reason, incluidng the user canceling a credential request
1391 * <li> {@link IOException} if the authenticator experienced an I/O problem
1392 * creating a new auth token, usually because of network trouble
1393 * </ul>
Dan Egnor8e4378b2010-08-02 18:22:09 -07001394 * If the account is no longer present on the device, the return value is
1395 * authenticator-dependent. The caller should verify the validity of the
1396 * account before requesting an auth token.
Dan Egnor661f0132010-02-19 11:23:00 -08001397 */
1398 public AccountManagerFuture<Bundle> getAuthToken(
1399 final Account account, final String authTokenType, final Bundle options,
1400 final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07001401 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001402 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Costin Manolachee5847ad2011-09-14 12:52:19 -07001403 final Bundle optionsIn = new Bundle();
1404 if (options != null) {
1405 optionsIn.putAll(options);
1406 }
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001407 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
Dan Egnor661f0132010-02-19 11:23:00 -08001408 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001409 @Override
Dan Egnor661f0132010-02-19 11:23:00 -08001410 public void doWork() throws RemoteException {
1411 mService.getAuthToken(mResponse, account, authTokenType,
1412 false /* notifyOnAuthFailure */, true /* expectActivityLaunch */,
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001413 optionsIn);
Dan Egnor661f0132010-02-19 11:23:00 -08001414 }
1415 }.start();
1416 }
1417
1418 /**
1419 * Gets an auth token of the specified type for a particular account,
1420 * optionally raising a notification if the user must enter credentials.
1421 * This method is intended for background tasks and services where the
1422 * user should not be immediately interrupted with a password prompt.
1423 *
1424 * <p>If a previously generated auth token is cached for this account and
Dan Egnor8e4378b2010-08-02 18:22:09 -07001425 * type, then it is returned. Otherwise, if a saved password is
1426 * available, it is sent to the server to generate a new auth token.
1427 * Otherwise, an {@link Intent} is returned which, when started, will
1428 * prompt the user for a password. If the notifyAuthFailure parameter is
1429 * set, a status bar notification is also created with the same Intent,
Dan Egnor661f0132010-02-19 11:23:00 -08001430 * alerting the user that they need to enter a password at some point.
1431 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001432 * <p>In that case, you may need to wait until the user responds, which
1433 * could take hours or days or forever. When the user does respond and
1434 * supply a new password, the account manager will broadcast the
1435 * {@link #LOGIN_ACCOUNTS_CHANGED_ACTION} Intent, which applications can
1436 * use to try again.
Dan Egnor661f0132010-02-19 11:23:00 -08001437 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001438 * <p>If notifyAuthFailure is not set, it is the application's
1439 * responsibility to launch the returned Intent at some point.
1440 * Either way, the result from this call will not wait for user action.
Dan Egnor661f0132010-02-19 11:23:00 -08001441 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001442 * <p>Some authenticators have auth token <em>types</em>, whose value
1443 * is authenticator-dependent. Some services use different token types to
1444 * access different functionality -- for example, Google uses different auth
1445 * tokens to access Gmail and Google Calendar for the same account.
Dan Egnor661f0132010-02-19 11:23:00 -08001446 *
1447 * <p>This method may be called from any thread, but the returned
1448 * {@link AccountManagerFuture} must not be used on the main thread.
1449 *
Dan Egnor661f0132010-02-19 11:23:00 -08001450 * @param account The account to fetch an auth token for
1451 * @param authTokenType The auth token type, an authenticator-dependent
1452 * string token, must not be null
Dan Egnor661f0132010-02-19 11:23:00 -08001453 * @param notifyAuthFailure True to add a notification to prompt the
1454 * user for a password if necessary, false to leave that to the caller
1455 * @param callback Callback to invoke when the request completes,
1456 * null for no callback
1457 * @param handler {@link Handler} identifying the callback thread,
1458 * null for the main thread
1459 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
1460 * at least the following fields on success:
1461 * <ul>
1462 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account you supplied
1463 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1464 * <li> {@link #KEY_AUTHTOKEN} - the auth token you wanted
1465 * </ul>
1466 *
1467 * (Other authenticator-specific values may be returned.) If the user
1468 * must enter credentials, the returned Bundle contains only
1469 * {@link #KEY_INTENT} with the {@link Intent} needed to launch a prompt.
1470 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001471 * If an error occurred, {@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08001472 * <ul>
1473 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1474 * <li> {@link OperationCanceledException} if the operation is canceled for
1475 * any reason, incluidng the user canceling a credential request
1476 * <li> {@link IOException} if the authenticator experienced an I/O problem
1477 * creating a new auth token, usually because of network trouble
1478 * </ul>
Dan Egnor8e4378b2010-08-02 18:22:09 -07001479 * If the account is no longer present on the device, the return value is
1480 * authenticator-dependent. The caller should verify the validity of the
1481 * account before requesting an auth token.
Fred Quintanaad93a322011-09-08 13:21:01 -07001482 * @deprecated use {@link #getAuthToken(Account, String, android.os.Bundle,
1483 * boolean, AccountManagerCallback, android.os.Handler)} instead
Dan Egnor661f0132010-02-19 11:23:00 -08001484 */
Fred Quintanaad93a322011-09-08 13:21:01 -07001485 @Deprecated
Dan Egnor661f0132010-02-19 11:23:00 -08001486 public AccountManagerFuture<Bundle> getAuthToken(
Jatin Lodhia3df7d692013-03-27 10:57:23 -07001487 final Account account, final String authTokenType,
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001488 final boolean notifyAuthFailure,
Dan Egnor661f0132010-02-19 11:23:00 -08001489 AccountManagerCallback<Bundle> callback, Handler handler) {
Jatin Lodhia3df7d692013-03-27 10:57:23 -07001490 return getAuthToken(account, authTokenType, null, notifyAuthFailure, callback,
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001491 handler);
Dan Egnor661f0132010-02-19 11:23:00 -08001492 }
1493
1494 /**
Fred Quintanaad93a322011-09-08 13:21:01 -07001495 * Gets an auth token of the specified type for a particular account,
1496 * optionally raising a notification if the user must enter credentials.
1497 * This method is intended for background tasks and services where the
1498 * user should not be immediately interrupted with a password prompt.
1499 *
1500 * <p>If a previously generated auth token is cached for this account and
1501 * type, then it is returned. Otherwise, if a saved password is
1502 * available, it is sent to the server to generate a new auth token.
1503 * Otherwise, an {@link Intent} is returned which, when started, will
1504 * prompt the user for a password. If the notifyAuthFailure parameter is
1505 * set, a status bar notification is also created with the same Intent,
1506 * alerting the user that they need to enter a password at some point.
1507 *
1508 * <p>In that case, you may need to wait until the user responds, which
1509 * could take hours or days or forever. When the user does respond and
1510 * supply a new password, the account manager will broadcast the
1511 * {@link #LOGIN_ACCOUNTS_CHANGED_ACTION} Intent, which applications can
1512 * use to try again.
1513 *
1514 * <p>If notifyAuthFailure is not set, it is the application's
1515 * responsibility to launch the returned Intent at some point.
1516 * Either way, the result from this call will not wait for user action.
1517 *
1518 * <p>Some authenticators have auth token <em>types</em>, whose value
1519 * is authenticator-dependent. Some services use different token types to
1520 * access different functionality -- for example, Google uses different auth
1521 * tokens to access Gmail and Google Calendar for the same account.
1522 *
1523 * <p>This method may be called from any thread, but the returned
1524 * {@link AccountManagerFuture} must not be used on the main thread.
1525 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001526 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
Sandra Kwan0b84b452016-01-20 15:25:42 -08001527 * USE_CREDENTIALS permission is needed for those platforms. See docs for
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001528 * this function in API level 22.
1529 *
Fred Quintanaad93a322011-09-08 13:21:01 -07001530 * @param account The account to fetch an auth token for
1531 * @param authTokenType The auth token type, an authenticator-dependent
1532 * string token, must not be null
1533 * @param options Authenticator-specific options for the request,
1534 * may be null or empty
1535 * @param notifyAuthFailure True to add a notification to prompt the
1536 * user for a password if necessary, false to leave that to the caller
1537 * @param callback Callback to invoke when the request completes,
1538 * null for no callback
1539 * @param handler {@link Handler} identifying the callback thread,
1540 * null for the main thread
1541 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
1542 * at least the following fields on success:
1543 * <ul>
1544 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account you supplied
1545 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1546 * <li> {@link #KEY_AUTHTOKEN} - the auth token you wanted
1547 * </ul>
1548 *
1549 * (Other authenticator-specific values may be returned.) If the user
1550 * must enter credentials, the returned Bundle contains only
1551 * {@link #KEY_INTENT} with the {@link Intent} needed to launch a prompt.
1552 *
1553 * If an error occurred, {@link AccountManagerFuture#getResult()} throws:
1554 * <ul>
1555 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1556 * <li> {@link OperationCanceledException} if the operation is canceled for
1557 * any reason, incluidng the user canceling a credential request
1558 * <li> {@link IOException} if the authenticator experienced an I/O problem
1559 * creating a new auth token, usually because of network trouble
1560 * </ul>
1561 * If the account is no longer present on the device, the return value is
1562 * authenticator-dependent. The caller should verify the validity of the
1563 * account before requesting an auth token.
1564 */
1565 public AccountManagerFuture<Bundle> getAuthToken(
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001566 final Account account, final String authTokenType, final Bundle options,
1567 final boolean notifyAuthFailure,
Fred Quintanaad93a322011-09-08 13:21:01 -07001568 AccountManagerCallback<Bundle> callback, Handler handler) {
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001569
Fred Quintanaad93a322011-09-08 13:21:01 -07001570 if (account == null) throw new IllegalArgumentException("account is null");
1571 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Costin Manolachee5847ad2011-09-14 12:52:19 -07001572 final Bundle optionsIn = new Bundle();
1573 if (options != null) {
1574 optionsIn.putAll(options);
1575 }
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001576 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
Fred Quintanaad93a322011-09-08 13:21:01 -07001577 return new AmsTask(null, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001578 @Override
Fred Quintanaad93a322011-09-08 13:21:01 -07001579 public void doWork() throws RemoteException {
1580 mService.getAuthToken(mResponse, account, authTokenType,
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001581 notifyAuthFailure, false /* expectActivityLaunch */, optionsIn);
Fred Quintanaad93a322011-09-08 13:21:01 -07001582 }
1583 }.start();
1584 }
1585
1586 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001587 * Asks the user to add an account of a specified type. The authenticator
1588 * for this account type processes this request with the appropriate user
1589 * interface. If the user does elect to create a new account, the account
1590 * name is returned.
1591 *
1592 * <p>This method may be called from any thread, but the returned
1593 * {@link AccountManagerFuture} must not be used on the main thread.
Sandra Kwan0b84b452016-01-20 15:25:42 -08001594 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001595 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1596 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
1597 * this function in API level 22.
Dan Egnor661f0132010-02-19 11:23:00 -08001598 *
Dan Egnor661f0132010-02-19 11:23:00 -08001599 * @param accountType The type of account to add; must not be null
1600 * @param authTokenType The type of auth token (see {@link #getAuthToken})
1601 * this account will need to be able to generate, null for none
1602 * @param requiredFeatures The features (see {@link #hasFeatures}) this
1603 * account must have, null for none
1604 * @param addAccountOptions Authenticator-specific options for the request,
1605 * may be null or empty
1606 * @param activity The {@link Activity} context to use for launching a new
1607 * authenticator-defined sub-Activity to prompt the user to create an
1608 * account; used only to call startActivity(); if null, the prompt
1609 * will not be launched directly, but the necessary {@link Intent}
1610 * will be returned to the caller instead
1611 * @param callback Callback to invoke when the request completes,
1612 * null for no callback
1613 * @param handler {@link Handler} identifying the callback thread,
1614 * null for the main thread
Doug Zongkerff592dc2010-02-23 12:26:33 -08001615 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
Dan Egnor661f0132010-02-19 11:23:00 -08001616 * these fields if activity was specified and an account was created:
1617 * <ul>
1618 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account created
1619 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1620 * </ul>
1621 *
1622 * If no activity was specified, the returned Bundle contains only
1623 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
Dan Egnor8e4378b2010-08-02 18:22:09 -07001624 * actual account creation process. If an error occurred,
1625 * {@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08001626 * <ul>
1627 * <li> {@link AuthenticatorException} if no authenticator was registered for
1628 * this account type or the authenticator failed to respond
1629 * <li> {@link OperationCanceledException} if the operation was canceled for
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001630 * any reason, including the user canceling the creation process or adding accounts
1631 * (of this type) has been disabled by policy
Dan Egnor661f0132010-02-19 11:23:00 -08001632 * <li> {@link IOException} if the authenticator experienced an I/O problem
1633 * creating a new account, usually because of network trouble
1634 * </ul>
1635 */
1636 public AccountManagerFuture<Bundle> addAccount(final String accountType,
1637 final String authTokenType, final String[] requiredFeatures,
1638 final Bundle addAccountOptions,
1639 final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07001640 if (accountType == null) throw new IllegalArgumentException("accountType is null");
Costin Manolachee5847ad2011-09-14 12:52:19 -07001641 final Bundle optionsIn = new Bundle();
1642 if (addAccountOptions != null) {
1643 optionsIn.putAll(addAccountOptions);
1644 }
1645 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001646
Dan Egnor661f0132010-02-19 11:23:00 -08001647 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001648 @Override
Dan Egnor661f0132010-02-19 11:23:00 -08001649 public void doWork() throws RemoteException {
Amith Yamasani27db4682013-03-30 17:07:47 -07001650 mService.addAccount(mResponse, accountType, authTokenType,
Costin Manolachee5847ad2011-09-14 12:52:19 -07001651 requiredFeatures, activity != null, optionsIn);
Dan Egnor661f0132010-02-19 11:23:00 -08001652 }
1653 }.start();
1654 }
1655
1656 /**
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001657 * @see #addAccount(String, String, String[], Bundle, Activity, AccountManagerCallback, Handler)
1658 * @hide
1659 */
1660 public AccountManagerFuture<Bundle> addAccountAsUser(final String accountType,
1661 final String authTokenType, final String[] requiredFeatures,
1662 final Bundle addAccountOptions, final Activity activity,
1663 AccountManagerCallback<Bundle> callback, Handler handler, final UserHandle userHandle) {
1664 if (accountType == null) throw new IllegalArgumentException("accountType is null");
1665 if (userHandle == null) throw new IllegalArgumentException("userHandle is null");
1666 final Bundle optionsIn = new Bundle();
1667 if (addAccountOptions != null) {
1668 optionsIn.putAll(addAccountOptions);
1669 }
1670 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
1671
1672 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001673 @Override
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001674 public void doWork() throws RemoteException {
1675 mService.addAccountAsUser(mResponse, accountType, authTokenType,
1676 requiredFeatures, activity != null, optionsIn, userHandle.getIdentifier());
1677 }
1678 }.start();
1679 }
1680
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001681
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001682 /**
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001683 * Adds shared accounts from a parent user to a secondary user. Adding the shared account
Amith Yamasani67df64b2012-12-14 12:09:36 -08001684 * doesn't take effect immediately. When the target user starts up, any pending shared accounts
1685 * are attempted to be copied to the target user from the primary via calls to the
1686 * authenticator.
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001687 * @param parentUser parent user
1688 * @param user target user
Amith Yamasani67df64b2012-12-14 12:09:36 -08001689 * @hide
1690 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001691 public void addSharedAccountsFromParentUser(UserHandle parentUser, UserHandle user) {
Amith Yamasani67df64b2012-12-14 12:09:36 -08001692 try {
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001693 mService.addSharedAccountsFromParentUser(parentUser.getIdentifier(),
1694 user.getIdentifier());
Amith Yamasani67df64b2012-12-14 12:09:36 -08001695 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001696 throw re.rethrowFromSystemServer();
Amith Yamasani67df64b2012-12-14 12:09:36 -08001697 }
1698 }
1699
1700 /**
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001701 * Copies an account from one user to another user.
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001702 * @param account the account to copy
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001703 * @param fromUser the user to copy the account from
1704 * @param toUser the target user
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001705 * @param callback Callback to invoke when the request completes,
1706 * null for no callback
1707 * @param handler {@link Handler} identifying the callback thread,
1708 * null for the main thread
1709 * @return An {@link AccountManagerFuture} which resolves to a Boolean indicated wether it
1710 * succeeded.
1711 * @hide
1712 */
1713 public AccountManagerFuture<Boolean> copyAccountToUser(
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001714 final Account account, final UserHandle fromUser, final UserHandle toUser,
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001715 AccountManagerCallback<Boolean> callback, Handler handler) {
1716 if (account == null) throw new IllegalArgumentException("account is null");
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001717 if (toUser == null || fromUser == null) {
1718 throw new IllegalArgumentException("fromUser and toUser cannot be null");
1719 }
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001720
1721 return new Future2Task<Boolean>(handler, callback) {
1722 @Override
1723 public void doWork() throws RemoteException {
1724 mService.copyAccountToUser(
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001725 mResponse, account, fromUser.getIdentifier(), toUser.getIdentifier());
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001726 }
1727 @Override
1728 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
1729 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
1730 throw new AuthenticatorException("no result in response");
1731 }
1732 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
1733 }
1734 }.start();
1735 }
1736
1737 /**
Amith Yamasani67df64b2012-12-14 12:09:36 -08001738 * @hide
1739 * Removes the shared account.
1740 * @param account the account to remove
1741 * @param user the user to remove the account from
1742 * @return
1743 */
1744 public boolean removeSharedAccount(final Account account, UserHandle user) {
1745 try {
1746 boolean val = mService.removeSharedAccountAsUser(account, user.getIdentifier());
1747 return val;
1748 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001749 throw re.rethrowFromSystemServer();
Amith Yamasani67df64b2012-12-14 12:09:36 -08001750 }
1751 }
1752
1753 /**
1754 * @hide
1755 * @param user
1756 * @return
1757 */
1758 public Account[] getSharedAccounts(UserHandle user) {
1759 try {
1760 return mService.getSharedAccountsAsUser(user.getIdentifier());
1761 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001762 throw re.rethrowFromSystemServer();
Amith Yamasani67df64b2012-12-14 12:09:36 -08001763 }
1764 }
1765
1766 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001767 * Confirms that the user knows the password for an account to make extra
1768 * sure they are the owner of the account. The user-entered password can
1769 * be supplied directly, otherwise the authenticator for this account type
1770 * prompts the user with the appropriate interface. This method is
1771 * intended for applications which want extra assurance; for example, the
1772 * phone lock screen uses this to let the user unlock the phone with an
1773 * account password if they forget the lock pattern.
1774 *
1775 * <p>If the user-entered password matches a saved password for this
1776 * account, the request is considered valid; otherwise the authenticator
1777 * verifies the password (usually by contacting the server).
1778 *
1779 * <p>This method may be called from any thread, but the returned
1780 * {@link AccountManagerFuture} must not be used on the main thread.
1781 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001782 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1783 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs
1784 * for this function in API level 22.
1785 *
Dan Egnor661f0132010-02-19 11:23:00 -08001786 * @param account The account to confirm password knowledge for
1787 * @param options Authenticator-specific options for the request;
1788 * if the {@link #KEY_PASSWORD} string field is present, the
1789 * authenticator may use it directly rather than prompting the user;
1790 * may be null or empty
1791 * @param activity The {@link Activity} context to use for launching a new
1792 * authenticator-defined sub-Activity to prompt the user to enter a
1793 * password; used only to call startActivity(); if null, the prompt
1794 * will not be launched directly, but the necessary {@link Intent}
1795 * will be returned to the caller instead
1796 * @param callback Callback to invoke when the request completes,
1797 * null for no callback
1798 * @param handler {@link Handler} identifying the callback thread,
1799 * null for the main thread
1800 * @return An {@link AccountManagerFuture} which resolves to a Bundle
1801 * with these fields if activity or password was supplied and
1802 * the account was successfully verified:
1803 * <ul>
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001804 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account verified
Dan Egnor661f0132010-02-19 11:23:00 -08001805 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1806 * <li> {@link #KEY_BOOLEAN_RESULT} - true to indicate success
1807 * </ul>
1808 *
1809 * If no activity or password was specified, the returned Bundle contains
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001810 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
1811 * password prompt.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001812 *
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001813 * <p>Also the returning Bundle may contain {@link
Simranjit Singh Kohli1663b442015-04-28 11:11:12 -07001814 * #KEY_LAST_AUTHENTICATED_TIME} indicating the last time the
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001815 * credential was validated/created.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001816 *
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001817 * If an error occurred,{@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08001818 * <ul>
1819 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1820 * <li> {@link OperationCanceledException} if the operation was canceled for
1821 * any reason, including the user canceling the password prompt
1822 * <li> {@link IOException} if the authenticator experienced an I/O problem
1823 * verifying the password, usually because of network trouble
1824 * </ul>
Fred Quintana756b7352009-10-21 13:43:10 -07001825 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07001826 public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
1827 final Bundle options,
1828 final Activity activity,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07001829 final AccountManagerCallback<Bundle> callback,
Fred Quintanaa698f422009-04-08 19:14:54 -07001830 final Handler handler) {
Amith Yamasani2c7bc262012-11-05 16:46:02 -08001831 return confirmCredentialsAsUser(account, options, activity, callback, handler,
1832 Process.myUserHandle());
1833 }
1834
1835 /**
1836 * @hide
1837 * Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)}
1838 * but for the specified user.
1839 */
1840 public AccountManagerFuture<Bundle> confirmCredentialsAsUser(final Account account,
1841 final Bundle options,
1842 final Activity activity,
1843 final AccountManagerCallback<Bundle> callback,
1844 final Handler handler, UserHandle userHandle) {
Fred Quintana382601f2010-03-25 12:25:10 -07001845 if (account == null) throw new IllegalArgumentException("account is null");
Amith Yamasani2c7bc262012-11-05 16:46:02 -08001846 final int userId = userHandle.getIdentifier();
Fred Quintanaa698f422009-04-08 19:14:54 -07001847 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001848 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07001849 public void doWork() throws RemoteException {
Amith Yamasani2c7bc262012-11-05 16:46:02 -08001850 mService.confirmCredentialsAsUser(mResponse, account, options, activity != null,
1851 userId);
Fred Quintanaa698f422009-04-08 19:14:54 -07001852 }
Fred Quintana33269202009-04-20 16:05:10 -07001853 }.start();
Fred Quintanaa698f422009-04-08 19:14:54 -07001854 }
1855
Fred Quintana756b7352009-10-21 13:43:10 -07001856 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001857 * Asks the user to enter a new password for an account, updating the
1858 * saved credentials for the account. Normally this happens automatically
1859 * when the server rejects credentials during an auth token fetch, but this
1860 * can be invoked directly to ensure we have the correct credentials stored.
Fred Quintana756b7352009-10-21 13:43:10 -07001861 *
Dan Egnor661f0132010-02-19 11:23:00 -08001862 * <p>This method may be called from any thread, but the returned
1863 * {@link AccountManagerFuture} must not be used on the main thread.
1864 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001865 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1866 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
1867 * this function in API level 22.
1868 *
Dan Egnor661f0132010-02-19 11:23:00 -08001869 * @param account The account to update credentials for
1870 * @param authTokenType The credentials entered must allow an auth token
1871 * of this type to be created (but no actual auth token is returned);
1872 * may be null
1873 * @param options Authenticator-specific options for the request;
1874 * may be null or empty
1875 * @param activity The {@link Activity} context to use for launching a new
1876 * authenticator-defined sub-Activity to prompt the user to enter a
1877 * password; used only to call startActivity(); if null, the prompt
1878 * will not be launched directly, but the necessary {@link Intent}
1879 * will be returned to the caller instead
1880 * @param callback Callback to invoke when the request completes,
1881 * null for no callback
1882 * @param handler {@link Handler} identifying the callback thread,
1883 * null for the main thread
1884 * @return An {@link AccountManagerFuture} which resolves to a Bundle
1885 * with these fields if an activity was supplied and the account
1886 * credentials were successfully updated:
Fred Quintana756b7352009-10-21 13:43:10 -07001887 * <ul>
Ian Pedowitz6cc066d2015-08-05 14:23:43 +00001888 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account
Dan Egnor661f0132010-02-19 11:23:00 -08001889 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
Fred Quintana756b7352009-10-21 13:43:10 -07001890 * </ul>
Dan Egnor661f0132010-02-19 11:23:00 -08001891 *
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001892 * If no activity was specified, the returned Bundle contains
Dan Egnor661f0132010-02-19 11:23:00 -08001893 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001894 * password prompt. If an error occurred,
Dan Egnor8e4378b2010-08-02 18:22:09 -07001895 * {@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08001896 * <ul>
1897 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1898 * <li> {@link OperationCanceledException} if the operation was canceled for
1899 * any reason, including the user canceling the password prompt
1900 * <li> {@link IOException} if the authenticator experienced an I/O problem
1901 * verifying the password, usually because of network trouble
1902 * </ul>
Fred Quintana756b7352009-10-21 13:43:10 -07001903 */
1904 public AccountManagerFuture<Bundle> updateCredentials(final Account account,
1905 final String authTokenType,
Fred Quintana31957f12009-10-21 13:43:10 -07001906 final Bundle options, final Activity activity,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07001907 final AccountManagerCallback<Bundle> callback,
Fred Quintanaa698f422009-04-08 19:14:54 -07001908 final Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07001909 if (account == null) throw new IllegalArgumentException("account is null");
Fred Quintanaa698f422009-04-08 19:14:54 -07001910 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001911 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07001912 public void doWork() throws RemoteException {
1913 mService.updateCredentials(mResponse, account, authTokenType, activity != null,
Fred Quintana31957f12009-10-21 13:43:10 -07001914 options);
Fred Quintanaa698f422009-04-08 19:14:54 -07001915 }
Fred Quintana33269202009-04-20 16:05:10 -07001916 }.start();
Fred Quintanaa698f422009-04-08 19:14:54 -07001917 }
1918
Fred Quintana756b7352009-10-21 13:43:10 -07001919 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001920 * Offers the user an opportunity to change an authenticator's settings.
1921 * These properties are for the authenticator in general, not a particular
1922 * account. Not all authenticators support this method.
Fred Quintana756b7352009-10-21 13:43:10 -07001923 *
Dan Egnor661f0132010-02-19 11:23:00 -08001924 * <p>This method may be called from any thread, but the returned
1925 * {@link AccountManagerFuture} must not be used on the main thread.
1926 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001927 * <p>This method requires the caller to have the same signature as the
1928 * authenticator associated with the specified account type.
Dan Egnor661f0132010-02-19 11:23:00 -08001929 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001930 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1931 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs
1932 * for this function in API level 22.
1933 *
Dan Egnor661f0132010-02-19 11:23:00 -08001934 * @param accountType The account type associated with the authenticator
1935 * to adjust
1936 * @param activity The {@link Activity} context to use for launching a new
1937 * authenticator-defined sub-Activity to adjust authenticator settings;
1938 * used only to call startActivity(); if null, the settings dialog will
1939 * not be launched directly, but the necessary {@link Intent} will be
1940 * returned to the caller instead
1941 * @param callback Callback to invoke when the request completes,
1942 * null for no callback
1943 * @param handler {@link Handler} identifying the callback thread,
1944 * null for the main thread
1945 * @return An {@link AccountManagerFuture} which resolves to a Bundle
1946 * which is empty if properties were edited successfully, or
1947 * if no activity was specified, contains only {@link #KEY_INTENT}
1948 * needed to launch the authenticator's settings dialog.
Dan Egnor8e4378b2010-08-02 18:22:09 -07001949 * If an error occurred, {@link AccountManagerFuture#getResult()}
1950 * throws:
Fred Quintana756b7352009-10-21 13:43:10 -07001951 * <ul>
Dan Egnor661f0132010-02-19 11:23:00 -08001952 * <li> {@link AuthenticatorException} if no authenticator was registered for
1953 * this account type or the authenticator failed to respond
1954 * <li> {@link OperationCanceledException} if the operation was canceled for
1955 * any reason, including the user canceling the settings dialog
1956 * <li> {@link IOException} if the authenticator experienced an I/O problem
1957 * updating settings, usually because of network trouble
Fred Quintana756b7352009-10-21 13:43:10 -07001958 * </ul>
Fred Quintana756b7352009-10-21 13:43:10 -07001959 */
1960 public AccountManagerFuture<Bundle> editProperties(final String accountType,
1961 final Activity activity, final AccountManagerCallback<Bundle> callback,
Fred Quintanaa698f422009-04-08 19:14:54 -07001962 final Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07001963 if (accountType == null) throw new IllegalArgumentException("accountType is null");
Fred Quintanaa698f422009-04-08 19:14:54 -07001964 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001965 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07001966 public void doWork() throws RemoteException {
1967 mService.editProperties(mResponse, accountType, activity != null);
1968 }
Fred Quintana33269202009-04-20 16:05:10 -07001969 }.start();
Fred Quintanaa698f422009-04-08 19:14:54 -07001970 }
1971
Amith Yamasani12747872015-12-07 14:19:49 -08001972 /**
1973 * @hide
1974 * Checks if the given account exists on any of the users on the device.
1975 * Only the system process can call this method.
1976 *
1977 * @param account The account to check for existence.
1978 * @return whether any user has this account
1979 */
1980 public boolean someUserHasAccount(@NonNull final Account account) {
1981 try {
1982 return mService.someUserHasAccount(account);
1983 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001984 throw re.rethrowFromSystemServer();
Amith Yamasani12747872015-12-07 14:19:49 -08001985 }
1986 }
1987
Fred Quintanaa698f422009-04-08 19:14:54 -07001988 private void ensureNotOnMainThread() {
1989 final Looper looper = Looper.myLooper();
1990 if (looper != null && looper == mContext.getMainLooper()) {
Fred Quintana53bd2522010-02-05 15:28:12 -08001991 final IllegalStateException exception = new IllegalStateException(
1992 "calling this from your main thread can lead to deadlock");
1993 Log.e(TAG, "calling this from your main thread can lead to deadlock and/or ANRs",
1994 exception);
Fred Quintana751fdc02010-02-09 14:13:18 -08001995 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO) {
1996 throw exception;
1997 }
Fred Quintana60307342009-03-24 22:48:12 -07001998 }
1999 }
2000
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002001 private void postToHandler(Handler handler, final AccountManagerCallback<Bundle> callback,
2002 final AccountManagerFuture<Bundle> future) {
Fred Quintanad9d2f112009-04-23 13:36:27 -07002003 handler = handler == null ? mMainHandler : handler;
2004 handler.post(new Runnable() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002005 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002006 public void run() {
2007 callback.run(future);
2008 }
2009 });
2010 }
Fred Quintana60307342009-03-24 22:48:12 -07002011
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002012 private void postToHandler(Handler handler, final OnAccountsUpdateListener listener,
Fred Quintanad9d2f112009-04-23 13:36:27 -07002013 final Account[] accounts) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002014 final Account[] accountsCopy = new Account[accounts.length];
2015 // send a copy to make sure that one doesn't
2016 // change what another sees
2017 System.arraycopy(accounts, 0, accountsCopy, 0, accountsCopy.length);
2018 handler = (handler == null) ? mMainHandler : handler;
Fred Quintanad9d2f112009-04-23 13:36:27 -07002019 handler.post(new Runnable() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002020 @Override
Fred Quintanad9d2f112009-04-23 13:36:27 -07002021 public void run() {
Hiroaki Kuriyama8d3e1592015-10-09 16:30:03 +02002022 synchronized (mAccountsUpdatedListeners) {
2023 try {
2024 if (mAccountsUpdatedListeners.containsKey(listener)) {
2025 listener.onAccountsUpdated(accountsCopy);
2026 }
2027 } catch (SQLException e) {
2028 // Better luck next time. If the problem was disk-full,
2029 // the STORAGE_OK intent will re-trigger the update.
2030 Log.e(TAG, "Can't update accounts", e);
2031 }
Costin Manolacheb6437242009-09-10 16:14:12 -07002032 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002033 }
2034 });
2035 }
2036
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002037 private abstract class AmsTask extends FutureTask<Bundle> implements AccountManagerFuture<Bundle> {
Fred Quintanaa698f422009-04-08 19:14:54 -07002038 final IAccountManagerResponse mResponse;
2039 final Handler mHandler;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002040 final AccountManagerCallback<Bundle> mCallback;
Fred Quintanaa698f422009-04-08 19:14:54 -07002041 final Activity mActivity;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002042 public AmsTask(Activity activity, Handler handler, AccountManagerCallback<Bundle> callback) {
Fred Quintanaa698f422009-04-08 19:14:54 -07002043 super(new Callable<Bundle>() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002044 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002045 public Bundle call() throws Exception {
2046 throw new IllegalStateException("this should never be called");
2047 }
2048 });
2049
2050 mHandler = handler;
2051 mCallback = callback;
2052 mActivity = activity;
2053 mResponse = new Response();
Fred Quintana33269202009-04-20 16:05:10 -07002054 }
2055
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002056 public final AccountManagerFuture<Bundle> start() {
2057 try {
2058 doWork();
2059 } catch (RemoteException e) {
2060 setException(e);
2061 }
Fred Quintana33269202009-04-20 16:05:10 -07002062 return this;
Fred Quintana60307342009-03-24 22:48:12 -07002063 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002064
Sandra Kwan0b84b452016-01-20 15:25:42 -08002065 @Override
Fred Quintana96580e02010-03-04 13:42:42 -08002066 protected void set(Bundle bundle) {
2067 // TODO: somehow a null is being set as the result of the Future. Log this
2068 // case to help debug where this is occurring. When this bug is fixed this
2069 // condition statement should be removed.
2070 if (bundle == null) {
2071 Log.e(TAG, "the bundle must not be null", new Exception());
2072 }
2073 super.set(bundle);
2074 }
2075
Fred Quintanaa698f422009-04-08 19:14:54 -07002076 public abstract void doWork() throws RemoteException;
2077
2078 private Bundle internalGetResult(Long timeout, TimeUnit unit)
2079 throws OperationCanceledException, IOException, AuthenticatorException {
Fred Quintana53bd2522010-02-05 15:28:12 -08002080 if (!isDone()) {
2081 ensureNotOnMainThread();
2082 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002083 try {
2084 if (timeout == null) {
2085 return get();
2086 } else {
2087 return get(timeout, unit);
2088 }
2089 } catch (CancellationException e) {
2090 throw new OperationCanceledException();
2091 } catch (TimeoutException e) {
2092 // fall through and cancel
2093 } catch (InterruptedException e) {
2094 // fall through and cancel
2095 } catch (ExecutionException e) {
2096 final Throwable cause = e.getCause();
2097 if (cause instanceof IOException) {
2098 throw (IOException) cause;
2099 } else if (cause instanceof UnsupportedOperationException) {
2100 throw new AuthenticatorException(cause);
2101 } else if (cause instanceof AuthenticatorException) {
2102 throw (AuthenticatorException) cause;
2103 } else if (cause instanceof RuntimeException) {
2104 throw (RuntimeException) cause;
2105 } else if (cause instanceof Error) {
2106 throw (Error) cause;
2107 } else {
2108 throw new IllegalStateException(cause);
2109 }
2110 } finally {
2111 cancel(true /* interrupt if running */);
2112 }
2113 throw new OperationCanceledException();
2114 }
2115
Sandra Kwan0b84b452016-01-20 15:25:42 -08002116 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002117 public Bundle getResult()
2118 throws OperationCanceledException, IOException, AuthenticatorException {
2119 return internalGetResult(null, null);
2120 }
2121
Sandra Kwan0b84b452016-01-20 15:25:42 -08002122 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002123 public Bundle getResult(long timeout, TimeUnit unit)
2124 throws OperationCanceledException, IOException, AuthenticatorException {
2125 return internalGetResult(timeout, unit);
2126 }
2127
Sandra Kwan0b84b452016-01-20 15:25:42 -08002128 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002129 protected void done() {
2130 if (mCallback != null) {
2131 postToHandler(mHandler, mCallback, this);
2132 }
2133 }
2134
2135 /** Handles the responses from the AccountManager */
2136 private class Response extends IAccountManagerResponse.Stub {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002137 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002138 public void onResult(Bundle bundle) {
Brian Carlstrom46703b02011-04-06 15:41:29 -07002139 Intent intent = bundle.getParcelable(KEY_INTENT);
Fred Quintanaa698f422009-04-08 19:14:54 -07002140 if (intent != null && mActivity != null) {
2141 // since the user provided an Activity we will silently start intents
2142 // that we see
2143 mActivity.startActivity(intent);
2144 // leave the Future running to wait for the real response to this request
Fred Quintanad4a1d2e2009-07-16 16:36:38 -07002145 } else if (bundle.getBoolean("retry")) {
2146 try {
2147 doWork();
2148 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07002149 throw e.rethrowFromSystemServer();
Fred Quintanad4a1d2e2009-07-16 16:36:38 -07002150 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002151 } else {
2152 set(bundle);
2153 }
2154 }
2155
Sandra Kwan0b84b452016-01-20 15:25:42 -08002156 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002157 public void onError(int code, String message) {
Alexandra Gherghina999d3942014-07-03 11:40:08 +01002158 if (code == ERROR_CODE_CANCELED || code == ERROR_CODE_USER_RESTRICTED
2159 || code == ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE) {
2160 // the authenticator indicated that this request was canceled or we were
2161 // forbidden to fulfill; cancel now
Fred Quintanaa698f422009-04-08 19:14:54 -07002162 cancel(true /* mayInterruptIfRunning */);
2163 return;
2164 }
2165 setException(convertErrorToException(code, message));
2166 }
2167 }
2168
Fred Quintana60307342009-03-24 22:48:12 -07002169 }
2170
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002171 private abstract class BaseFutureTask<T> extends FutureTask<T> {
2172 final public IAccountManagerResponse mResponse;
Fred Quintanaa698f422009-04-08 19:14:54 -07002173 final Handler mHandler;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002174
2175 public BaseFutureTask(Handler handler) {
2176 super(new Callable<T>() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002177 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002178 public T call() throws Exception {
Fred Quintanaa698f422009-04-08 19:14:54 -07002179 throw new IllegalStateException("this should never be called");
2180 }
2181 });
Fred Quintanaa698f422009-04-08 19:14:54 -07002182 mHandler = handler;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002183 mResponse = new Response();
Fred Quintana60307342009-03-24 22:48:12 -07002184 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002185
2186 public abstract void doWork() throws RemoteException;
2187
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002188 public abstract T bundleToResult(Bundle bundle) throws AuthenticatorException;
Fred Quintanaa698f422009-04-08 19:14:54 -07002189
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002190 protected void postRunnableToHandler(Runnable runnable) {
2191 Handler handler = (mHandler == null) ? mMainHandler : mHandler;
2192 handler.post(runnable);
Fred Quintanaa698f422009-04-08 19:14:54 -07002193 }
2194
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002195 protected void startTask() {
Fred Quintanaa698f422009-04-08 19:14:54 -07002196 try {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002197 doWork();
2198 } catch (RemoteException e) {
2199 setException(e);
Fred Quintanaa698f422009-04-08 19:14:54 -07002200 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002201 }
2202
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002203 protected class Response extends IAccountManagerResponse.Stub {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002204 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002205 public void onResult(Bundle bundle) {
2206 try {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002207 T result = bundleToResult(bundle);
2208 if (result == null) {
Fred Quintanaa698f422009-04-08 19:14:54 -07002209 return;
2210 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002211 set(result);
2212 return;
Fred Quintanaa698f422009-04-08 19:14:54 -07002213 } catch (ClassCastException e) {
2214 // we will set the exception below
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002215 } catch (AuthenticatorException e) {
2216 // we will set the exception below
Fred Quintanaa698f422009-04-08 19:14:54 -07002217 }
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002218 onError(ERROR_CODE_INVALID_RESPONSE, "no result in response");
Fred Quintanaa698f422009-04-08 19:14:54 -07002219 }
2220
Sandra Kwan0b84b452016-01-20 15:25:42 -08002221 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002222 public void onError(int code, String message) {
Alexandra Gherghina999d3942014-07-03 11:40:08 +01002223 if (code == ERROR_CODE_CANCELED || code == ERROR_CODE_USER_RESTRICTED
2224 || code == ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE) {
2225 // the authenticator indicated that this request was canceled or we were
2226 // forbidden to fulfill; cancel now
Fred Quintanaa698f422009-04-08 19:14:54 -07002227 cancel(true /* mayInterruptIfRunning */);
2228 return;
2229 }
2230 setException(convertErrorToException(code, message));
2231 }
2232 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002233 }
2234
2235 private abstract class Future2Task<T>
2236 extends BaseFutureTask<T> implements AccountManagerFuture<T> {
2237 final AccountManagerCallback<T> mCallback;
2238 public Future2Task(Handler handler, AccountManagerCallback<T> callback) {
2239 super(handler);
2240 mCallback = callback;
2241 }
2242
Sandra Kwan0b84b452016-01-20 15:25:42 -08002243 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002244 protected void done() {
2245 if (mCallback != null) {
2246 postRunnableToHandler(new Runnable() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002247 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002248 public void run() {
2249 mCallback.run(Future2Task.this);
2250 }
2251 });
2252 }
2253 }
2254
2255 public Future2Task<T> start() {
2256 startTask();
2257 return this;
2258 }
2259
2260 private T internalGetResult(Long timeout, TimeUnit unit)
2261 throws OperationCanceledException, IOException, AuthenticatorException {
Fred Quintana53bd2522010-02-05 15:28:12 -08002262 if (!isDone()) {
2263 ensureNotOnMainThread();
2264 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002265 try {
2266 if (timeout == null) {
2267 return get();
2268 } else {
2269 return get(timeout, unit);
2270 }
2271 } catch (InterruptedException e) {
2272 // fall through and cancel
2273 } catch (TimeoutException e) {
2274 // fall through and cancel
2275 } catch (CancellationException e) {
2276 // fall through and cancel
2277 } catch (ExecutionException e) {
2278 final Throwable cause = e.getCause();
2279 if (cause instanceof IOException) {
2280 throw (IOException) cause;
2281 } else if (cause instanceof UnsupportedOperationException) {
2282 throw new AuthenticatorException(cause);
2283 } else if (cause instanceof AuthenticatorException) {
2284 throw (AuthenticatorException) cause;
2285 } else if (cause instanceof RuntimeException) {
2286 throw (RuntimeException) cause;
2287 } else if (cause instanceof Error) {
2288 throw (Error) cause;
2289 } else {
2290 throw new IllegalStateException(cause);
2291 }
2292 } finally {
2293 cancel(true /* interrupt if running */);
2294 }
2295 throw new OperationCanceledException();
2296 }
2297
Sandra Kwan0b84b452016-01-20 15:25:42 -08002298 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002299 public T getResult()
2300 throws OperationCanceledException, IOException, AuthenticatorException {
2301 return internalGetResult(null, null);
2302 }
2303
Sandra Kwan0b84b452016-01-20 15:25:42 -08002304 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002305 public T getResult(long timeout, TimeUnit unit)
2306 throws OperationCanceledException, IOException, AuthenticatorException {
2307 return internalGetResult(timeout, unit);
2308 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002309
Fred Quintana60307342009-03-24 22:48:12 -07002310 }
2311
Fred Quintanaa698f422009-04-08 19:14:54 -07002312 private Exception convertErrorToException(int code, String message) {
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002313 if (code == ERROR_CODE_NETWORK_ERROR) {
Fred Quintanaa698f422009-04-08 19:14:54 -07002314 return new IOException(message);
Fred Quintana60307342009-03-24 22:48:12 -07002315 }
Fred Quintana60307342009-03-24 22:48:12 -07002316
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002317 if (code == ERROR_CODE_UNSUPPORTED_OPERATION) {
Fred Quintana33269202009-04-20 16:05:10 -07002318 return new UnsupportedOperationException(message);
Fred Quintana60307342009-03-24 22:48:12 -07002319 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002320
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002321 if (code == ERROR_CODE_INVALID_RESPONSE) {
Fred Quintana33269202009-04-20 16:05:10 -07002322 return new AuthenticatorException(message);
Fred Quintanaa698f422009-04-08 19:14:54 -07002323 }
2324
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002325 if (code == ERROR_CODE_BAD_ARGUMENTS) {
Fred Quintana33269202009-04-20 16:05:10 -07002326 return new IllegalArgumentException(message);
2327 }
2328
2329 return new AuthenticatorException(message);
2330 }
2331
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002332 private class GetAuthTokenByTypeAndFeaturesTask
2333 extends AmsTask implements AccountManagerCallback<Bundle> {
Fred Quintana33269202009-04-20 16:05:10 -07002334 GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType,
2335 final String[] features, Activity activityForPrompting,
2336 final Bundle addAccountOptions, final Bundle loginOptions,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002337 AccountManagerCallback<Bundle> callback, Handler handler) {
Fred Quintana33269202009-04-20 16:05:10 -07002338 super(activityForPrompting, handler, callback);
2339 if (accountType == null) throw new IllegalArgumentException("account type is null");
2340 mAccountType = accountType;
2341 mAuthTokenType = authTokenType;
2342 mFeatures = features;
2343 mAddAccountOptions = addAccountOptions;
2344 mLoginOptions = loginOptions;
2345 mMyCallback = this;
2346 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002347 volatile AccountManagerFuture<Bundle> mFuture = null;
Fred Quintana33269202009-04-20 16:05:10 -07002348 final String mAccountType;
2349 final String mAuthTokenType;
2350 final String[] mFeatures;
2351 final Bundle mAddAccountOptions;
2352 final Bundle mLoginOptions;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002353 final AccountManagerCallback<Bundle> mMyCallback;
Fred Quintanaf0fd8432010-03-08 12:48:05 -08002354 private volatile int mNumAccounts = 0;
Fred Quintana33269202009-04-20 16:05:10 -07002355
Sandra Kwan0b84b452016-01-20 15:25:42 -08002356 @Override
Fred Quintana33269202009-04-20 16:05:10 -07002357 public void doWork() throws RemoteException {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002358 getAccountsByTypeAndFeatures(mAccountType, mFeatures,
2359 new AccountManagerCallback<Account[]>() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002360 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002361 public void run(AccountManagerFuture<Account[]> future) {
2362 Account[] accounts;
Fred Quintana33269202009-04-20 16:05:10 -07002363 try {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002364 accounts = future.getResult();
2365 } catch (OperationCanceledException e) {
2366 setException(e);
2367 return;
2368 } catch (IOException e) {
2369 setException(e);
2370 return;
2371 } catch (AuthenticatorException e) {
2372 setException(e);
2373 return;
Fred Quintana33269202009-04-20 16:05:10 -07002374 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002375
Fred Quintanaf0fd8432010-03-08 12:48:05 -08002376 mNumAccounts = accounts.length;
2377
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002378 if (accounts.length == 0) {
2379 if (mActivity != null) {
2380 // no accounts, add one now. pretend that the user directly
2381 // made this request
2382 mFuture = addAccount(mAccountType, mAuthTokenType, mFeatures,
2383 mAddAccountOptions, mActivity, mMyCallback, mHandler);
2384 } else {
2385 // send result since we can't prompt to add an account
2386 Bundle result = new Bundle();
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002387 result.putString(KEY_ACCOUNT_NAME, null);
2388 result.putString(KEY_ACCOUNT_TYPE, null);
2389 result.putString(KEY_AUTHTOKEN, null);
Svet Ganovc1c0d1c2016-09-23 19:15:47 -07002390 result.putBinder(KEY_ACCOUNT_ACCESS_ID, null);
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002391 try {
2392 mResponse.onResult(result);
2393 } catch (RemoteException e) {
2394 // this will never happen
2395 }
2396 // we are done
2397 }
2398 } else if (accounts.length == 1) {
2399 // have a single account, return an authtoken for it
2400 if (mActivity == null) {
2401 mFuture = getAuthToken(accounts[0], mAuthTokenType,
2402 false /* notifyAuthFailure */, mMyCallback, mHandler);
2403 } else {
2404 mFuture = getAuthToken(accounts[0],
2405 mAuthTokenType, mLoginOptions,
Fred Quintana33269202009-04-20 16:05:10 -07002406 mActivity, mMyCallback, mHandler);
2407 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002408 } else {
2409 if (mActivity != null) {
2410 IAccountManagerResponse chooseResponse =
2411 new IAccountManagerResponse.Stub() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002412 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002413 public void onResult(Bundle value) throws RemoteException {
2414 Account account = new Account(
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002415 value.getString(KEY_ACCOUNT_NAME),
Svet Ganovf6d424f12016-09-20 20:18:53 -07002416 value.getString(KEY_ACCOUNT_TYPE),
Svet Ganovc1c0d1c2016-09-23 19:15:47 -07002417 value.getString(KEY_ACCOUNT_ACCESS_ID));
Svet Ganovf6d424f12016-09-20 20:18:53 -07002418 mFuture = getAuthToken(account, mAuthTokenType,
2419 mLoginOptions, mActivity, mMyCallback,
2420 mHandler);
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002421 }
Fred Quintana33269202009-04-20 16:05:10 -07002422
Sandra Kwan0b84b452016-01-20 15:25:42 -08002423 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002424 public void onError(int errorCode, String errorMessage)
2425 throws RemoteException {
2426 mResponse.onError(errorCode, errorMessage);
2427 }
2428 };
2429 // have many accounts, launch the chooser
2430 Intent intent = new Intent();
Amith Yamasani12b8e132013-03-14 10:48:07 -07002431 ComponentName componentName = ComponentName.unflattenFromString(
2432 Resources.getSystem().getString(
2433 R.string.config_chooseAccountActivity));
2434 intent.setClassName(componentName.getPackageName(),
2435 componentName.getClassName());
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002436 intent.putExtra(KEY_ACCOUNTS, accounts);
2437 intent.putExtra(KEY_ACCOUNT_MANAGER_RESPONSE,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002438 new AccountManagerResponse(chooseResponse));
2439 mActivity.startActivity(intent);
2440 // the result will arrive via the IAccountManagerResponse
2441 } else {
2442 // send result since we can't prompt to select an account
2443 Bundle result = new Bundle();
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002444 result.putString(KEY_ACCOUNTS, null);
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002445 try {
2446 mResponse.onResult(result);
2447 } catch (RemoteException e) {
2448 // this will never happen
2449 }
2450 // we are done
Fred Quintana33269202009-04-20 16:05:10 -07002451 }
Fred Quintana33269202009-04-20 16:05:10 -07002452 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002453 }}, mHandler);
Fred Quintana33269202009-04-20 16:05:10 -07002454 }
2455
Sandra Kwan0b84b452016-01-20 15:25:42 -08002456 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002457 public void run(AccountManagerFuture<Bundle> future) {
Fred Quintana33269202009-04-20 16:05:10 -07002458 try {
Fred Quintanaf0fd8432010-03-08 12:48:05 -08002459 final Bundle result = future.getResult();
2460 if (mNumAccounts == 0) {
2461 final String accountName = result.getString(KEY_ACCOUNT_NAME);
2462 final String accountType = result.getString(KEY_ACCOUNT_TYPE);
2463 if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
2464 setException(new AuthenticatorException("account not in result"));
2465 return;
2466 }
Svet Ganovc1c0d1c2016-09-23 19:15:47 -07002467 final String accessId = result.getString(KEY_ACCOUNT_ACCESS_ID);
2468 final Account account = new Account(accountName, accountType, accessId);
Fred Quintanaf0fd8432010-03-08 12:48:05 -08002469 mNumAccounts = 1;
2470 getAuthToken(account, mAuthTokenType, null /* options */, mActivity,
2471 mMyCallback, mHandler);
2472 return;
2473 }
2474 set(result);
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002475 } catch (OperationCanceledException e) {
2476 cancel(true /* mayInterruptIfRUnning */);
2477 } catch (IOException e) {
2478 setException(e);
2479 } catch (AuthenticatorException e) {
2480 setException(e);
Fred Quintana33269202009-04-20 16:05:10 -07002481 }
2482 }
2483 }
2484
Fred Quintana756b7352009-10-21 13:43:10 -07002485 /**
Dan Egnor661f0132010-02-19 11:23:00 -08002486 * This convenience helper combines the functionality of
2487 * {@link #getAccountsByTypeAndFeatures}, {@link #getAuthToken}, and
2488 * {@link #addAccount}.
Fred Quintana756b7352009-10-21 13:43:10 -07002489 *
Dan Egnor661f0132010-02-19 11:23:00 -08002490 * <p>This method gets a list of the accounts matching the
2491 * specified type and feature set; if there is exactly one, it is
2492 * used; if there are more than one, the user is prompted to pick one;
2493 * if there are none, the user is prompted to add one. Finally,
2494 * an auth token is acquired for the chosen account.
2495 *
2496 * <p>This method may be called from any thread, but the returned
2497 * {@link AccountManagerFuture} must not be used on the main thread.
2498 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07002499 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
2500 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
2501 * this function in API level 22.
2502 *
Dan Egnor661f0132010-02-19 11:23:00 -08002503 * @param accountType The account type required
Doug Zongkerff592dc2010-02-23 12:26:33 -08002504 * (see {@link #getAccountsByType}), must not be null
Dan Egnor661f0132010-02-19 11:23:00 -08002505 * @param authTokenType The desired auth token type
2506 * (see {@link #getAuthToken}), must not be null
2507 * @param features Required features for the account
2508 * (see {@link #getAccountsByTypeAndFeatures}), may be null or empty
2509 * @param activity The {@link Activity} context to use for launching new
2510 * sub-Activities to prompt to add an account, select an account,
2511 * and/or enter a password, as necessary; used only to call
2512 * startActivity(); should not be null
2513 * @param addAccountOptions Authenticator-specific options to use for
2514 * adding new accounts; may be null or empty
2515 * @param getAuthTokenOptions Authenticator-specific options to use for
2516 * getting auth tokens; may be null or empty
2517 * @param callback Callback to invoke when the request completes,
2518 * null for no callback
2519 * @param handler {@link Handler} identifying the callback thread,
2520 * null for the main thread
2521 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
2522 * at least the following fields:
Fred Quintana756b7352009-10-21 13:43:10 -07002523 * <ul>
Dan Egnor661f0132010-02-19 11:23:00 -08002524 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account
2525 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
2526 * <li> {@link #KEY_AUTHTOKEN} - the auth token you wanted
Fred Quintana756b7352009-10-21 13:43:10 -07002527 * </ul>
Dan Egnor661f0132010-02-19 11:23:00 -08002528 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07002529 * If an error occurred, {@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08002530 * <ul>
2531 * <li> {@link AuthenticatorException} if no authenticator was registered for
2532 * this account type or the authenticator failed to respond
2533 * <li> {@link OperationCanceledException} if the operation was canceled for
2534 * any reason, including the user canceling any operation
2535 * <li> {@link IOException} if the authenticator experienced an I/O problem
2536 * updating settings, usually because of network trouble
2537 * </ul>
Fred Quintana756b7352009-10-21 13:43:10 -07002538 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002539 public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
Fred Quintana33269202009-04-20 16:05:10 -07002540 final String accountType, final String authTokenType, final String[] features,
Dan Egnor661f0132010-02-19 11:23:00 -08002541 final Activity activity, final Bundle addAccountOptions,
Fred Quintana31957f12009-10-21 13:43:10 -07002542 final Bundle getAuthTokenOptions,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002543 final AccountManagerCallback<Bundle> callback, final Handler handler) {
Fred Quintana33269202009-04-20 16:05:10 -07002544 if (accountType == null) throw new IllegalArgumentException("account type is null");
2545 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002546 final GetAuthTokenByTypeAndFeaturesTask task =
2547 new GetAuthTokenByTypeAndFeaturesTask(accountType, authTokenType, features,
Dan Egnor661f0132010-02-19 11:23:00 -08002548 activity, addAccountOptions, getAuthTokenOptions, callback, handler);
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002549 task.start();
2550 return task;
Fred Quintana60307342009-03-24 22:48:12 -07002551 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002552
Fred Quintana1121bb52011-09-14 23:19:35 -07002553 /**
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002554 * Deprecated in favor of {@link #newChooseAccountIntent(Account, List, String[], String,
2555 * String, String[], Bundle)}.
2556 *
Fred Quintana1121bb52011-09-14 23:19:35 -07002557 * Returns an intent to an {@link Activity} that prompts the user to choose from a list of
2558 * accounts.
2559 * The caller will then typically start the activity by calling
Mark Fickettab249e02012-09-05 09:45:47 -04002560 * <code>startActivityForResult(intent, ...);</code>.
Fred Quintana1121bb52011-09-14 23:19:35 -07002561 * <p>
2562 * On success the activity returns a Bundle with the account name and type specified using
2563 * keys {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE}.
2564 * <p>
2565 * The most common case is to call this with one account type, e.g.:
2566 * <p>
kmccormickf783ce52013-03-29 14:31:54 -07002567 * <pre> newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null,
Fred Quintanad88324d2011-09-19 11:43:05 -07002568 * null, null, null);</pre>
Fred Quintana1121bb52011-09-14 23:19:35 -07002569 * @param selectedAccount if specified, indicates that the {@link Account} is the currently
2570 * selected one, according to the caller's definition of selected.
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002571 * @param allowableAccounts an optional {@link List} of accounts that are allowed to be
Fred Quintana1121bb52011-09-14 23:19:35 -07002572 * shown. If not specified then this field will not limit the displayed accounts.
2573 * @param allowableAccountTypes an optional string array of account types. These are used
2574 * both to filter the shown accounts and to filter the list of account types that are shown
Simranjit Singh Kohli734f8fb2015-05-22 14:00:32 -07002575 * when adding an account. If not specified then this field will not limit the displayed
2576 * account types when adding an account.
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002577 * @param alwaysPromptForAccount boolean that is ignored.
Fred Quintanad88324d2011-09-19 11:43:05 -07002578 * @param descriptionOverrideText if non-null this string is used as the description in the
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002579 * accounts chooser screen rather than the default
Fred Quintanad88324d2011-09-19 11:43:05 -07002580 * @param addAccountAuthTokenType this string is passed as the {@link #addAccount}
2581 * authTokenType parameter
2582 * @param addAccountRequiredFeatures this string array is passed as the {@link #addAccount}
2583 * requiredFeatures parameter
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002584 * @param addAccountOptions This {@link Bundle} is passed as the {@link #addAccount} options
Fred Quintanad88324d2011-09-19 11:43:05 -07002585 * parameter
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002586 * @return an {@link Intent} that can be used to launch the ChooseAccount activity flow.
Fred Quintana1121bb52011-09-14 23:19:35 -07002587 */
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002588 @Deprecated
2589 static public Intent newChooseAccountIntent(
2590 Account selectedAccount,
Baligh Uddinf2d248d2015-07-10 03:01:47 +00002591 ArrayList<Account> allowableAccounts,
Fred Quintana1121bb52011-09-14 23:19:35 -07002592 String[] allowableAccountTypes,
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002593 boolean alwaysPromptForAccount,
2594 String descriptionOverrideText,
2595 String addAccountAuthTokenType,
2596 String[] addAccountRequiredFeatures,
Fred Quintana1121bb52011-09-14 23:19:35 -07002597 Bundle addAccountOptions) {
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002598 return newChooseAccountIntent(
2599 selectedAccount,
2600 allowableAccounts,
2601 allowableAccountTypes,
2602 descriptionOverrideText,
2603 addAccountAuthTokenType,
2604 addAccountRequiredFeatures,
2605 addAccountOptions);
2606 }
2607
2608 /**
2609 * Returns an intent to an {@link Activity} that prompts the user to choose from a list of
2610 * accounts.
2611 * The caller will then typically start the activity by calling
2612 * <code>startActivityForResult(intent, ...);</code>.
2613 * <p>
2614 * On success the activity returns a Bundle with the account name and type specified using
2615 * keys {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE}.
2616 * <p>
2617 * The most common case is to call this with one account type, e.g.:
2618 * <p>
2619 * <pre> newChooseAccountIntent(null, null, new String[]{"com.google"}, null, null, null,
2620 * null);</pre>
2621 * @param selectedAccount if specified, indicates that the {@link Account} is the currently
2622 * selected one, according to the caller's definition of selected.
2623 * @param allowableAccounts an optional {@link List} of accounts that are allowed to be
2624 * shown. If not specified then this field will not limit the displayed accounts.
2625 * @param allowableAccountTypes an optional string array of account types. These are used
2626 * both to filter the shown accounts and to filter the list of account types that are shown
2627 * when adding an account. If not specified then this field will not limit the displayed
2628 * account types when adding an account.
2629 * @param descriptionOverrideText if non-null this string is used as the description in the
2630 * accounts chooser screen rather than the default
2631 * @param addAccountAuthTokenType this string is passed as the {@link #addAccount}
2632 * authTokenType parameter
2633 * @param addAccountRequiredFeatures this string array is passed as the {@link #addAccount}
2634 * requiredFeatures parameter
2635 * @param addAccountOptions This {@link Bundle} is passed as the {@link #addAccount} options
2636 * parameter
2637 * @return an {@link Intent} that can be used to launch the ChooseAccount activity flow.
2638 */
2639 static public Intent newChooseAccountIntent(
2640 Account selectedAccount,
2641 List<Account> allowableAccounts,
2642 String[] allowableAccountTypes,
2643 String descriptionOverrideText,
2644 String addAccountAuthTokenType,
2645 String[] addAccountRequiredFeatures,
2646 Bundle addAccountOptions) {
Fred Quintana1121bb52011-09-14 23:19:35 -07002647 Intent intent = new Intent();
Amith Yamasani12b8e132013-03-14 10:48:07 -07002648 ComponentName componentName = ComponentName.unflattenFromString(
2649 Resources.getSystem().getString(R.string.config_chooseTypeAndAccountActivity));
2650 intent.setClassName(componentName.getPackageName(),
2651 componentName.getClassName());
Fred Quintana1121bb52011-09-14 23:19:35 -07002652 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ALLOWABLE_ACCOUNTS_ARRAYLIST,
Craig Lafayette3c9c71d2015-07-14 10:48:46 -04002653 allowableAccounts == null ? null : new ArrayList<Account>(allowableAccounts));
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002654 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY,
2655 allowableAccountTypes);
Fred Quintana1121bb52011-09-14 23:19:35 -07002656 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_OPTIONS_BUNDLE,
2657 addAccountOptions);
2658 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_SELECTED_ACCOUNT, selectedAccount);
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002659 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_DESCRIPTION_TEXT_OVERRIDE,
2660 descriptionOverrideText);
2661 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_AUTH_TOKEN_TYPE_STRING,
2662 addAccountAuthTokenType);
2663 intent.putExtra(
2664 ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_REQUIRED_FEATURES_STRING_ARRAY,
2665 addAccountRequiredFeatures);
Fred Quintana1121bb52011-09-14 23:19:35 -07002666 return intent;
2667 }
2668
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002669 private final HashMap<OnAccountsUpdateListener, Handler> mAccountsUpdatedListeners =
Fred Quintanad9d2f112009-04-23 13:36:27 -07002670 Maps.newHashMap();
2671
Fred Quintanad9d2f112009-04-23 13:36:27 -07002672 /**
2673 * BroadcastReceiver that listens for the LOGIN_ACCOUNTS_CHANGED_ACTION intent
2674 * so that it can read the updated list of accounts and send them to the listener
2675 * in mAccountsUpdatedListeners.
2676 */
2677 private final BroadcastReceiver mAccountsChangedBroadcastReceiver = new BroadcastReceiver() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002678 @Override
Fred Quintanad9d2f112009-04-23 13:36:27 -07002679 public void onReceive(final Context context, final Intent intent) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002680 final Account[] accounts = getAccounts();
2681 // send the result to the listeners
2682 synchronized (mAccountsUpdatedListeners) {
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002683 for (Map.Entry<OnAccountsUpdateListener, Handler> entry :
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002684 mAccountsUpdatedListeners.entrySet()) {
2685 postToHandler(entry.getValue(), entry.getKey(), accounts);
Fred Quintanad9d2f112009-04-23 13:36:27 -07002686 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002687 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002688 }
2689 };
2690
2691 /**
Dan Egnor661f0132010-02-19 11:23:00 -08002692 * Adds an {@link OnAccountsUpdateListener} to this instance of the
2693 * {@link AccountManager}. This listener will be notified whenever the
2694 * list of accounts on the device changes.
2695 *
2696 * <p>As long as this listener is present, the AccountManager instance
2697 * will not be garbage-collected, and neither will the {@link Context}
2698 * used to retrieve it, which may be a large Activity instance. To avoid
2699 * memory leaks, you must remove this listener before then. Normally
2700 * listeners are added in an Activity or Service's {@link Activity#onCreate}
2701 * and removed in {@link Activity#onDestroy}.
2702 *
Ian Pedowitz6cc066d2015-08-05 14:23:43 +00002703 * <p>The listener will only be informed of accounts that would be returned
2704 * to the caller via {@link #getAccounts()}. Typically this means that to
2705 * get any accounts, the caller will need to be grated the GET_ACCOUNTS
2706 * permission.
Dan Egnor661f0132010-02-19 11:23:00 -08002707 *
Ian Pedowitz6cc066d2015-08-05 14:23:43 +00002708 * <p>It is safe to call this method from the main thread.
Ian Pedowitz845d14d2015-08-04 07:47:37 -07002709 *
Dan Egnor661f0132010-02-19 11:23:00 -08002710 * @param listener The listener to send notifications to
2711 * @param handler {@link Handler} identifying the thread to use
2712 * for notifications, null for the main thread
2713 * @param updateImmediately If true, the listener will be invoked
2714 * (on the handler thread) right away with the current account list
Fred Quintanad9d2f112009-04-23 13:36:27 -07002715 * @throws IllegalArgumentException if listener is null
2716 * @throws IllegalStateException if listener was already added
2717 */
Tor Norbye80b530a2015-04-23 16:36:09 -07002718 @RequiresPermission(GET_ACCOUNTS)
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002719 public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
Fred Quintanad9d2f112009-04-23 13:36:27 -07002720 Handler handler, boolean updateImmediately) {
2721 if (listener == null) {
2722 throw new IllegalArgumentException("the listener is null");
2723 }
2724 synchronized (mAccountsUpdatedListeners) {
2725 if (mAccountsUpdatedListeners.containsKey(listener)) {
2726 throw new IllegalStateException("this listener is already added");
2727 }
2728 final boolean wasEmpty = mAccountsUpdatedListeners.isEmpty();
2729
2730 mAccountsUpdatedListeners.put(listener, handler);
2731
2732 if (wasEmpty) {
2733 // Register a broadcast receiver to monitor account changes
2734 IntentFilter intentFilter = new IntentFilter();
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002735 intentFilter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION);
Costin Manolacheb6437242009-09-10 16:14:12 -07002736 // To recover from disk-full.
Fred Quintanac5d1c6d2010-01-27 12:17:49 -08002737 intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
Fred Quintanad9d2f112009-04-23 13:36:27 -07002738 mContext.registerReceiver(mAccountsChangedBroadcastReceiver, intentFilter);
2739 }
2740 }
2741
2742 if (updateImmediately) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002743 postToHandler(handler, listener, getAccounts());
Fred Quintanad9d2f112009-04-23 13:36:27 -07002744 }
2745 }
2746
2747 /**
Dan Egnor661f0132010-02-19 11:23:00 -08002748 * Removes an {@link OnAccountsUpdateListener} previously registered with
2749 * {@link #addOnAccountsUpdatedListener}. The listener will no longer
2750 * receive notifications of account changes.
2751 *
2752 * <p>It is safe to call this method from the main thread.
2753 *
2754 * <p>No permission is required to call this method.
2755 *
2756 * @param listener The previously added listener to remove
Fred Quintanad9d2f112009-04-23 13:36:27 -07002757 * @throws IllegalArgumentException if listener is null
2758 * @throws IllegalStateException if listener was not already added
2759 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002760 public void removeOnAccountsUpdatedListener(OnAccountsUpdateListener listener) {
Fred Quintana382601f2010-03-25 12:25:10 -07002761 if (listener == null) throw new IllegalArgumentException("listener is null");
Fred Quintanad9d2f112009-04-23 13:36:27 -07002762 synchronized (mAccountsUpdatedListeners) {
Bryan Mawhinney5be61f52009-09-24 14:50:25 +01002763 if (!mAccountsUpdatedListeners.containsKey(listener)) {
Costin Manolache88a211b2009-10-29 11:30:11 -07002764 Log.e(TAG, "Listener was not previously added");
2765 return;
Fred Quintanad9d2f112009-04-23 13:36:27 -07002766 }
Bryan Mawhinney5be61f52009-09-24 14:50:25 +01002767 mAccountsUpdatedListeners.remove(listener);
Fred Quintanad9d2f112009-04-23 13:36:27 -07002768 if (mAccountsUpdatedListeners.isEmpty()) {
2769 mContext.unregisterReceiver(mAccountsChangedBroadcastReceiver);
2770 }
2771 }
2772 }
Sandra Kwan78812282015-11-04 11:19:47 -08002773
2774 /**
2775 * Asks the user to authenticate with an account of a specified type. The
2776 * authenticator for this account type processes this request with the
2777 * appropriate user interface. If the user does elect to authenticate with a
2778 * new account, a bundle of session data for installing the account later is
2779 * returned with optional account password and account status token.
2780 * <p>
2781 * This method may be called from any thread, but the returned
2782 * {@link AccountManagerFuture} must not be used on the main thread.
2783 * <p>
2784 * <p>
2785 * <b>NOTE:</b> The account will not be installed to the device by calling
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002786 * this api alone. #finishSession should be called after this to install the
2787 * account on device.
Sandra Kwan78812282015-11-04 11:19:47 -08002788 *
2789 * @param accountType The type of account to add; must not be null
2790 * @param authTokenType The type of auth token (see {@link #getAuthToken})
2791 * this account will need to be able to generate, null for none
2792 * @param requiredFeatures The features (see {@link #hasFeatures}) this
2793 * account must have, null for none
2794 * @param options Authenticator-specific options for the request, may be
2795 * null or empty
2796 * @param activity The {@link Activity} context to use for launching a new
2797 * authenticator-defined sub-Activity to prompt the user to
2798 * create an account; used only to call startActivity(); if null,
2799 * the prompt will not be launched directly, but the necessary
2800 * {@link Intent} will be returned to the caller instead
2801 * @param callback Callback to invoke when the request completes, null for
2802 * no callback
2803 * @param handler {@link Handler} identifying the callback thread, null for
2804 * the main thread
2805 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
2806 * these fields if activity was specified and user was authenticated
2807 * with an account:
2808 * <ul>
2809 * <li>{@link #KEY_ACCOUNT_SESSION_BUNDLE} - encrypted Bundle for
2810 * adding the the to the device later.
Sandra Kwan78812282015-11-04 11:19:47 -08002811 * <li>{@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check
2812 * status of the account
2813 * </ul>
2814 * If no activity was specified, the returned Bundle contains only
2815 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
2816 * actual account creation process. If authenticator doesn't support
2817 * this method, the returned Bundle contains only
2818 * {@link #KEY_ACCOUNT_SESSION_BUNDLE} with encrypted
2819 * {@code options} needed to add account later. If an error
2820 * occurred, {@link AccountManagerFuture#getResult()} throws:
2821 * <ul>
2822 * <li>{@link AuthenticatorException} if no authenticator was
2823 * registered for this account type or the authenticator failed to
2824 * respond
2825 * <li>{@link OperationCanceledException} if the operation was
2826 * canceled for any reason, including the user canceling the
2827 * creation process or adding accounts (of this type) has been
2828 * disabled by policy
2829 * <li>{@link IOException} if the authenticator experienced an I/O
2830 * problem creating a new account, usually because of network
2831 * trouble
2832 * </ul>
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002833 * @see #finishSession
Sandra Kwan78812282015-11-04 11:19:47 -08002834 */
Sandra Kwane68c37e2015-11-12 17:11:49 -08002835 public AccountManagerFuture<Bundle> startAddAccountSession(
2836 final String accountType,
2837 final String authTokenType,
2838 final String[] requiredFeatures,
2839 final Bundle options,
2840 final Activity activity,
2841 AccountManagerCallback<Bundle> callback,
2842 Handler handler) {
Sandra Kwan78812282015-11-04 11:19:47 -08002843 if (accountType == null) throw new IllegalArgumentException("accountType is null");
2844 final Bundle optionsIn = new Bundle();
2845 if (options != null) {
2846 optionsIn.putAll(options);
2847 }
2848 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
2849
2850 return new AmsTask(activity, handler, callback) {
2851 @Override
2852 public void doWork() throws RemoteException {
Sandra Kwane68c37e2015-11-12 17:11:49 -08002853 mService.startAddAccountSession(
2854 mResponse,
2855 accountType,
2856 authTokenType,
2857 requiredFeatures,
2858 activity != null,
2859 optionsIn);
2860 }
2861 }.start();
2862 }
2863
2864 /**
2865 * Asks the user to enter a new password for an account but not updating the
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002866 * saved credentials for the account until {@link #finishSession} is called.
Sandra Kwane68c37e2015-11-12 17:11:49 -08002867 * <p>
2868 * This method may be called from any thread, but the returned
2869 * {@link AccountManagerFuture} must not be used on the main thread.
2870 * <p>
2871 * <b>NOTE:</b> The saved credentials for the account alone will not be
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002872 * updated by calling this API alone. #finishSession should be called after
2873 * this to update local credentials
Sandra Kwane68c37e2015-11-12 17:11:49 -08002874 *
2875 * @param account The account to update credentials for
2876 * @param authTokenType The credentials entered must allow an auth token of
2877 * this type to be created (but no actual auth token is
2878 * returned); may be null
2879 * @param options Authenticator-specific options for the request; may be
2880 * null or empty
2881 * @param activity The {@link Activity} context to use for launching a new
2882 * authenticator-defined sub-Activity to prompt the user to enter
2883 * a password; used only to call startActivity(); if null, the
2884 * prompt will not be launched directly, but the necessary
2885 * {@link Intent} will be returned to the caller instead
2886 * @param callback Callback to invoke when the request completes, null for
2887 * no callback
2888 * @param handler {@link Handler} identifying the callback thread, null for
2889 * the main thread
2890 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
2891 * these fields if an activity was supplied and user was
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002892 * successfully re-authenticated to the account:
Sandra Kwane68c37e2015-11-12 17:11:49 -08002893 * <ul>
2894 * <li>{@link #KEY_ACCOUNT_SESSION_BUNDLE} - encrypted Bundle for
2895 * updating the local credentials on device later.
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002896 * <li>{@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check
2897 * status of the account
Sandra Kwane68c37e2015-11-12 17:11:49 -08002898 * </ul>
2899 * If no activity was specified, the returned Bundle contains
2900 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
2901 * password prompt. If an error occurred,
2902 * {@link AccountManagerFuture#getResult()} throws:
2903 * <ul>
2904 * <li>{@link AuthenticatorException} if the authenticator failed to
2905 * respond
2906 * <li>{@link OperationCanceledException} if the operation was
2907 * canceled for any reason, including the user canceling the
2908 * password prompt
2909 * <li>{@link IOException} if the authenticator experienced an I/O
2910 * problem verifying the password, usually because of network
2911 * trouble
2912 * </ul>
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002913 * @see #finishSession
Sandra Kwane68c37e2015-11-12 17:11:49 -08002914 */
2915 public AccountManagerFuture<Bundle> startUpdateCredentialsSession(
2916 final Account account,
2917 final String authTokenType,
2918 final Bundle options,
2919 final Activity activity,
2920 final AccountManagerCallback<Bundle> callback,
2921 final Handler handler) {
2922 if (account == null) {
2923 throw new IllegalArgumentException("account is null");
2924 }
Carlos Valdivia51b651a2016-03-30 13:44:28 -07002925
2926 // Always include the calling package name. This just makes life easier
2927 // down stream.
2928 final Bundle optionsIn = new Bundle();
2929 if (options != null) {
2930 optionsIn.putAll(options);
2931 }
2932 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
2933
Sandra Kwane68c37e2015-11-12 17:11:49 -08002934 return new AmsTask(activity, handler, callback) {
2935 @Override
2936 public void doWork() throws RemoteException {
2937 mService.startUpdateCredentialsSession(
2938 mResponse,
2939 account,
2940 authTokenType,
2941 activity != null,
Carlos Valdivia51b651a2016-03-30 13:44:28 -07002942 optionsIn);
Sandra Kwan78812282015-11-04 11:19:47 -08002943 }
2944 }.start();
2945 }
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002946
2947 /**
2948 * Finishes the session started by {@link #startAddAccountSession} or
2949 * {@link #startUpdateCredentialsSession}. This will either add the account
2950 * to AccountManager or update the local credentials stored.
2951 * <p>
2952 * This method may be called from any thread, but the returned
2953 * {@link AccountManagerFuture} must not be used on the main thread.
2954 *
2955 * @param sessionBundle a {@link Bundle} created by {@link #startAddAccountSession} or
2956 * {@link #startUpdateCredentialsSession}
2957 * @param activity The {@link Activity} context to use for launching a new
2958 * authenticator-defined sub-Activity to prompt the user to
2959 * create an account or reauthenticate existing account; used
2960 * only to call startActivity(); if null, the prompt will not
2961 * be launched directly, but the necessary {@link Intent} will
2962 * be returned to the caller instead
2963 * @param callback Callback to invoke when the request completes, null for
2964 * no callback
2965 * @param handler {@link Handler} identifying the callback thread, null for
2966 * the main thread
2967 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
2968 * these fields if an activity was supplied and an account was added
2969 * to device or local credentials were updated::
2970 * <ul>
2971 * <li>{@link #KEY_ACCOUNT_NAME} - the name of the account created
2972 * <li>{@link #KEY_ACCOUNT_TYPE} - the type of the account
Hongming Jin8b442752016-06-26 10:36:21 -07002973 * <li>{@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check
2974 * status of the account
Sandra Kwan920f6ef2015-11-10 14:13:29 -08002975 * </ul>
2976 * If no activity was specified and additional information is needed
2977 * from user, the returned Bundle may contains only
2978 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
2979 * actual account creation process. If an error occurred,
2980 * {@link AccountManagerFuture#getResult()} throws:
2981 * <ul>
2982 * <li>{@link AuthenticatorException} if no authenticator was
2983 * registered for this account type or the authenticator failed to
2984 * respond
2985 * <li>{@link OperationCanceledException} if the operation was
2986 * canceled for any reason, including the user canceling the
2987 * creation process or adding accounts (of this type) has been
2988 * disabled by policy
2989 * <li>{@link IOException} if the authenticator experienced an I/O
2990 * problem creating a new account, usually because of network
2991 * trouble
2992 * </ul>
2993 * @see #startAddAccountSession and #startUpdateCredentialsSession
2994 */
2995 public AccountManagerFuture<Bundle> finishSession(
2996 final Bundle sessionBundle,
2997 final Activity activity,
2998 AccountManagerCallback<Bundle> callback,
2999 Handler handler) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08003000 return finishSessionAsUser(
3001 sessionBundle,
3002 activity,
3003 Process.myUserHandle(),
3004 callback,
3005 handler);
3006 }
3007
3008 /**
3009 * @see #finishSession
3010 * @hide
3011 */
3012 @SystemApi
3013 public AccountManagerFuture<Bundle> finishSessionAsUser(
3014 final Bundle sessionBundle,
3015 final Activity activity,
3016 final UserHandle userHandle,
3017 AccountManagerCallback<Bundle> callback,
3018 Handler handler) {
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003019 if (sessionBundle == null) {
3020 throw new IllegalArgumentException("sessionBundle is null");
3021 }
3022
3023 /* Add information required by add account flow */
3024 final Bundle appInfo = new Bundle();
3025 appInfo.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
3026
3027 return new AmsTask(activity, handler, callback) {
3028 @Override
3029 public void doWork() throws RemoteException {
Sandra Kwan0b84b452016-01-20 15:25:42 -08003030 mService.finishSessionAsUser(
3031 mResponse,
3032 sessionBundle,
3033 activity != null,
3034 appInfo,
3035 userHandle.getIdentifier());
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003036 }
3037 }.start();
3038 }
Sandra Kwan390c9d22016-01-12 14:13:37 -08003039
3040 /**
3041 * Checks whether {@link #updateCredentials} or {@link #startUpdateCredentialsSession} should be
3042 * called with respect to the specified account.
3043 * <p>
3044 * This method may be called from any thread, but the returned {@link AccountManagerFuture} must
3045 * not be used on the main thread.
3046 *
3047 * @param account The {@link Account} to be checked whether {@link #updateCredentials} or
3048 * {@link #startUpdateCredentialsSession} should be called
3049 * @param statusToken a String of token to check account staus
3050 * @param callback Callback to invoke when the request completes, null for no callback
3051 * @param handler {@link Handler} identifying the callback thread, null for the main thread
3052 * @return An {@link AccountManagerFuture} which resolves to a Boolean, true if the credentials
3053 * of the account should be updated.
Sandra Kwan390c9d22016-01-12 14:13:37 -08003054 */
Sandra Kwan390c9d22016-01-12 14:13:37 -08003055 public AccountManagerFuture<Boolean> isCredentialsUpdateSuggested(
3056 final Account account,
3057 final String statusToken,
3058 AccountManagerCallback<Boolean> callback,
3059 Handler handler) {
3060 if (account == null) {
3061 throw new IllegalArgumentException("account is null");
3062 }
3063
3064 if (TextUtils.isEmpty(statusToken)) {
3065 throw new IllegalArgumentException("status token is empty");
3066 }
3067
3068 return new Future2Task<Boolean>(handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08003069 @Override
Sandra Kwan390c9d22016-01-12 14:13:37 -08003070 public void doWork() throws RemoteException {
3071 mService.isCredentialsUpdateSuggested(
3072 mResponse,
3073 account,
3074 statusToken);
3075 }
Sandra Kwan0b84b452016-01-20 15:25:42 -08003076 @Override
Sandra Kwan390c9d22016-01-12 14:13:37 -08003077 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
3078 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
3079 throw new AuthenticatorException("no result in response");
3080 }
3081 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
3082 }
3083 }.start();
3084 }
Svetoslav Ganov5cb29732016-07-11 19:32:30 -07003085
3086 /**
3087 * Gets whether a given package under a user has access to an account.
3088 * Can be called only from the system UID.
3089 *
3090 * @param account The account for which to check.
3091 * @param packageName The package for which to check.
3092 * @param userHandle The user for which to check.
3093 * @return True if the package can access the account.
3094 *
3095 * @hide
3096 */
3097 public boolean hasAccountAccess(@NonNull Account account, @NonNull String packageName,
3098 @NonNull UserHandle userHandle) {
3099 try {
3100 return mService.hasAccountAccess(account, packageName, userHandle);
3101 } catch (RemoteException e) {
3102 throw e.rethrowFromSystemServer();
3103 }
3104 }
3105
3106 /**
3107 * Creates an intent to request access to a given account for a UID.
3108 * The returned intent should be stated for a result where {@link
3109 * Activity#RESULT_OK} result means access was granted whereas {@link
3110 * Activity#RESULT_CANCELED} result means access wasn't granted. Can
3111 * be called only from the system UID.
3112 *
3113 * @param account The account for which to request.
3114 * @param packageName The package name which to request.
3115 * @param userHandle The user for which to request.
3116 * @return The intent to request account access or null if the package
3117 * doesn't exist.
3118 *
3119 * @hide
3120 */
3121 public IntentSender createRequestAccountAccessIntentSenderAsUser(@NonNull Account account,
3122 @NonNull String packageName, @NonNull UserHandle userHandle) {
3123 try {
3124 return mService.createRequestAccountAccessIntentSenderAsUser(account, packageName,
3125 userHandle);
3126 } catch (RemoteException e) {
3127 throw e.rethrowFromSystemServer();
3128 }
3129 }
Fred Quintana60307342009-03-24 22:48:12 -07003130}