blob: 0f10c3980021360fc1baeb2bdfc802d134e44133 [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
Dmitry Dementyev16d69752018-10-30 14:56:53 -070019import android.annotation.BroadcastBehavior;
Dmitry Dementyev52745472016-12-02 10:27:45 -080020import android.annotation.IntDef;
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -070021import android.annotation.NonNull;
Tor Norbye80b530a2015-04-23 16:36:09 -070022import android.annotation.RequiresPermission;
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -070023import android.annotation.SdkConstant;
Dmitry Dementyev16d69752018-10-30 14:56:53 -070024import android.annotation.SdkConstant.SdkConstantType;
Tor Norbye80b530a2015-04-23 16:36:09 -070025import android.annotation.Size;
Sandra Kwana578d112015-12-16 16:01:43 -080026import android.annotation.SystemApi;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060027import android.annotation.SystemService;
Mathew Inwood1fde99a2018-08-06 16:43:30 +010028import android.annotation.UnsupportedAppUsage;
Fred Quintana60307342009-03-24 22:48:12 -070029import android.app.Activity;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080030import android.content.BroadcastReceiver;
Amith Yamasani12b8e132013-03-14 10:48:07 -070031import android.content.ComponentName;
Fred Quintana60307342009-03-24 22:48:12 -070032import android.content.Context;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080033import android.content.Intent;
Fred Quintanad9d2f112009-04-23 13:36:27 -070034import android.content.IntentFilter;
Svetoslav Ganov5cb29732016-07-11 19:32:30 -070035import android.content.IntentSender;
Amith Yamasani12b8e132013-03-14 10:48:07 -070036import android.content.res.Resources;
Costin Manolacheb6437242009-09-10 16:14:12 -070037import android.database.SQLException;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080038import android.os.Build;
Fred Quintanaa698f422009-04-08 19:14:54 -070039import android.os.Bundle;
40import android.os.Handler;
41import android.os.Looper;
Fred Quintana33269202009-04-20 16:05:10 -070042import android.os.Parcelable;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080043import android.os.RemoteException;
Amith Yamasani2c7bc262012-11-05 16:46:02 -080044import android.os.UserHandle;
Fred Quintanaf0fd8432010-03-08 12:48:05 -080045import android.text.TextUtils;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080046import android.util.Log;
47
48import com.android.internal.R;
Dmitry Dementyev16d69752018-10-30 14:56:53 -070049
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080050import com.google.android.collect.Maps;
Fred Quintana60307342009-03-24 22:48:12 -070051
Fred Quintanaa698f422009-04-08 19:14:54 -070052import java.io.IOException;
Dmitry Dementyev52745472016-12-02 10:27:45 -080053import java.lang.annotation.Retention;
54import java.lang.annotation.RetentionPolicy;
Fred Quintana1121bb52011-09-14 23:19:35 -070055import java.util.ArrayList;
Dmitry Dementyev01985ff2017-01-19 16:03:39 -080056import java.util.Arrays;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080057import java.util.HashMap;
Dmitry Dementyev01985ff2017-01-19 16:03:39 -080058import java.util.HashSet;
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -070059import java.util.List;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080060import java.util.Map;
Dmitry Dementyev01985ff2017-01-19 16:03:39 -080061import java.util.Set;
Fred Quintanaa698f422009-04-08 19:14:54 -070062import java.util.concurrent.Callable;
63import java.util.concurrent.CancellationException;
64import java.util.concurrent.ExecutionException;
65import java.util.concurrent.FutureTask;
Fred Quintanaa698f422009-04-08 19:14:54 -070066import java.util.concurrent.TimeUnit;
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -080067import java.util.concurrent.TimeoutException;
Fred Quintana60307342009-03-24 22:48:12 -070068
69/**
Dan Egnor661f0132010-02-19 11:23:00 -080070 * This class provides access to a centralized registry of the user's
Dan Egnor8e4378b2010-08-02 18:22:09 -070071 * online accounts. The user enters credentials (username and password) once
72 * per account, granting applications access to online resources with
73 * "one-click" approval.
Fred Quintana60307342009-03-24 22:48:12 -070074 *
Dan Egnor661f0132010-02-19 11:23:00 -080075 * <p>Different online services have different ways of handling accounts and
76 * authentication, so the account manager uses pluggable <em>authenticator</em>
Dan Egnor8e4378b2010-08-02 18:22:09 -070077 * modules for different <em>account types</em>. Authenticators (which may be
78 * written by third parties) handle the actual details of validating account
79 * credentials and storing account information. For example, Google, Facebook,
80 * and Microsoft Exchange each have their own authenticator.
Dan Egnor661f0132010-02-19 11:23:00 -080081 *
82 * <p>Many servers support some notion of an <em>authentication token</em>,
83 * which can be used to authenticate a request to the server without sending
84 * the user's actual password. (Auth tokens are normally created with a
85 * separate request which does include the user's credentials.) AccountManager
Dan Egnor8e4378b2010-08-02 18:22:09 -070086 * can generate auth tokens for applications, so the application doesn't need to
87 * handle passwords directly. Auth tokens are normally reusable and cached by
88 * AccountManager, but must be refreshed periodically. It's the responsibility
89 * of applications to <em>invalidate</em> auth tokens when they stop working so
90 * the AccountManager knows it needs to regenerate them.
Dan Egnor661f0132010-02-19 11:23:00 -080091 *
92 * <p>Applications accessing a server normally go through these steps:
93 *
94 * <ul>
95 * <li>Get an instance of AccountManager using {@link #get(Context)}.
96 *
97 * <li>List the available accounts using {@link #getAccountsByType} or
98 * {@link #getAccountsByTypeAndFeatures}. Normally applications will only
99 * be interested in accounts with one particular <em>type</em>, which
100 * identifies the authenticator. Account <em>features</em> are used to
101 * identify particular account subtypes and capabilities. Both the account
102 * type and features are authenticator-specific strings, and must be known by
103 * the application in coordination with its preferred authenticators.
104 *
105 * <li>Select one or more of the available accounts, possibly by asking the
106 * user for their preference. If no suitable accounts are available,
107 * {@link #addAccount} may be called to prompt the user to create an
108 * account of the appropriate type.
109 *
Dan Egnor8e4378b2010-08-02 18:22:09 -0700110 * <li><b>Important:</b> If the application is using a previously remembered
111 * account selection, it must make sure the account is still in the list
112 * of accounts returned by {@link #getAccountsByType}. Requesting an auth token
113 * for an account no longer on the device results in an undefined failure.
114 *
Dan Egnor661f0132010-02-19 11:23:00 -0800115 * <li>Request an auth token for the selected account(s) using one of the
116 * {@link #getAuthToken} methods or related helpers. Refer to the description
117 * of each method for exact usage and error handling details.
118 *
119 * <li>Make the request using the auth token. The form of the auth token,
120 * the format of the request, and the protocol used are all specific to the
Dan Egnor8e4378b2010-08-02 18:22:09 -0700121 * service you are accessing. The application may use whatever network and
122 * protocol libraries are useful.
Dan Egnor661f0132010-02-19 11:23:00 -0800123 *
124 * <li><b>Important:</b> If the request fails with an authentication error,
125 * it could be that a cached auth token is stale and no longer honored by
126 * the server. The application must call {@link #invalidateAuthToken} to remove
127 * the token from the cache, otherwise requests will continue failing! After
128 * invalidating the auth token, immediately go back to the "Request an auth
129 * token" step above. If the process fails the second time, then it can be
130 * treated as a "genuine" authentication failure and the user notified or other
131 * appropriate actions taken.
132 * </ul>
133 *
Dan Egnor8e4378b2010-08-02 18:22:09 -0700134 * <p>Some AccountManager methods may need to interact with the user to
Dan Egnor661f0132010-02-19 11:23:00 -0800135 * prompt for credentials, present options, or ask the user to add an account.
136 * The caller may choose whether to allow AccountManager to directly launch the
137 * necessary user interface and wait for the user, or to return an Intent which
138 * the caller may use to launch the interface, or (in some cases) to install a
139 * notification which the user can select at any time to launch the interface.
140 * To have AccountManager launch the interface directly, the caller must supply
141 * the current foreground {@link Activity} context.
142 *
143 * <p>Many AccountManager methods take {@link AccountManagerCallback} and
Dan Egnor8e4378b2010-08-02 18:22:09 -0700144 * {@link Handler} as parameters. These methods return immediately and
Dan Egnor661f0132010-02-19 11:23:00 -0800145 * run asynchronously. If a callback is provided then
146 * {@link AccountManagerCallback#run} will be invoked on the Handler's
147 * thread when the request completes, successfully or not.
Dan Egnor8e4378b2010-08-02 18:22:09 -0700148 * The result is retrieved by calling {@link AccountManagerFuture#getResult()}
149 * on the {@link AccountManagerFuture} returned by the method (and also passed
150 * to the callback). This method waits for the operation to complete (if
151 * necessary) and either returns the result or throws an exception if an error
152 * occurred during the operation. To make the request synchronously, call
Dan Egnor661f0132010-02-19 11:23:00 -0800153 * {@link AccountManagerFuture#getResult()} immediately on receiving the
Dan Egnor8e4378b2010-08-02 18:22:09 -0700154 * future from the method; no callback need be supplied.
Dan Egnor661f0132010-02-19 11:23:00 -0800155 *
156 * <p>Requests which may block, including
157 * {@link AccountManagerFuture#getResult()}, must never be called on
158 * the application's main event thread. These operations throw
159 * {@link IllegalStateException} if they are used on the main thread.
Fred Quintana60307342009-03-24 22:48:12 -0700160 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600161@SystemService(Context.ACCOUNT_SERVICE)
Fred Quintana60307342009-03-24 22:48:12 -0700162public class AccountManager {
Dmitry Dementyev52745472016-12-02 10:27:45 -0800163
Fred Quintana60307342009-03-24 22:48:12 -0700164 private static final String TAG = "AccountManager";
165
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700166 public static final int ERROR_CODE_REMOTE_EXCEPTION = 1;
167 public static final int ERROR_CODE_NETWORK_ERROR = 3;
168 public static final int ERROR_CODE_CANCELED = 4;
169 public static final int ERROR_CODE_INVALID_RESPONSE = 5;
170 public static final int ERROR_CODE_UNSUPPORTED_OPERATION = 6;
171 public static final int ERROR_CODE_BAD_ARGUMENTS = 7;
172 public static final int ERROR_CODE_BAD_REQUEST = 8;
Jatin Lodhia3df7d692013-03-27 10:57:23 -0700173 public static final int ERROR_CODE_BAD_AUTHENTICATION = 9;
Fred Quintana756b7352009-10-21 13:43:10 -0700174
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800175 /** @hide */
176 public static final int ERROR_CODE_USER_RESTRICTED = 100;
Alexandra Gherghina999d3942014-07-03 11:40:08 +0100177 /** @hide */
178 public static final int ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE = 101;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800179
Dan Egnor661f0132010-02-19 11:23:00 -0800180 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700181 * Bundle key used for the {@link String} account name in results
Dan Egnor661f0132010-02-19 11:23:00 -0800182 * from methods which return information about a particular account.
183 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700184 public static final String KEY_ACCOUNT_NAME = "authAccount";
Dan Egnor661f0132010-02-19 11:23:00 -0800185
186 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700187 * Bundle key used for the {@link String} account type in results
Dan Egnor661f0132010-02-19 11:23:00 -0800188 * from methods which return information about a particular account.
189 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700190 public static final String KEY_ACCOUNT_TYPE = "accountType";
Dan Egnor661f0132010-02-19 11:23:00 -0800191
192 /**
Svet Ganovd4696122016-09-24 13:57:45 -0700193 * Bundle key used for the account access id used for noting the
194 * account was accessed when unmarshaled from a parcel.
Svet Ganovf6d424f12016-09-20 20:18:53 -0700195 *
196 * @hide
197 */
Svet Ganovd4696122016-09-24 13:57:45 -0700198 public static final String KEY_ACCOUNT_ACCESS_ID = "accountAccessId";
Svet Ganovf6d424f12016-09-20 20:18:53 -0700199
200 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700201 * Bundle key used for the auth token value in results
Dan Egnor661f0132010-02-19 11:23:00 -0800202 * from {@link #getAuthToken} and friends.
203 */
204 public static final String KEY_AUTHTOKEN = "authtoken";
205
206 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700207 * Bundle key used for an {@link Intent} in results from methods that
Dan Egnor661f0132010-02-19 11:23:00 -0800208 * may require the caller to interact with the user. The Intent can
209 * be used to start the corresponding user interface activity.
210 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700211 public static final String KEY_INTENT = "intent";
Dan Egnor661f0132010-02-19 11:23:00 -0800212
213 /**
Dan Egnor8e4378b2010-08-02 18:22:09 -0700214 * Bundle key used to supply the password directly in options to
Dan Egnor661f0132010-02-19 11:23:00 -0800215 * {@link #confirmCredentials}, rather than prompting the user with
216 * the standard password prompt.
217 */
218 public static final String KEY_PASSWORD = "password";
219
220 public static final String KEY_ACCOUNTS = "accounts";
Brian Carlstrom46703b02011-04-06 15:41:29 -0700221
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700222 public static final String KEY_ACCOUNT_AUTHENTICATOR_RESPONSE = "accountAuthenticatorResponse";
223 public static final String KEY_ACCOUNT_MANAGER_RESPONSE = "accountManagerResponse";
Dan Egnor661f0132010-02-19 11:23:00 -0800224 public static final String KEY_AUTHENTICATOR_TYPES = "authenticator_types";
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700225 public static final String KEY_AUTH_FAILED_MESSAGE = "authFailedMessage";
226 public static final String KEY_AUTH_TOKEN_LABEL = "authTokenLabelKey";
Dan Egnor661f0132010-02-19 11:23:00 -0800227 public static final String KEY_BOOLEAN_RESULT = "booleanResult";
228 public static final String KEY_ERROR_CODE = "errorCode";
229 public static final String KEY_ERROR_MESSAGE = "errorMessage";
230 public static final String KEY_USERDATA = "userdata";
Costin Manolacheb61e8fb2011-09-08 11:26:09 -0700231
Costin Manolachea40c6302010-12-13 14:50:45 -0800232 /**
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800233 * Bundle key used to supply the last time the credentials of the account
234 * were authenticated successfully. Time is specified in milliseconds since
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700235 * epoch. Associated time is updated on successful authentication of account
236 * on adding account, confirming credentials, or updating credentials.
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800237 */
Simranjit Singh Kohli1663b442015-04-28 11:11:12 -0700238 public static final String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime";
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -0800239
240 /**
sunjian87d0c3c2017-07-14 11:54:46 -0700241 * The UID of caller app.
Costin Manolachea40c6302010-12-13 14:50:45 -0800242 */
243 public static final String KEY_CALLER_UID = "callerUid";
sunjian87d0c3c2017-07-14 11:54:46 -0700244
245 /**
246 * The process id of caller app.
247 */
Costin Manolachea40c6302010-12-13 14:50:45 -0800248 public static final String KEY_CALLER_PID = "callerPid";
Dan Egnor661f0132010-02-19 11:23:00 -0800249
Costin Manolached6060452011-01-24 16:11:36 -0800250 /**
Fred Quintanaad93a322011-09-08 13:21:01 -0700251 * The Android package of the caller will be set in the options bundle by the
252 * {@link AccountManager} and will be passed to the AccountManagerService and
253 * to the AccountAuthenticators. The uid of the caller will be known by the
254 * AccountManagerService as well as the AccountAuthenticators so they will be able to
255 * verify that the package is consistent with the uid (a uid might be shared by many
256 * packages).
257 */
258 public static final String KEY_ANDROID_PACKAGE_NAME = "androidPackageName";
259
260 /**
Costin Manolached6060452011-01-24 16:11:36 -0800261 * Boolean, if set and 'customTokens' the authenticator is responsible for
262 * notifications.
263 * @hide
264 */
265 public static final String KEY_NOTIFY_ON_FAILURE = "notifyOnAuthFailure";
266
Sandra Kwan78812282015-11-04 11:19:47 -0800267 /**
268 * Bundle key used for a {@link Bundle} in result from
269 * {@link #startAddAccountSession} and friends which returns session data
270 * for installing an account later.
271 */
272 public static final String KEY_ACCOUNT_SESSION_BUNDLE = "accountSessionBundle";
273
274 /**
275 * Bundle key used for the {@link String} account status token in result
276 * from {@link #startAddAccountSession} and friends which returns
277 * information about a particular account.
278 */
279 public static final String KEY_ACCOUNT_STATUS_TOKEN = "accountStatusToken";
280
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700281 public static final String ACTION_AUTHENTICATOR_INTENT =
282 "android.accounts.AccountAuthenticator";
283 public static final String AUTHENTICATOR_META_DATA_NAME =
Dan Egnor661f0132010-02-19 11:23:00 -0800284 "android.accounts.AccountAuthenticator";
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700285 public static final String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
286
Dmitry Dementyev52745472016-12-02 10:27:45 -0800287 /** @hide */
288 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700289 @IntDef(prefix = { "VISIBILITY_" }, value = {
290 VISIBILITY_UNDEFINED,
291 VISIBILITY_VISIBLE,
292 VISIBILITY_USER_MANAGED_VISIBLE,
293 VISIBILITY_NOT_VISIBLE,
294 VISIBILITY_USER_MANAGED_NOT_VISIBLE
295 })
Dmitry Dementyev52745472016-12-02 10:27:45 -0800296 public @interface AccountVisibility {
297 }
298
299 /**
Dmitry Dementyev06f32e02017-02-16 17:47:48 -0800300 * Account visibility was not set. Default visibility value will be used.
301 * See {@link #PACKAGE_NAME_KEY_LEGACY_VISIBLE}, {@link #PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE}
Dmitry Dementyev52745472016-12-02 10:27:45 -0800302 */
303 public static final int VISIBILITY_UNDEFINED = 0;
304
305 /**
306 * Account is always visible to given application and only authenticator can revoke visibility.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800307 */
308 public static final int VISIBILITY_VISIBLE = 1;
309
310 /**
311 * Account is visible to given application, but user can revoke visibility.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800312 */
313 public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2;
314
315 /**
316 * Account is not visible to given application and only authenticator can grant visibility.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800317 */
318 public static final int VISIBILITY_NOT_VISIBLE = 3;
319
320 /**
321 * Account is not visible to given application, but user can reveal it, for example, using
322 * {@link #newChooseAccountIntent(Account, List, String[], String, String, String[], Bundle)}
Dmitry Dementyev52745472016-12-02 10:27:45 -0800323 */
324 public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4;
325
326 /**
Svet Ganovf6d424f12016-09-20 20:18:53 -0700327 * Token type for the special case where a UID has access only to an account
328 * but no authenticator specific auth token types.
Dmitry Dementyev2e22cfb2017-01-09 18:42:14 +0000329 *
Svetoslav Ganov5cb29732016-07-11 19:32:30 -0700330 * @hide
331 */
Svet Ganovf6d424f12016-09-20 20:18:53 -0700332 public static final String ACCOUNT_ACCESS_TOKEN_TYPE =
333 "com.android.AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE";
Svetoslav Ganov5cb29732016-07-11 19:32:30 -0700334
Mathew Inwood1fde99a2018-08-06 16:43:30 +0100335 @UnsupportedAppUsage
Fred Quintana60307342009-03-24 22:48:12 -0700336 private final Context mContext;
337 private final IAccountManager mService;
Fred Quintanad9d2f112009-04-23 13:36:27 -0700338 private final Handler mMainHandler;
Dan Egnor661f0132010-02-19 11:23:00 -0800339
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700340 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -0800341 * Action sent as a broadcast Intent by the AccountsService when accounts are added, accounts
342 * are removed, or an account's credentials (saved password, etc) are changed.
Dan Egnor661f0132010-02-19 11:23:00 -0800343 *
344 * @see #addOnAccountsUpdatedListener
Dmitry Dementyeva461e302017-04-12 11:00:48 -0700345 * @see #ACTION_ACCOUNT_REMOVED
Dmitry Dementyev52745472016-12-02 10:27:45 -0800346 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -0700347 * @deprecated use {@link #addOnAccountsUpdatedListener} to get account updates in runtime.
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700348 */
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700349 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
350 @BroadcastBehavior(includeBackground = true)
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700351 public static final String LOGIN_ACCOUNTS_CHANGED_ACTION =
352 "android.accounts.LOGIN_ACCOUNTS_CHANGED";
Fred Quintana60307342009-03-24 22:48:12 -0700353
Fred Quintana33269202009-04-20 16:05:10 -0700354 /**
Dmitry Dementyevb6a7dc02017-04-18 13:43:31 -0700355 * Action sent as a broadcast Intent by the AccountsService when any account is removed
356 * or renamed. Only applications which were able to see the account will receive the intent.
357 * Intent extra will include the following fields:
358 * <ul>
359 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the removed account
360 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
361 * </ul>
Dmitry Dementyeva461e302017-04-12 11:00:48 -0700362 */
363 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
364 @BroadcastBehavior(includeBackground = true)
365 public static final String ACTION_ACCOUNT_REMOVED =
366 "android.accounts.action.ACCOUNT_REMOVED";
367
368 /**
Dmitry Dementyev8882d882017-03-14 17:25:46 -0700369 * Action sent as a broadcast Intent to specific package by the AccountsService
370 * when account visibility or account's credentials (saved password, etc) are changed.
371 *
372 * @see #addOnAccountsUpdatedListener
373 *
374 * @hide
375 */
376 public static final String ACTION_VISIBLE_ACCOUNTS_CHANGED =
377 "android.accounts.action.VISIBLE_ACCOUNTS_CHANGED";
378
379 /**
Dmitry Dementyevd6f06722017-04-05 12:43:26 -0700380 * Key to set visibility for applications which satisfy one of the following conditions:
381 * <ul>
382 * <li>Target API level below {@link android.os.Build.VERSION_CODES#O} and have
383 * deprecated {@link android.Manifest.permission#GET_ACCOUNTS} permission.
384 * </li>
385 * <li> Have {@link android.Manifest.permission#GET_ACCOUNTS_PRIVILEGED} permission. </li>
386 * <li> Have the same signature as authenticator. </li>
387 * <li> Have {@link android.Manifest.permission#READ_CONTACTS} permission and
388 * account type may be associated with contacts data - (verified by
389 * {@link android.Manifest.permission#WRITE_CONTACTS} permission check for the authenticator).
390 * </li>
391 * </ul>
392 * See {@link #getAccountVisibility}. If the value was not set by authenticator
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800393 * {@link #VISIBILITY_USER_MANAGED_VISIBLE} is used.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800394 */
Dmitry Dementyev85d8a342017-05-02 17:33:17 -0700395 public static final String PACKAGE_NAME_KEY_LEGACY_VISIBLE =
396 "android:accounts:key_legacy_visible";
397
398 /**
399 * Key to set default visibility for applications which don't satisfy conditions in
Jeff Sharkey67f9d502017-08-05 13:49:13 -0600400 * {@link #PACKAGE_NAME_KEY_LEGACY_VISIBLE}. If the value was not set by authenticator
Dmitry Dementyev85d8a342017-05-02 17:33:17 -0700401 * {@link #VISIBILITY_USER_MANAGED_NOT_VISIBLE} is used.
402 */
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800403 public static final String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE =
Dmitry Dementyevcbe1bd12017-04-25 17:02:47 -0700404 "android:accounts:key_legacy_not_visible";
Dmitry Dementyev52745472016-12-02 10:27:45 -0800405
406 /**
Fred Quintana33269202009-04-20 16:05:10 -0700407 * @hide
408 */
Mathew Inwood1fde99a2018-08-06 16:43:30 +0100409 @UnsupportedAppUsage
Fred Quintana60307342009-03-24 22:48:12 -0700410 public AccountManager(Context context, IAccountManager service) {
411 mContext = context;
412 mService = service;
Fred Quintanad9d2f112009-04-23 13:36:27 -0700413 mMainHandler = new Handler(mContext.getMainLooper());
Fred Quintana60307342009-03-24 22:48:12 -0700414 }
415
Fred Quintana0eabf022009-04-27 15:08:17 -0700416 /**
417 * @hide used for testing only
418 */
Mathew Inwood1fde99a2018-08-06 16:43:30 +0100419 @UnsupportedAppUsage
Fred Quintana0eabf022009-04-27 15:08:17 -0700420 public AccountManager(Context context, IAccountManager service, Handler handler) {
421 mContext = context;
422 mService = service;
423 mMainHandler = handler;
424 }
425
Fred Quintana756b7352009-10-21 13:43:10 -0700426 /**
Fred Quintanaf0fd8432010-03-08 12:48:05 -0800427 * @hide for internal use only
428 */
429 public static Bundle sanitizeResult(Bundle result) {
Fred Quintana382601f2010-03-25 12:25:10 -0700430 if (result != null) {
431 if (result.containsKey(KEY_AUTHTOKEN)
432 && !TextUtils.isEmpty(result.getString(KEY_AUTHTOKEN))) {
433 final Bundle newResult = new Bundle(result);
434 newResult.putString(KEY_AUTHTOKEN, "<omitted for logging purposes>");
435 return newResult;
436 }
Fred Quintanaf0fd8432010-03-08 12:48:05 -0800437 }
438 return result;
439 }
440
441 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800442 * Gets an AccountManager instance associated with a Context.
443 * The {@link Context} will be used as long as the AccountManager is
444 * active, so make sure to use a {@link Context} whose lifetime is
445 * commensurate with any listeners registered to
446 * {@link #addOnAccountsUpdatedListener} or similar methods.
447 *
448 * <p>It is safe to call this method from the main thread.
449 *
450 * <p>No permission is required to call this method.
451 *
Fred Quintana756b7352009-10-21 13:43:10 -0700452 * @param context The {@link Context} to use when necessary
Dan Egnor661f0132010-02-19 11:23:00 -0800453 * @return An {@link AccountManager} instance
Fred Quintana756b7352009-10-21 13:43:10 -0700454 */
Fred Quintanaa698f422009-04-08 19:14:54 -0700455 public static AccountManager get(Context context) {
Fred Quintana382601f2010-03-25 12:25:10 -0700456 if (context == null) throw new IllegalArgumentException("context is null");
Fred Quintanaa698f422009-04-08 19:14:54 -0700457 return (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
458 }
459
Fred Quintana756b7352009-10-21 13:43:10 -0700460 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -0800461 * Gets the saved password associated with the account. This is intended for authenticators and
462 * related code; applications should get an auth token instead.
Dan Egnor661f0132010-02-19 11:23:00 -0800463 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800464 * <p>
465 * It is safe to call this method from the main thread.
Dan Egnor661f0132010-02-19 11:23:00 -0800466 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800467 * <p>
468 * This method requires the caller to have a signature match with the authenticator that owns
469 * the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -0800470 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800471 * <p>
472 * <b>NOTE:</b> If targeting your app to work on API level
473 * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before, AUTHENTICATE_ACCOUNTS
474 * permission is needed for those platforms. See docs for this function in API level
475 * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -0700476 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700477 * @param account The account to query for a password. Must not be {@code null}.
Dan Egnor661f0132010-02-19 11:23:00 -0800478 * @return The account's password, null if none or if the account doesn't exist
Fred Quintana756b7352009-10-21 13:43:10 -0700479 */
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700480 public String getPassword(final Account account) {
Fred Quintana382601f2010-03-25 12:25:10 -0700481 if (account == null) throw new IllegalArgumentException("account is null");
Fred Quintana60307342009-03-24 22:48:12 -0700482 try {
483 return mService.getPassword(account);
484 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700485 throw e.rethrowFromSystemServer();
Fred Quintana60307342009-03-24 22:48:12 -0700486 }
487 }
488
Fred Quintana756b7352009-10-21 13:43:10 -0700489 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -0800490 * Gets the user data named by "key" associated with the account. This is intended for
491 * authenticators and related code to store arbitrary metadata along with accounts. The meaning
492 * of the keys and values is up to the authenticator for the account.
Dan Egnor661f0132010-02-19 11:23:00 -0800493 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800494 * <p>
495 * It is safe to call this method from the main thread.
Dan Egnor661f0132010-02-19 11:23:00 -0800496 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800497 * <p>
498 * This method requires the caller to have a signature match with the authenticator that owns
499 * the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -0800500 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800501 * <p>
502 * <b>NOTE:</b> If targeting your app to work on API level
503 * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before, AUTHENTICATE_ACCOUNTS
504 * permission is needed for those platforms. See docs for this function in API level
505 * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -0700506 *
Dan Egnor661f0132010-02-19 11:23:00 -0800507 * @param account The account to query for user data
Dmitry Dementyev16d69752018-10-30 14:56:53 -0700508 * @return The user data, null if the account, key doesn't exist, or the user is locked
Fred Quintana756b7352009-10-21 13:43:10 -0700509 */
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700510 public String getUserData(final Account account, final String key) {
Fred Quintana382601f2010-03-25 12:25:10 -0700511 if (account == null) throw new IllegalArgumentException("account is null");
512 if (key == null) throw new IllegalArgumentException("key is null");
Fred Quintana60307342009-03-24 22:48:12 -0700513 try {
514 return mService.getUserData(account, key);
515 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700516 throw e.rethrowFromSystemServer();
Fred Quintana60307342009-03-24 22:48:12 -0700517 }
518 }
519
Fred Quintana756b7352009-10-21 13:43:10 -0700520 /**
Dan Egnor661f0132010-02-19 11:23:00 -0800521 * Lists the currently registered authenticators.
522 *
523 * <p>It is safe to call this method from the main thread.
524 *
525 * <p>No permission is required to call this method.
526 *
527 * @return An array of {@link AuthenticatorDescription} for every
528 * authenticator known to the AccountManager service. Empty (never
529 * null) if no authenticators are known.
Fred Quintana756b7352009-10-21 13:43:10 -0700530 */
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700531 public AuthenticatorDescription[] getAuthenticatorTypes() {
Fred Quintanaa698f422009-04-08 19:14:54 -0700532 try {
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100533 return mService.getAuthenticatorTypes(UserHandle.getCallingUserId());
534 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700535 throw e.rethrowFromSystemServer();
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100536 }
537 }
538
539 /**
540 * @hide
541 * Lists the currently registered authenticators for a given user id.
542 *
543 * <p>It is safe to call this method from the main thread.
544 *
545 * <p>The caller has to be in the same user or have the permission
546 * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
547 *
548 * @return An array of {@link AuthenticatorDescription} for every
549 * authenticator known to the AccountManager service. Empty (never
550 * null) if no authenticators are known.
551 */
552 public AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) {
553 try {
554 return mService.getAuthenticatorTypes(userId);
Fred Quintanaa698f422009-04-08 19:14:54 -0700555 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700556 throw e.rethrowFromSystemServer();
Fred Quintanaa698f422009-04-08 19:14:54 -0700557 }
558 }
559
Fred Quintana756b7352009-10-21 13:43:10 -0700560 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -0800561 * Lists all accounts visible to the caller regardless of type. Equivalent to
562 * getAccountsByType(null). These accounts may be visible because the user granted access to the
563 * account, or the AbstractAcccountAuthenticator managing the account did so or because the
564 * client shares a signature with the managing AbstractAccountAuthenticator.
Dan Egnor661f0132010-02-19 11:23:00 -0800565 *
Kevin Hufnaglec665fed2019-09-30 17:59:49 +0000566 * <div class="caution"><p><b>Caution: </b>This method returns personal and sensitive user data.
567 * If your app accesses, collects, uses, or shares personal and sensitive data, you must clearly
568 * disclose that fact to users. For apps published on Google Play, policies protecting user data
569 * require that you do the following:</p>
570 * <ul>
571 * <li>Disclose to the user how your app accesses, collects, uses, or shares personal and
572 * sensitive data. Learn more about
573 * <a href="https://play.google.com/about/privacy-security-deception/user-data/#!#personal-sensitive">acceptable
574 * disclosure and consent</a>.</li>
575 * <li>Provide a privacy policy that describes your use of this data on- and off-device.</li>
576 * </ul>
577 * <p>To learn more, visit the
578 * <a href="https://play.google.com/about/privacy-security-deception/user-data">Google Play
579 * Policy regarding user data</a>.</p></div>
580 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800581 * <p>
582 * It is safe to call this method from the main thread.
Dan Egnor661f0132010-02-19 11:23:00 -0800583 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800584 * @return An array of {@link Account}, one for each account. Empty (never null) if no accounts
585 * have been added.
Fred Quintana756b7352009-10-21 13:43:10 -0700586 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700587 @NonNull
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700588 public Account[] getAccounts() {
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000589 try {
590 return mService.getAccounts(null, mContext.getOpPackageName());
591 } catch (RemoteException e) {
592 throw e.rethrowFromSystemServer();
593 }
Fred Quintana60307342009-03-24 22:48:12 -0700594 }
595
Fred Quintana756b7352009-10-21 13:43:10 -0700596 /**
Amith Yamasani27db4682013-03-30 17:07:47 -0700597 * @hide
Dmitry Dementyev52745472016-12-02 10:27:45 -0800598 * Lists all accounts visible to caller regardless of type for a given user id. Equivalent to
599 * getAccountsByType(null).
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100600 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800601 * <p>
602 * It is safe to call this method from the main thread.
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100603 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800604 * @return An array of {@link Account}, one for each account. Empty (never null) if no accounts
605 * have been added.
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100606 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700607 @NonNull
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100608 public Account[] getAccountsAsUser(int userId) {
609 try {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700610 return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName());
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100611 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700612 throw e.rethrowFromSystemServer();
Alexandra Gherghinac1cf1612014-06-05 10:49:14 +0100613 }
614 }
615
616 /**
617 * @hide
Amith Yamasani27db4682013-03-30 17:07:47 -0700618 * For use by internal activities. Returns the list of accounts that the calling package
619 * is authorized to use, particularly for shared accounts.
620 * @param packageName package name of the calling app.
621 * @param uid the uid of the calling app.
622 * @return the accounts that are available to this package and user.
623 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700624 @NonNull
Amith Yamasani27db4682013-03-30 17:07:47 -0700625 public Account[] getAccountsForPackage(String packageName, int uid) {
626 try {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700627 return mService.getAccountsForPackage(packageName, uid, mContext.getOpPackageName());
Amith Yamasani27db4682013-03-30 17:07:47 -0700628 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700629 throw re.rethrowFromSystemServer();
Amith Yamasani27db4682013-03-30 17:07:47 -0700630 }
631 }
632
633 /**
Dmitry Dementyev85d8a342017-05-02 17:33:17 -0700634 * Returns the accounts visible to the specified package in an environment where some apps are
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800635 * not authorized to view all accounts. This method can only be called by system apps and
Dmitry Dementyev85d8a342017-05-02 17:33:17 -0700636 * authenticators managing the type.
637 * Beginning API level {@link android.os.Build.VERSION_CODES#O} it also return accounts
Jeff Sharkey67f9d502017-08-05 13:49:13 -0600638 * which user can make visible to the application (see {@link #VISIBILITY_USER_MANAGED_VISIBLE}).
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800639 *
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700640 * @param type The type of accounts to return, null to retrieve all accounts
641 * @param packageName The package name of the app for which the accounts are to be returned
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800642 * @return An array of {@link Account}, one per matching account. Empty (never null) if no
Dmitry Dementyev85d8a342017-05-02 17:33:17 -0700643 * accounts of the specified type can be accessed by the package.
644 *
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700645 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700646 @NonNull
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700647 public Account[] getAccountsByTypeForPackage(String type, String packageName) {
648 try {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700649 return mService.getAccountsByTypeForPackage(type, packageName,
650 mContext.getOpPackageName());
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700651 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700652 throw re.rethrowFromSystemServer();
Amith Yamasani3b458ad2013-04-18 18:40:07 -0700653 }
654 }
655
656 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -0800657 * Lists all accounts of particular type visible to the caller. These accounts may be visible
658 * because the user granted access to the account, or the AbstractAcccountAuthenticator managing
659 * the account did so or because the client shares a signature with the managing
660 * AbstractAccountAuthenticator.
Dan Egnor661f0132010-02-19 11:23:00 -0800661 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800662 * <p>
663 * The account type is a string token corresponding to the authenticator and useful domain of
664 * the account. For example, there are types corresponding to Google and Facebook. The exact
665 * string token to use will be published somewhere associated with the authenticator in
666 * question.
Kevin Hufnaglec665fed2019-09-30 17:59:49 +0000667 * </p>
668 *
669 * <div class="caution"><p><b>Caution: </b>This method returns personal and sensitive user data.
670 * If your app accesses, collects, uses, or shares personal and sensitive data, you must clearly
671 * disclose that fact to users. For apps published on Google Play, policies protecting user data
672 * require that you do the following:</p>
673 * <ul>
674 * <li>Disclose to the user how your app accesses, collects, uses, or shares personal and
675 * sensitive data. Learn more about
676 * <a href="https://play.google.com/about/privacy-security-deception/user-data/#!#personal-sensitive">acceptable
677 * disclosure and consent</a>.</li>
678 * <li>Provide a privacy policy that describes your use of this data on- and off-device.</li>
679 * </ul>
680 * <p>To learn more, visit the
681 * <a href="https://play.google.com/about/privacy-security-deception/user-data">Google Play
682 * Policy regarding user data</a>.</p></div>
Dan Egnor661f0132010-02-19 11:23:00 -0800683 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800684 * <p>
685 * It is safe to call this method from the main thread.
Dan Egnor661f0132010-02-19 11:23:00 -0800686 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800687 * <p>
688 * Caller targeting API level {@link android.os.Build.VERSION_CODES#O} and above, will get list
Dmitry Dementyev85d8a342017-05-02 17:33:17 -0700689 * of accounts made visible to it by user
690 * (see {@link #newChooseAccountIntent(Account, List, String[], String,
691 * String, String[], Bundle)}) or AbstractAcccountAuthenticator
Jeff Sharkey67f9d502017-08-05 13:49:13 -0600692 * using {@link #setAccountVisibility}.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800693 * {@link android.Manifest.permission#GET_ACCOUNTS} permission is not used.
694 *
695 * <p>
696 * Caller targeting API level below {@link android.os.Build.VERSION_CODES#O} that have not been
697 * granted the {@link android.Manifest.permission#GET_ACCOUNTS} permission, will only see those
698 * accounts managed by AbstractAccountAuthenticators whose signature matches the client.
699 *
700 * <p>
701 * <b>NOTE:</b> If targeting your app to work on API level
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800702 * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before,
703 * {@link android.Manifest.permission#GET_ACCOUNTS} permission is
Dmitry Dementyev52745472016-12-02 10:27:45 -0800704 * needed for those platforms, irrespective of uid or signature match. See docs for this
705 * function in API level {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
Ian Pedowitz358e51f2016-03-15 17:08:27 +0000706 *
707 * @param type The type of accounts to return, null to retrieve all accounts
Dmitry Dementyev52745472016-12-02 10:27:45 -0800708 * @return An array of {@link Account}, one per matching account. Empty (never null) if no
709 * accounts of the specified type have been added.
Fred Quintana756b7352009-10-21 13:43:10 -0700710 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700711 @NonNull
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700712 public Account[] getAccountsByType(String type) {
Jeff Sharkeyad357d12018-02-02 13:25:31 -0700713 return getAccountsByTypeAsUser(type, mContext.getUser());
Amith Yamasani2c7bc262012-11-05 16:46:02 -0800714 }
715
716 /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -0700717 @NonNull
Mathew Inwood1fde99a2018-08-06 16:43:30 +0100718 @UnsupportedAppUsage
Amith Yamasani2c7bc262012-11-05 16:46:02 -0800719 public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
Fred Quintana60307342009-03-24 22:48:12 -0700720 try {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700721 return mService.getAccountsAsUser(type, userHandle.getIdentifier(),
722 mContext.getOpPackageName());
Fred Quintana60307342009-03-24 22:48:12 -0700723 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700724 throw e.rethrowFromSystemServer();
Fred Quintana60307342009-03-24 22:48:12 -0700725 }
726 }
727
Fred Quintana756b7352009-10-21 13:43:10 -0700728 /**
Fred Quintanad9640ec2012-05-23 12:37:00 -0700729 * Change whether or not an app (identified by its uid) is allowed to retrieve an authToken
730 * for an account.
731 * <p>
732 * This is only meant to be used by system activities and is not in the SDK.
733 * @param account The account whose permissions are being modified
734 * @param authTokenType The type of token whose permissions are being modified
735 * @param uid The uid that identifies the app which is being granted or revoked permission.
736 * @param value true is permission is being granted, false for revoked
737 * @hide
738 */
739 public void updateAppPermission(Account account, String authTokenType, int uid, boolean value) {
740 try {
741 mService.updateAppPermission(account, authTokenType, uid, value);
742 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700743 throw e.rethrowFromSystemServer();
Fred Quintanad9640ec2012-05-23 12:37:00 -0700744 }
745 }
746
747 /**
748 * Get the user-friendly label associated with an authenticator's auth token.
749 * @param accountType the type of the authenticator. must not be null.
750 * @param authTokenType the token type. must not be null.
751 * @param callback callback to invoke when the result is available. may be null.
752 * @param handler the handler on which to invoke the callback, or null for the main thread
753 * @return a future containing the label string
754 * @hide
755 */
756 public AccountManagerFuture<String> getAuthTokenLabel(
757 final String accountType, final String authTokenType,
758 AccountManagerCallback<String> callback, Handler handler) {
759 if (accountType == null) throw new IllegalArgumentException("accountType is null");
760 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
761 return new Future2Task<String>(handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -0800762 @Override
Fred Quintanad9640ec2012-05-23 12:37:00 -0700763 public void doWork() throws RemoteException {
764 mService.getAuthTokenLabel(mResponse, accountType, authTokenType);
765 }
766
767 @Override
768 public String bundleToResult(Bundle bundle) throws AuthenticatorException {
769 if (!bundle.containsKey(KEY_AUTH_TOKEN_LABEL)) {
770 throw new AuthenticatorException("no result in response");
771 }
772 return bundle.getString(KEY_AUTH_TOKEN_LABEL);
773 }
774 }.start();
775 }
776
777 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -0800778 * Finds out whether a particular account has all the specified features. Account features are
779 * authenticator-specific string tokens identifying boolean account properties. For example,
780 * features are used to tell whether Google accounts have a particular service (such as Google
781 * Calendar or Google Talk) enabled. The feature names and their meanings are published
782 * somewhere associated with the authenticator in question.
Dan Egnor661f0132010-02-19 11:23:00 -0800783 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800784 * <p>
785 * This method may be called from any thread, but the returned {@link AccountManagerFuture} must
786 * not be used on the main thread.
Dan Egnor661f0132010-02-19 11:23:00 -0800787 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800788 * <p>
789 * If caller target API level is below {@link android.os.Build.VERSION_CODES#O}, it is
790 * required to hold the permission {@link android.Manifest.permission#GET_ACCOUNTS} or have a
791 * signature match with the AbstractAccountAuthenticator that manages the account.
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800792 *
793 * @param account The {@link Account} to test
Dan Egnor661f0132010-02-19 11:23:00 -0800794 * @param features An array of the account features to check
Dmitry Dementyev52745472016-12-02 10:27:45 -0800795 * @param callback Callback to invoke when the request completes, null for no callback
796 * @param handler {@link Handler} identifying the callback thread, null for the main thread
797 * @return An {@link AccountManagerFuture} which resolves to a Boolean, true if the account
798 * exists and has all of the specified features.
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800799 */
Fred Quintana3084a6f2010-01-14 18:02:03 -0800800 public AccountManagerFuture<Boolean> hasFeatures(final Account account,
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800801 final String[] features,
802 AccountManagerCallback<Boolean> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -0700803 if (account == null) throw new IllegalArgumentException("account is null");
804 if (features == null) throw new IllegalArgumentException("features is null");
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800805 return new Future2Task<Boolean>(handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -0800806 @Override
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800807 public void doWork() throws RemoteException {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700808 mService.hasFeatures(mResponse, account, features, mContext.getOpPackageName());
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800809 }
Sandra Kwan0b84b452016-01-20 15:25:42 -0800810 @Override
Fred Quintanabb68a4f2010-01-13 17:28:39 -0800811 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
812 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
813 throw new AuthenticatorException("no result in response");
814 }
815 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
816 }
817 }.start();
818 }
819
820 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -0800821 * Lists all accounts of a type which have certain features. The account type identifies the
822 * authenticator (see {@link #getAccountsByType}). Account features are authenticator-specific
823 * string tokens identifying boolean account properties (see {@link #hasFeatures}).
Fred Quintana756b7352009-10-21 13:43:10 -0700824 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800825 * <p>
826 * Unlike {@link #getAccountsByType}, this method calls the authenticator, which may contact the
827 * server or do other work to check account features, so the method returns an
828 * {@link AccountManagerFuture}.
Fred Quintanaa698f422009-04-08 19:14:54 -0700829 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800830 * <p>
831 * This method may be called from any thread, but the returned {@link AccountManagerFuture} must
832 * not be used on the main thread.
Fred Quintana756b7352009-10-21 13:43:10 -0700833 *
Dmitry Dementyev52745472016-12-02 10:27:45 -0800834 * <p>
835 * Caller targeting API level {@link android.os.Build.VERSION_CODES#O} and above, will get list
Dmitry Dementyev85d8a342017-05-02 17:33:17 -0700836 * of accounts made visible to it by user
837 * (see {@link #newChooseAccountIntent(Account, List, String[], String,
838 * String, String[], Bundle)}) or AbstractAcccountAuthenticator
Jeff Sharkey67f9d502017-08-05 13:49:13 -0600839 * using {@link #setAccountVisibility}.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800840 * {@link android.Manifest.permission#GET_ACCOUNTS} permission is not used.
841 *
842 * <p>
843 * Caller targeting API level below {@link android.os.Build.VERSION_CODES#O} that have not been
844 * granted the {@link android.Manifest.permission#GET_ACCOUNTS} permission, will only see those
845 * accounts managed by AbstractAccountAuthenticators whose signature matches the client.
846 * <p>
847 * <b>NOTE:</b> If targeting your app to work on API level
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800848 * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before,
849 * {@link android.Manifest.permission#GET_ACCOUNTS} permission is
Dmitry Dementyev52745472016-12-02 10:27:45 -0800850 * needed for those platforms, irrespective of uid or signature match. See docs for this
851 * function in API level {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
852 *
Fred Quintana756b7352009-10-21 13:43:10 -0700853 *
Dan Egnor661f0132010-02-19 11:23:00 -0800854 * @param type The type of accounts to return, must not be null
Dmitry Dementyev52745472016-12-02 10:27:45 -0800855 * @param features An array of the account features to require, may be null or empty *
856 * @param callback Callback to invoke when the request completes, null for no callback
857 * @param handler {@link Handler} identifying the callback thread, null for the main thread
858 * @return An {@link AccountManagerFuture} which resolves to an array of {@link Account}, one
859 * per account of the specified type which matches the requested features.
Fred Quintana8570f742010-02-18 10:32:54 -0800860 */
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700861 public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
862 final String type, final String[] features,
863 AccountManagerCallback<Account[]> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -0700864 if (type == null) throw new IllegalArgumentException("type is null");
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700865 return new Future2Task<Account[]>(handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -0800866 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700867 public void doWork() throws RemoteException {
Svetoslavf3f02ac2015-09-08 14:36:35 -0700868 mService.getAccountsByFeatures(mResponse, type, features,
869 mContext.getOpPackageName());
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700870 }
Sandra Kwan0b84b452016-01-20 15:25:42 -0800871 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700872 public Account[] bundleToResult(Bundle bundle) throws AuthenticatorException {
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700873 if (!bundle.containsKey(KEY_ACCOUNTS)) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700874 throw new AuthenticatorException("no result in response");
875 }
Fred Quintanaf7ae77c2009-10-02 17:19:31 -0700876 final Parcelable[] parcelables = bundle.getParcelableArray(KEY_ACCOUNTS);
Fred Quintanaffd0cb042009-08-15 21:45:26 -0700877 Account[] descs = new Account[parcelables.length];
878 for (int i = 0; i < parcelables.length; i++) {
879 descs[i] = (Account) parcelables[i];
880 }
881 return descs;
882 }
883 }.start();
884 }
885
Fred Quintana756b7352009-10-21 13:43:10 -0700886 /**
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700887 * Adds an account directly to the AccountManager. Normally used by sign-up
Dan Egnor661f0132010-02-19 11:23:00 -0800888 * wizards associated with authenticators, not directly by applications.
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700889 * <p>Calling this method does not update the last authenticated timestamp,
890 * referred by {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
891 * {@link #notifyAccountAuthenticated(Account)} after getting success.
892 * However, if this method is called when it is triggered by addAccount() or
893 * addAccountAsUser() or similar functions, then there is no need to update
894 * timestamp manually as it is updated automatically by framework on
895 * successful completion of the mentioned functions.
Dan Egnor661f0132010-02-19 11:23:00 -0800896 * <p>It is safe to call this method from the main thread.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -0700897 * <p>This method requires the caller to have a signature match with the
898 * authenticator that owns the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -0800899 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -0700900 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
901 * AUTHENTICATE_ACCOUNTS permission is needed for those platforms. See docs
902 * for this function in API level 22.
903 *
Dan Egnor661f0132010-02-19 11:23:00 -0800904 * @param account The {@link Account} to add
905 * @param password The password to associate with the account, null for none
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -0700906 * @param userdata String values to use for the account's userdata, null for
907 * none
Dan Egnor8e4378b2010-08-02 18:22:09 -0700908 * @return True if the account was successfully added, false if the account
Dmitry Dementyev16d69752018-10-30 14:56:53 -0700909 * already exists, the account is null, the user is locked, or another error occurs.
Dan Egnor661f0132010-02-19 11:23:00 -0800910 */
911 public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
Fred Quintana382601f2010-03-25 12:25:10 -0700912 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -0800913 try {
Amith Yamasani27db4682013-03-30 17:07:47 -0700914 return mService.addAccountExplicitly(account, password, userdata);
Dan Egnor661f0132010-02-19 11:23:00 -0800915 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700916 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -0800917 }
918 }
919
920 /**
Dmitry Dementyev85d8a342017-05-02 17:33:17 -0700921 * Adds an account directly to the AccountManager. Additionally it specifies Account visibility
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800922 * for given list of packages.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800923 * <p>
924 * Normally used by sign-up wizards associated with authenticators, not directly by
925 * applications.
926 * <p>
927 * Calling this method does not update the last authenticated timestamp, referred by
928 * {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700929 * {@link #notifyAccountAuthenticated(Account)} after getting success.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800930 * <p>
931 * It is safe to call this method from the main thread.
932 * <p>
933 * This method requires the caller to have a signature match with the authenticator that owns
934 * the specified account.
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700935 *
936 * @param account The {@link Account} to add
937 * @param password The password to associate with the account, null for none
Dmitry Dementyev52745472016-12-02 10:27:45 -0800938 * @param extras String values to use for the account's userdata, null for none
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800939 * @param visibility Map from packageName to visibility values which will be set before account
940 * is added. See {@link #getAccountVisibility} for possible values.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800941 *
942 * @return True if the account was successfully added, false if the account already exists, the
943 * account is null, or another error occurs.
Dmitry Dementyev52745472016-12-02 10:27:45 -0800944 */
945 public boolean addAccountExplicitly(Account account, String password, Bundle extras,
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800946 Map<String, Integer> visibility) {
Dmitry Dementyev52745472016-12-02 10:27:45 -0800947 if (account == null)
948 throw new IllegalArgumentException("account is null");
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700949 try {
Dmitry Dementyev52745472016-12-02 10:27:45 -0800950 return mService.addAccountExplicitlyWithVisibility(account, password, extras,
951 visibility);
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700952 } catch (RemoteException e) {
953 throw e.rethrowFromSystemServer();
954 }
955 }
956
957 /**
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800958 * Returns package names and visibility which were explicitly set for given account.
Dmitry Dementyev2ae64092017-01-09 12:48:18 -0800959 * <p>
960 * This method requires the caller to have a signature match with the authenticator that owns
961 * the specified account.
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700962 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -0700963 * @param account The account for which visibility data should be returned
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700964 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -0700965 * @return Map from package names to visibility for given account
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700966 */
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800967 public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
Dmitry Dementyev01985ff2017-01-19 16:03:39 -0800968 try {
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800969 if (account == null)
970 throw new IllegalArgumentException("account is null");
Dmitry Dementyev01985ff2017-01-19 16:03:39 -0800971 @SuppressWarnings("unchecked")
Dmitry Dementyeve366f822017-01-31 10:25:10 -0800972 Map<String, Integer> result = (Map<String, Integer>) mService
973 .getPackagesAndVisibilityForAccount(account);
Dmitry Dementyev01985ff2017-01-19 16:03:39 -0800974 return result;
975 } catch (RemoteException re) {
976 throw re.rethrowFromSystemServer();
977 }
Tejas Khorana5edff3b2016-06-28 20:59:52 -0700978 }
979
980 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -0800981 * Gets all accounts of given type and their visibility for specific package. This method
982 * requires the caller to have a signature match with the authenticator that manages
983 * accountType. It is a helper method which combines calls to {@link #getAccountsByType} by
984 * authenticator and {@link #getAccountVisibility} for every returned account.
985 *
986 * <p>
987 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -0700988 * @param packageName Package name
989 * @param accountType {@link Account} type
Dmitry Dementyev52745472016-12-02 10:27:45 -0800990 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -0700991 * @return Map with visibility for all accounts of given type
992 * See {@link #getAccountVisibility} for possible values
Dmitry Dementyev52745472016-12-02 10:27:45 -0800993 */
994 public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
995 String accountType) {
996 try {
997 @SuppressWarnings("unchecked")
998 Map<Account, Integer> result = (Map<Account, Integer>) mService
999 .getAccountsAndVisibilityForPackage(packageName, accountType);
1000 return result;
1001 } catch (RemoteException re) {
1002 throw re.rethrowFromSystemServer();
1003 }
1004 }
1005
1006 /**
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -07001007 * Set visibility value of given account to certain package.
Dmitry Dementyeve366f822017-01-31 10:25:10 -08001008 * Package name must match installed application, or be equal to
1009 * {@link #PACKAGE_NAME_KEY_LEGACY_VISIBLE} or {@link #PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE}.
Dmitry Dementyev52745472016-12-02 10:27:45 -08001010 * <p>
Dmitry Dementyev06f32e02017-02-16 17:47:48 -08001011 * Possible visibility values:
1012 * <ul>
1013 * <li>{@link #VISIBILITY_UNDEFINED}</li>
1014 * <li>{@link #VISIBILITY_VISIBLE}</li>
1015 * <li>{@link #VISIBILITY_USER_MANAGED_VISIBLE}</li>
1016 * <li>{@link #VISIBILITY_NOT_VISIBLE}
1017 * <li>{@link #VISIBILITY_USER_MANAGED_NOT_VISIBLE}</li>
1018 * </ul>
Dmitry Dementyev52745472016-12-02 10:27:45 -08001019 * <p>
1020 * This method requires the caller to have a signature match with the authenticator that owns
1021 * the specified account.
1022 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -07001023 * @param account {@link Account} to update visibility
1024 * @param packageName Package name of the application to modify account visibility
1025 * @param visibility New visibility value
Dmitry Dementyev52745472016-12-02 10:27:45 -08001026 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -07001027 * @return True, if visibility value was successfully updated.
Dmitry Dementyev52745472016-12-02 10:27:45 -08001028 */
Dmitry Dementyeve366f822017-01-31 10:25:10 -08001029 public boolean setAccountVisibility(Account account, String packageName,
Dmitry Dementyev52745472016-12-02 10:27:45 -08001030 @AccountVisibility int visibility) {
Dmitry Dementyeve366f822017-01-31 10:25:10 -08001031 if (account == null)
1032 throw new IllegalArgumentException("account is null");
Dmitry Dementyev52745472016-12-02 10:27:45 -08001033 try {
Dmitry Dementyeve366f822017-01-31 10:25:10 -08001034 return mService.setAccountVisibility(account, packageName, visibility);
Dmitry Dementyev52745472016-12-02 10:27:45 -08001035 } catch (RemoteException re) {
1036 throw re.rethrowFromSystemServer();
1037 }
1038 }
1039
1040 /**
Dmitry Dementyeve366f822017-01-31 10:25:10 -08001041 * Get visibility of certain account for given application. Possible returned values are:
Dmitry Dementyev52745472016-12-02 10:27:45 -08001042 * <ul>
1043 * <li>{@link #VISIBILITY_VISIBLE}</li>
1044 * <li>{@link #VISIBILITY_USER_MANAGED_VISIBLE}</li>
1045 * <li>{@link #VISIBILITY_NOT_VISIBLE}
1046 * <li>{@link #VISIBILITY_USER_MANAGED_NOT_VISIBLE}</li>
1047 * </ul>
1048 *
1049 * <p>
1050 * This method requires the caller to have a signature match with the authenticator that owns
1051 * the specified account.
1052 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -07001053 * @param account {@link Account} to get visibility
Dmitry Dementyeve366f822017-01-31 10:25:10 -08001054 * @param packageName Package name of the application to get account visibility
Dmitry Dementyev52745472016-12-02 10:27:45 -08001055 *
Dmitry Dementyev0f8bba02017-03-20 10:57:01 -07001056 * @return int Visibility of given account.
Dmitry Dementyev52745472016-12-02 10:27:45 -08001057 */
Dmitry Dementyeve366f822017-01-31 10:25:10 -08001058 public @AccountVisibility int getAccountVisibility(Account account, String packageName) {
1059 if (account == null)
1060 throw new IllegalArgumentException("account is null");
Dmitry Dementyev52745472016-12-02 10:27:45 -08001061 try {
Dmitry Dementyeve366f822017-01-31 10:25:10 -08001062 return mService.getAccountVisibility(account, packageName);
Tejas Khorana5edff3b2016-06-28 20:59:52 -07001063 } catch (RemoteException re) {
1064 throw re.rethrowFromSystemServer();
1065 }
1066 }
1067
1068 /**
Simranjit Singh Kohli1663b442015-04-28 11:11:12 -07001069 * Notifies the system that the account has just been authenticated. This
1070 * information may be used by other applications to verify the account. This
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001071 * should be called only when the user has entered correct credentials for
1072 * the account.
1073 * <p>
1074 * It is not safe to call this method from the main thread. As such, call it
1075 * from another thread.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001076 * <p>This method requires the caller to have a signature match with the
1077 * authenticator that owns the specified account.
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001078 *
1079 * @param account The {@link Account} to be updated.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001080 * @return boolean {@code true} if the authentication of the account has been successfully
1081 * acknowledged. Otherwise {@code false}.
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001082 */
Simranjit Singh Kohli1663b442015-04-28 11:11:12 -07001083 public boolean notifyAccountAuthenticated(Account account) {
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001084 if (account == null)
1085 throw new IllegalArgumentException("account is null");
1086 try {
1087 return mService.accountAuthenticated(account);
1088 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001089 throw e.rethrowFromSystemServer();
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001090 }
1091 }
1092
1093 /**
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -07001094 * Rename the specified {@link Account}. This is equivalent to removing
1095 * the existing account and adding a new renamed account with the old
1096 * account's user data.
1097 *
1098 * <p>It is safe to call this method from the main thread.
1099 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001100 * <p>This method requires the caller to have a signature match with the
1101 * authenticator that manages the specified account.
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -07001102 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001103 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1104 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1105 * is needed for those platforms. See docs for this function in API level 22.
1106 *
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -07001107 * @param account The {@link Account} to rename
1108 * @param newName String name to be associated with the account.
1109 * @param callback Callback to invoke when the request completes, null for
1110 * no callback
1111 * @param handler {@link Handler} identifying the callback thread, null for
1112 * the main thread
1113 * @return An {@link AccountManagerFuture} which resolves to the Account
1114 * after the name change. If successful the account's name will be the
1115 * specified new name.
1116 */
1117 public AccountManagerFuture<Account> renameAccount(
1118 final Account account,
Tor Norbye80b530a2015-04-23 16:36:09 -07001119 @Size(min = 1) final String newName,
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -07001120 AccountManagerCallback<Account> callback,
1121 Handler handler) {
1122 if (account == null) throw new IllegalArgumentException("account is null.");
1123 if (TextUtils.isEmpty(newName)) {
1124 throw new IllegalArgumentException("newName is empty or null.");
1125 }
1126 return new Future2Task<Account>(handler, callback) {
1127 @Override
1128 public void doWork() throws RemoteException {
1129 mService.renameAccount(mResponse, account, newName);
1130 }
1131 @Override
1132 public Account bundleToResult(Bundle bundle) throws AuthenticatorException {
1133 String name = bundle.getString(KEY_ACCOUNT_NAME);
1134 String type = bundle.getString(KEY_ACCOUNT_TYPE);
Svet Ganovc1c0d1c2016-09-23 19:15:47 -07001135 String accessId = bundle.getString(KEY_ACCOUNT_ACCESS_ID);
1136 return new Account(name, type, accessId);
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -07001137 }
1138 }.start();
1139 }
1140
1141 /**
1142 * Gets the previous name associated with the account or {@code null}, if
Dmitry Dementyev8882d882017-03-14 17:25:46 -07001143 * none. This is intended so that clients of
1144 * {@link OnAccountsUpdateListener} can determine if an
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -07001145 * authenticator has renamed an account.
1146 *
1147 * <p>It is safe to call this method from the main thread.
1148 *
1149 * @param account The account to query for a previous name.
1150 * @return The account's previous name, null if the account has never been
1151 * renamed.
1152 */
1153 public String getPreviousName(final Account account) {
1154 if (account == null) throw new IllegalArgumentException("account is null");
1155 try {
1156 return mService.getPreviousName(account);
1157 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001158 throw e.rethrowFromSystemServer();
Carlos Valdiviaf193b9a2014-07-18 01:34:57 -07001159 }
1160 }
1161
1162 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001163 * Removes an account from the AccountManager. Does nothing if the account
1164 * does not exist. Does not delete the account from the server.
1165 * The authenticator may have its own policies preventing account
1166 * deletion, in which case the account will not be deleted.
1167 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001168 * <p>This method requires the caller to have a signature match with the
1169 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001170 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001171 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1172 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
1173 * this function in API level 22.
1174 *
Dan Egnor661f0132010-02-19 11:23:00 -08001175 * @param account The {@link Account} to remove
1176 * @param callback Callback to invoke when the request completes,
1177 * null for no callback
1178 * @param handler {@link Handler} identifying the callback thread,
1179 * null for the main thread
1180 * @return An {@link AccountManagerFuture} which resolves to a Boolean,
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001181 * true if the account has been successfully removed
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001182 * @deprecated use
1183 * {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)}
1184 * instead
Dan Egnor661f0132010-02-19 11:23:00 -08001185 */
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001186 @Deprecated
Dan Egnor661f0132010-02-19 11:23:00 -08001187 public AccountManagerFuture<Boolean> removeAccount(final Account account,
1188 AccountManagerCallback<Boolean> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07001189 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001190 return new Future2Task<Boolean>(handler, callback) {
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001191 @Override
Dan Egnor661f0132010-02-19 11:23:00 -08001192 public void doWork() throws RemoteException {
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001193 mService.removeAccount(mResponse, account, false);
Dan Egnor661f0132010-02-19 11:23:00 -08001194 }
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001195 @Override
Dan Egnor661f0132010-02-19 11:23:00 -08001196 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
1197 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
1198 throw new AuthenticatorException("no result in response");
1199 }
1200 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
1201 }
1202 }.start();
1203 }
1204
1205 /**
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001206 * Removes an account from the AccountManager. Does nothing if the account
1207 * does not exist. Does not delete the account from the server.
1208 * The authenticator may have its own policies preventing account
1209 * deletion, in which case the account will not be deleted.
1210 *
1211 * <p>This method may be called from any thread, but the returned
1212 * {@link AccountManagerFuture} must not be used on the main thread.
1213 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001214 * <p>This method requires the caller to have a signature match with the
1215 * authenticator that manages the specified account.
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001216 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001217 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1218 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
1219 * this function in API level 22.
1220 *
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001221 * @param account The {@link Account} to remove
1222 * @param activity The {@link Activity} context to use for launching a new
1223 * authenticator-defined sub-Activity to prompt the user to delete an
1224 * account; used only to call startActivity(); if null, the prompt
1225 * will not be launched directly, but the {@link Intent} may be
1226 * returned to the caller instead
1227 * @param callback Callback to invoke when the request completes,
1228 * null for no callback
1229 * @param handler {@link Handler} identifying the callback thread,
1230 * null for the main thread
1231 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
1232 * {@link #KEY_BOOLEAN_RESULT} if activity was specified and an account
1233 * was removed or if active. If no activity was specified, the returned
1234 * Bundle contains only {@link #KEY_INTENT} with the {@link Intent}
1235 * needed to launch the actual account removal process, if authenticator
1236 * needs the activity launch. If an error occurred,
1237 * {@link AccountManagerFuture#getResult()} throws:
1238 * <ul>
1239 * <li> {@link AuthenticatorException} if no authenticator was registered for
1240 * this account type or the authenticator failed to respond
1241 * <li> {@link OperationCanceledException} if the operation was canceled for
1242 * any reason, including the user canceling the creation process or
1243 * adding accounts (of this type) has been disabled by policy
1244 * </ul>
1245 */
1246 public AccountManagerFuture<Bundle> removeAccount(final Account account,
1247 final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
1248 if (account == null) throw new IllegalArgumentException("account is null");
1249 return new AmsTask(activity, handler, callback) {
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001250 @Override
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001251 public void doWork() throws RemoteException {
1252 mService.removeAccount(mResponse, account, activity != null);
1253 }
1254 }.start();
1255 }
1256
1257 /**
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001258 * @see #removeAccount(Account, AccountManagerCallback, Handler)
1259 * @hide
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001260 * @deprecated use
1261 * {@link #removeAccountAsUser(Account, Activity, AccountManagerCallback, Handler)}
1262 * instead
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001263 */
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001264 @Deprecated
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001265 public AccountManagerFuture<Boolean> removeAccountAsUser(final Account account,
1266 AccountManagerCallback<Boolean> callback, Handler handler,
1267 final UserHandle userHandle) {
1268 if (account == null) throw new IllegalArgumentException("account is null");
1269 if (userHandle == null) throw new IllegalArgumentException("userHandle is null");
1270 return new Future2Task<Boolean>(handler, callback) {
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001271 @Override
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001272 public void doWork() throws RemoteException {
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001273 mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier());
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001274 }
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001275 @Override
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001276 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
1277 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
1278 throw new AuthenticatorException("no result in response");
1279 }
1280 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
1281 }
1282 }.start();
1283 }
1284
1285 /**
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001286 * @see #removeAccount(Account, Activity, AccountManagerCallback, Handler)
1287 * @hide
1288 */
1289 public AccountManagerFuture<Bundle> removeAccountAsUser(final Account account,
1290 final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler,
1291 final UserHandle userHandle) {
1292 if (account == null)
1293 throw new IllegalArgumentException("account is null");
1294 if (userHandle == null)
1295 throw new IllegalArgumentException("userHandle is null");
1296 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001297 @Override
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001298 public void doWork() throws RemoteException {
1299 mService.removeAccountAsUser(mResponse, account, activity != null,
1300 userHandle.getIdentifier());
1301 }
1302 }.start();
1303 }
1304
1305 /**
1306 * Removes an account directly. Normally used by authenticators, not
1307 * directly by applications. Does not delete the account from the server.
1308 * The authenticator may have its own policies preventing account deletion,
1309 * in which case the account will not be deleted.
1310 * <p>
1311 * It is safe to call this method from the main thread.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001312 * <p>This method requires the caller to have a signature match with the
1313 * authenticator that manages the specified account.
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001314 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001315 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1316 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1317 * is needed for those platforms. See docs for this function in API level 22.
1318 *
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001319 * @param account The {@link Account} to delete.
1320 * @return True if the account was successfully deleted, false if the
1321 * account did not exist, the account is null, or another error
1322 * occurs.
1323 */
1324 public boolean removeAccountExplicitly(Account account) {
1325 if (account == null) throw new IllegalArgumentException("account is null");
1326 try {
1327 return mService.removeAccountExplicitly(account);
1328 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001329 throw e.rethrowFromSystemServer();
Simranjit Singh Kohli8778f992014-11-05 21:33:55 -08001330 }
1331 }
1332
1333 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001334 * Removes an auth token from the AccountManager's cache. Does nothing if
1335 * the auth token is not currently in the cache. Applications must call this
1336 * method when the auth token is found to have expired or otherwise become
1337 * invalid for authenticating requests. The AccountManager does not validate
1338 * or expire cached auth tokens otherwise.
1339 *
1340 * <p>It is safe to call this method from the main thread.
1341 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001342 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1343 * MANAGE_ACCOUNTS or USE_CREDENTIALS permission is needed for those
1344 * platforms. See docs for this function in API level 22.
1345 *
Fred Quintanaf35b68f2010-04-01 11:36:00 -07001346 * @param accountType The account type of the auth token to invalidate, must not be null
1347 * @param authToken The auth token to invalidate, may be null
Dan Egnor661f0132010-02-19 11:23:00 -08001348 */
1349 public void invalidateAuthToken(final String accountType, final String authToken) {
Fred Quintana382601f2010-03-25 12:25:10 -07001350 if (accountType == null) throw new IllegalArgumentException("accountType is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001351 try {
Fred Quintanaf35b68f2010-04-01 11:36:00 -07001352 if (authToken != null) {
1353 mService.invalidateAuthToken(accountType, authToken);
1354 }
Dan Egnor661f0132010-02-19 11:23:00 -08001355 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001356 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001357 }
1358 }
1359
1360 /**
1361 * Gets an auth token from the AccountManager's cache. If no auth
1362 * token is cached for this account, null will be returned -- a new
1363 * auth token will not be generated, and the server will not be contacted.
1364 * Intended for use by the authenticator, not directly by applications.
1365 *
1366 * <p>It is safe to call this method from the main thread.
1367 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001368 * <p>This method requires the caller to have a signature match with the
1369 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001370 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001371 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1372 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1373 * is needed for those platforms. See docs for this function in API level 22.
1374 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001375 * @param account The account for which an auth token is to be fetched. Cannot be {@code null}.
Sandra Kwan0b84b452016-01-20 15:25:42 -08001376 * @param authTokenType The type of auth token to fetch. Cannot be {@code null}.
Dan Egnor661f0132010-02-19 11:23:00 -08001377 * @return The cached auth token for this account and type, or null if
Dmitry Dementyev16d69752018-10-30 14:56:53 -07001378 * no auth token is cached, the account does not exist, or the user is locked
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001379 * @see #getAuthToken
Dan Egnor661f0132010-02-19 11:23:00 -08001380 */
1381 public String peekAuthToken(final Account account, final String authTokenType) {
Fred Quintana382601f2010-03-25 12:25:10 -07001382 if (account == null) throw new IllegalArgumentException("account is null");
1383 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001384 try {
1385 return mService.peekAuthToken(account, authTokenType);
1386 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001387 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001388 }
1389 }
1390
1391 /**
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -07001392 * Sets or forgets a saved password. This modifies the local copy of the
1393 * password used to automatically authenticate the user; it does not change
1394 * the user's account password on the server. Intended for use by the
1395 * authenticator, not directly by applications.
1396 * <p>Calling this method does not update the last authenticated timestamp,
1397 * referred by {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
1398 * {@link #notifyAccountAuthenticated(Account)} after getting success.
Dan Egnor661f0132010-02-19 11:23:00 -08001399 * <p>It is safe to call this method from the main thread.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001400 * <p>This method requires the caller to have a signature match with the
1401 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001402 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001403 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1404 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1405 * is needed for those platforms. See docs for this function in API level 22.
1406 *
Simranjit Singh Kohli0b8a7c02015-06-19 12:45:27 -07001407 * @param account The account whose password is to be set. Cannot be
1408 * {@code null}.
Dan Egnor661f0132010-02-19 11:23:00 -08001409 * @param password The password to set, null to clear the password
1410 */
1411 public void setPassword(final Account account, final String password) {
Fred Quintana382601f2010-03-25 12:25:10 -07001412 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001413 try {
1414 mService.setPassword(account, password);
1415 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001416 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001417 }
1418 }
1419
1420 /**
1421 * Forgets a saved password. This erases the local copy of the password;
1422 * it does not change the user's account password on the server.
1423 * Has the same effect as setPassword(account, null) but requires fewer
1424 * permissions, and may be used by applications or management interfaces
1425 * to "sign out" from an account.
1426 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001427 * <p>This method only successfully clear the account's password when the
1428 * caller has the same signature as the authenticator that owns the
1429 * specified account. Otherwise, this method will silently fail.
Dan Egnor661f0132010-02-19 11:23:00 -08001430 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001431 * <p>It is safe to call this method from the main thread.
Carlos Valdiviadcddc472015-06-11 20:04:04 +00001432 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001433 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1434 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
1435 * this function in API level 22.
1436 *
Dan Egnor661f0132010-02-19 11:23:00 -08001437 * @param account The account whose password to clear
1438 */
1439 public void clearPassword(final Account account) {
Fred Quintana382601f2010-03-25 12:25:10 -07001440 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001441 try {
1442 mService.clearPassword(account);
1443 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001444 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001445 }
1446 }
1447
1448 /**
Dmitry Dementyev16d69752018-10-30 14:56:53 -07001449 * Sets one userdata key for an account. Intended by use for the
Dan Egnor661f0132010-02-19 11:23:00 -08001450 * authenticator to stash state for itself, not directly by applications.
1451 * The meaning of the keys and values is up to the authenticator.
1452 *
1453 * <p>It is safe to call this method from the main thread.
1454 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001455 * <p>This method requires the caller to have a signature match with the
1456 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001457 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001458 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1459 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1460 * is needed for those platforms. See docs for this function in API level 22.
1461 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001462 * @param account Account whose user data is to be set. Must not be {@code null}.
1463 * @param key String user data key to set. Must not be null
1464 * @param value String value to set, {@code null} to clear this user data key
Dan Egnor661f0132010-02-19 11:23:00 -08001465 */
1466 public void setUserData(final Account account, final String key, final String value) {
Fred Quintana382601f2010-03-25 12:25:10 -07001467 if (account == null) throw new IllegalArgumentException("account is null");
1468 if (key == null) throw new IllegalArgumentException("key is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001469 try {
1470 mService.setUserData(account, key, value);
1471 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001472 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001473 }
1474 }
1475
1476 /**
1477 * Adds an auth token to the AccountManager cache for an account.
1478 * If the account does not exist then this call has no effect.
1479 * Replaces any previous auth token for this account and auth token type.
1480 * Intended for use by the authenticator, not directly by applications.
1481 *
1482 * <p>It is safe to call this method from the main thread.
1483 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001484 * <p>This method requires the caller to have a signature match with the
1485 * authenticator that manages the specified account.
Dan Egnor661f0132010-02-19 11:23:00 -08001486 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001487 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1488 * AUTHENTICATE_ACCOUNTS permission and same UID as account's authenticator
1489 * is needed for those platforms. See docs for this function in API level 22.
1490 *
Dan Egnor661f0132010-02-19 11:23:00 -08001491 * @param account The account to set an auth token for
1492 * @param authTokenType The type of the auth token, see {#getAuthToken}
1493 * @param authToken The auth token to add to the cache
1494 */
1495 public void setAuthToken(Account account, final String authTokenType, final String authToken) {
Fred Quintana382601f2010-03-25 12:25:10 -07001496 if (account == null) throw new IllegalArgumentException("account is null");
1497 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001498 try {
1499 mService.setAuthToken(account, authTokenType, authToken);
1500 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001501 throw e.rethrowFromSystemServer();
Dan Egnor661f0132010-02-19 11:23:00 -08001502 }
1503 }
1504
1505 /**
1506 * This convenience helper synchronously gets an auth token with
1507 * {@link #getAuthToken(Account, String, boolean, AccountManagerCallback, Handler)}.
1508 *
1509 * <p>This method may block while a network request completes, and must
1510 * never be made from the main thread.
1511 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001512 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1513 * USE_CREDENTIALS permission is needed for those platforms. See docs for
1514 * this function in API level 22.
1515 *
Dan Egnor661f0132010-02-19 11:23:00 -08001516 * @param account The account to fetch an auth token for
Joe Malinb6a35262013-06-03 09:49:04 -07001517 * @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()}
Dan Egnor661f0132010-02-19 11:23:00 -08001518 * @param notifyAuthFailure If true, display a notification and return null
1519 * if authentication fails; if false, prompt and wait for the user to
1520 * re-enter correct credentials before returning
1521 * @return An auth token of the specified type for this account, or null
1522 * if authentication fails or none can be fetched.
1523 * @throws AuthenticatorException if the authenticator failed to respond
1524 * @throws OperationCanceledException if the request was canceled for any
1525 * reason, including the user canceling a credential request
1526 * @throws java.io.IOException if the authenticator experienced an I/O problem
1527 * creating a new auth token, usually because of network trouble
1528 */
1529 public String blockingGetAuthToken(Account account, String authTokenType,
1530 boolean notifyAuthFailure)
1531 throws OperationCanceledException, IOException, AuthenticatorException {
Fred Quintana382601f2010-03-25 12:25:10 -07001532 if (account == null) throw new IllegalArgumentException("account is null");
1533 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001534 Bundle bundle = getAuthToken(account, authTokenType, notifyAuthFailure, null /* callback */,
1535 null /* handler */).getResult();
Fred Quintana96580e02010-03-04 13:42:42 -08001536 if (bundle == null) {
1537 // This should never happen, but it does, occasionally. If it does return null to
1538 // signify that we were not able to get the authtoken.
1539 // TODO: remove this when the bug is found that sometimes causes a null bundle to be
1540 // returned
1541 Log.e(TAG, "blockingGetAuthToken: null was returned from getResult() for "
1542 + account + ", authTokenType " + authTokenType);
1543 return null;
1544 }
Dan Egnor661f0132010-02-19 11:23:00 -08001545 return bundle.getString(KEY_AUTHTOKEN);
1546 }
1547
1548 /**
1549 * Gets an auth token of the specified type for a particular account,
1550 * prompting the user for credentials if necessary. This method is
1551 * intended for applications running in the foreground where it makes
1552 * sense to ask the user directly for a password.
1553 *
1554 * <p>If a previously generated auth token is cached for this account and
Dan Egnor8e4378b2010-08-02 18:22:09 -07001555 * type, then it is returned. Otherwise, if a saved password is
1556 * available, it is sent to the server to generate a new auth token.
1557 * Otherwise, the user is prompted to enter a password.
Dan Egnor661f0132010-02-19 11:23:00 -08001558 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001559 * <p>Some authenticators have auth token <em>types</em>, whose value
1560 * is authenticator-dependent. Some services use different token types to
1561 * access different functionality -- for example, Google uses different auth
1562 * tokens to access Gmail and Google Calendar for the same account.
Dan Egnor661f0132010-02-19 11:23:00 -08001563 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001564 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
Sandra Kwan0b84b452016-01-20 15:25:42 -08001565 * USE_CREDENTIALS permission is needed for those platforms. See docs for
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001566 * this function in API level 22.
1567 *
Dan Egnor661f0132010-02-19 11:23:00 -08001568 * <p>This method may be called from any thread, but the returned
1569 * {@link AccountManagerFuture} must not be used on the main thread.
1570 *
Dan Egnor661f0132010-02-19 11:23:00 -08001571 * @param account The account to fetch an auth token for
1572 * @param authTokenType The auth token type, an authenticator-dependent
1573 * string token, must not be null
1574 * @param options Authenticator-specific options for the request,
1575 * may be null or empty
1576 * @param activity The {@link Activity} context to use for launching a new
1577 * authenticator-defined sub-Activity to prompt the user for a password
1578 * if necessary; used only to call startActivity(); must not be null.
1579 * @param callback Callback to invoke when the request completes,
1580 * null for no callback
1581 * @param handler {@link Handler} identifying the callback thread,
1582 * null for the main thread
1583 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
1584 * at least the following fields:
Fred Quintana756b7352009-10-21 13:43:10 -07001585 * <ul>
Dan Egnor661f0132010-02-19 11:23:00 -08001586 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account you supplied
1587 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1588 * <li> {@link #KEY_AUTHTOKEN} - the auth token you wanted
Fred Quintana756b7352009-10-21 13:43:10 -07001589 * </ul>
Dan Egnor661f0132010-02-19 11:23:00 -08001590 *
1591 * (Other authenticator-specific values may be returned.) If an auth token
1592 * could not be fetched, {@link AccountManagerFuture#getResult()} throws:
1593 * <ul>
1594 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1595 * <li> {@link OperationCanceledException} if the operation is canceled for
1596 * any reason, incluidng the user canceling a credential request
1597 * <li> {@link IOException} if the authenticator experienced an I/O problem
1598 * creating a new auth token, usually because of network trouble
1599 * </ul>
Dan Egnor8e4378b2010-08-02 18:22:09 -07001600 * If the account is no longer present on the device, the return value is
1601 * authenticator-dependent. The caller should verify the validity of the
1602 * account before requesting an auth token.
Dan Egnor661f0132010-02-19 11:23:00 -08001603 */
1604 public AccountManagerFuture<Bundle> getAuthToken(
1605 final Account account, final String authTokenType, final Bundle options,
1606 final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07001607 if (account == null) throw new IllegalArgumentException("account is null");
Dan Egnor661f0132010-02-19 11:23:00 -08001608 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Costin Manolachee5847ad2011-09-14 12:52:19 -07001609 final Bundle optionsIn = new Bundle();
1610 if (options != null) {
1611 optionsIn.putAll(options);
1612 }
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001613 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
Dan Egnor661f0132010-02-19 11:23:00 -08001614 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001615 @Override
Dan Egnor661f0132010-02-19 11:23:00 -08001616 public void doWork() throws RemoteException {
1617 mService.getAuthToken(mResponse, account, authTokenType,
1618 false /* notifyOnAuthFailure */, true /* expectActivityLaunch */,
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001619 optionsIn);
Dan Egnor661f0132010-02-19 11:23:00 -08001620 }
1621 }.start();
1622 }
1623
1624 /**
1625 * Gets an auth token of the specified type for a particular account,
1626 * optionally raising a notification if the user must enter credentials.
1627 * This method is intended for background tasks and services where the
1628 * user should not be immediately interrupted with a password prompt.
1629 *
1630 * <p>If a previously generated auth token is cached for this account and
Dan Egnor8e4378b2010-08-02 18:22:09 -07001631 * type, then it is returned. Otherwise, if a saved password is
1632 * available, it is sent to the server to generate a new auth token.
1633 * Otherwise, an {@link Intent} is returned which, when started, will
1634 * prompt the user for a password. If the notifyAuthFailure parameter is
1635 * set, a status bar notification is also created with the same Intent,
Dan Egnor661f0132010-02-19 11:23:00 -08001636 * alerting the user that they need to enter a password at some point.
1637 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001638 * <p>In that case, you may need to wait until the user responds, which
1639 * could take hours or days or forever. When the user does respond and
1640 * supply a new password, the account manager will broadcast the
Dmitry Dementyev8882d882017-03-14 17:25:46 -07001641 * {@link #LOGIN_ACCOUNTS_CHANGED_ACTION} Intent and
1642 * notify {@link OnAccountsUpdateListener} which applications can
Dan Egnor8e4378b2010-08-02 18:22:09 -07001643 * use to try again.
Dan Egnor661f0132010-02-19 11:23:00 -08001644 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001645 * <p>If notifyAuthFailure is not set, it is the application's
1646 * responsibility to launch the returned Intent at some point.
1647 * Either way, the result from this call will not wait for user action.
Dan Egnor661f0132010-02-19 11:23:00 -08001648 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001649 * <p>Some authenticators have auth token <em>types</em>, whose value
1650 * is authenticator-dependent. Some services use different token types to
1651 * access different functionality -- for example, Google uses different auth
1652 * tokens to access Gmail and Google Calendar for the same account.
Dan Egnor661f0132010-02-19 11:23:00 -08001653 *
1654 * <p>This method may be called from any thread, but the returned
1655 * {@link AccountManagerFuture} must not be used on the main thread.
1656 *
Dan Egnor661f0132010-02-19 11:23:00 -08001657 * @param account The account to fetch an auth token for
1658 * @param authTokenType The auth token type, an authenticator-dependent
1659 * string token, must not be null
Dan Egnor661f0132010-02-19 11:23:00 -08001660 * @param notifyAuthFailure True to add a notification to prompt the
1661 * user for a password if necessary, false to leave that to the caller
1662 * @param callback Callback to invoke when the request completes,
1663 * null for no callback
1664 * @param handler {@link Handler} identifying the callback thread,
1665 * null for the main thread
1666 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
1667 * at least the following fields on success:
1668 * <ul>
1669 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account you supplied
1670 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1671 * <li> {@link #KEY_AUTHTOKEN} - the auth token you wanted
1672 * </ul>
1673 *
1674 * (Other authenticator-specific values may be returned.) If the user
1675 * must enter credentials, the returned Bundle contains only
1676 * {@link #KEY_INTENT} with the {@link Intent} needed to launch a prompt.
1677 *
Dan Egnor8e4378b2010-08-02 18:22:09 -07001678 * If an error occurred, {@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08001679 * <ul>
1680 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1681 * <li> {@link OperationCanceledException} if the operation is canceled for
1682 * any reason, incluidng the user canceling a credential request
1683 * <li> {@link IOException} if the authenticator experienced an I/O problem
1684 * creating a new auth token, usually because of network trouble
1685 * </ul>
Dan Egnor8e4378b2010-08-02 18:22:09 -07001686 * If the account is no longer present on the device, the return value is
1687 * authenticator-dependent. The caller should verify the validity of the
1688 * account before requesting an auth token.
Fred Quintanaad93a322011-09-08 13:21:01 -07001689 * @deprecated use {@link #getAuthToken(Account, String, android.os.Bundle,
1690 * boolean, AccountManagerCallback, android.os.Handler)} instead
Dan Egnor661f0132010-02-19 11:23:00 -08001691 */
Fred Quintanaad93a322011-09-08 13:21:01 -07001692 @Deprecated
Dan Egnor661f0132010-02-19 11:23:00 -08001693 public AccountManagerFuture<Bundle> getAuthToken(
Jatin Lodhia3df7d692013-03-27 10:57:23 -07001694 final Account account, final String authTokenType,
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001695 final boolean notifyAuthFailure,
Dan Egnor661f0132010-02-19 11:23:00 -08001696 AccountManagerCallback<Bundle> callback, Handler handler) {
Jatin Lodhia3df7d692013-03-27 10:57:23 -07001697 return getAuthToken(account, authTokenType, null, notifyAuthFailure, callback,
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001698 handler);
Dan Egnor661f0132010-02-19 11:23:00 -08001699 }
1700
1701 /**
Fred Quintanaad93a322011-09-08 13:21:01 -07001702 * Gets an auth token of the specified type for a particular account,
1703 * optionally raising a notification if the user must enter credentials.
1704 * This method is intended for background tasks and services where the
1705 * user should not be immediately interrupted with a password prompt.
1706 *
1707 * <p>If a previously generated auth token is cached for this account and
1708 * type, then it is returned. Otherwise, if a saved password is
1709 * available, it is sent to the server to generate a new auth token.
1710 * Otherwise, an {@link Intent} is returned which, when started, will
1711 * prompt the user for a password. If the notifyAuthFailure parameter is
1712 * set, a status bar notification is also created with the same Intent,
1713 * alerting the user that they need to enter a password at some point.
1714 *
1715 * <p>In that case, you may need to wait until the user responds, which
1716 * could take hours or days or forever. When the user does respond and
1717 * supply a new password, the account manager will broadcast the
Dmitry Dementyev8882d882017-03-14 17:25:46 -07001718 * {@link #LOGIN_ACCOUNTS_CHANGED_ACTION} Intent and
1719 * notify {@link OnAccountsUpdateListener} which applications can
Fred Quintanaad93a322011-09-08 13:21:01 -07001720 * use to try again.
1721 *
1722 * <p>If notifyAuthFailure is not set, it is the application's
1723 * responsibility to launch the returned Intent at some point.
1724 * Either way, the result from this call will not wait for user action.
1725 *
1726 * <p>Some authenticators have auth token <em>types</em>, whose value
1727 * is authenticator-dependent. Some services use different token types to
1728 * access different functionality -- for example, Google uses different auth
1729 * tokens to access Gmail and Google Calendar for the same account.
1730 *
1731 * <p>This method may be called from any thread, but the returned
1732 * {@link AccountManagerFuture} must not be used on the main thread.
1733 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001734 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
Sandra Kwan0b84b452016-01-20 15:25:42 -08001735 * USE_CREDENTIALS permission is needed for those platforms. See docs for
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001736 * this function in API level 22.
1737 *
Fred Quintanaad93a322011-09-08 13:21:01 -07001738 * @param account The account to fetch an auth token for
1739 * @param authTokenType The auth token type, an authenticator-dependent
1740 * string token, must not be null
1741 * @param options Authenticator-specific options for the request,
1742 * may be null or empty
1743 * @param notifyAuthFailure True to add a notification to prompt the
1744 * user for a password if necessary, false to leave that to the caller
1745 * @param callback Callback to invoke when the request completes,
1746 * null for no callback
1747 * @param handler {@link Handler} identifying the callback thread,
1748 * null for the main thread
1749 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
1750 * at least the following fields on success:
1751 * <ul>
1752 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account you supplied
1753 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1754 * <li> {@link #KEY_AUTHTOKEN} - the auth token you wanted
1755 * </ul>
1756 *
1757 * (Other authenticator-specific values may be returned.) If the user
1758 * must enter credentials, the returned Bundle contains only
1759 * {@link #KEY_INTENT} with the {@link Intent} needed to launch a prompt.
1760 *
1761 * If an error occurred, {@link AccountManagerFuture#getResult()} throws:
1762 * <ul>
1763 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1764 * <li> {@link OperationCanceledException} if the operation is canceled for
1765 * any reason, incluidng the user canceling a credential request
1766 * <li> {@link IOException} if the authenticator experienced an I/O problem
1767 * creating a new auth token, usually because of network trouble
1768 * </ul>
1769 * If the account is no longer present on the device, the return value is
1770 * authenticator-dependent. The caller should verify the validity of the
1771 * account before requesting an auth token.
1772 */
1773 public AccountManagerFuture<Bundle> getAuthToken(
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001774 final Account account, final String authTokenType, final Bundle options,
1775 final boolean notifyAuthFailure,
Fred Quintanaad93a322011-09-08 13:21:01 -07001776 AccountManagerCallback<Bundle> callback, Handler handler) {
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001777
Fred Quintanaad93a322011-09-08 13:21:01 -07001778 if (account == null) throw new IllegalArgumentException("account is null");
1779 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Costin Manolachee5847ad2011-09-14 12:52:19 -07001780 final Bundle optionsIn = new Bundle();
1781 if (options != null) {
1782 optionsIn.putAll(options);
1783 }
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001784 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
Fred Quintanaad93a322011-09-08 13:21:01 -07001785 return new AmsTask(null, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001786 @Override
Fred Quintanaad93a322011-09-08 13:21:01 -07001787 public void doWork() throws RemoteException {
1788 mService.getAuthToken(mResponse, account, authTokenType,
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001789 notifyAuthFailure, false /* expectActivityLaunch */, optionsIn);
Fred Quintanaad93a322011-09-08 13:21:01 -07001790 }
1791 }.start();
1792 }
1793
1794 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001795 * Asks the user to add an account of a specified type. The authenticator
1796 * for this account type processes this request with the appropriate user
1797 * interface. If the user does elect to create a new account, the account
1798 * name is returned.
1799 *
1800 * <p>This method may be called from any thread, but the returned
1801 * {@link AccountManagerFuture} must not be used on the main thread.
Sandra Kwan0b84b452016-01-20 15:25:42 -08001802 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001803 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1804 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
1805 * this function in API level 22.
Dan Egnor661f0132010-02-19 11:23:00 -08001806 *
Dan Egnor661f0132010-02-19 11:23:00 -08001807 * @param accountType The type of account to add; must not be null
1808 * @param authTokenType The type of auth token (see {@link #getAuthToken})
1809 * this account will need to be able to generate, null for none
1810 * @param requiredFeatures The features (see {@link #hasFeatures}) this
1811 * account must have, null for none
1812 * @param addAccountOptions Authenticator-specific options for the request,
1813 * may be null or empty
1814 * @param activity The {@link Activity} context to use for launching a new
1815 * authenticator-defined sub-Activity to prompt the user to create an
1816 * account; used only to call startActivity(); if null, the prompt
1817 * will not be launched directly, but the necessary {@link Intent}
1818 * will be returned to the caller instead
1819 * @param callback Callback to invoke when the request completes,
1820 * null for no callback
1821 * @param handler {@link Handler} identifying the callback thread,
1822 * null for the main thread
Doug Zongkerff592dc2010-02-23 12:26:33 -08001823 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
Dan Egnor661f0132010-02-19 11:23:00 -08001824 * these fields if activity was specified and an account was created:
1825 * <ul>
1826 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account created
1827 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1828 * </ul>
1829 *
1830 * If no activity was specified, the returned Bundle contains only
1831 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
Dan Egnor8e4378b2010-08-02 18:22:09 -07001832 * actual account creation process. If an error occurred,
1833 * {@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08001834 * <ul>
1835 * <li> {@link AuthenticatorException} if no authenticator was registered for
1836 * this account type or the authenticator failed to respond
1837 * <li> {@link OperationCanceledException} if the operation was canceled for
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001838 * any reason, including the user canceling the creation process or adding accounts
1839 * (of this type) has been disabled by policy
Dan Egnor661f0132010-02-19 11:23:00 -08001840 * <li> {@link IOException} if the authenticator experienced an I/O problem
1841 * creating a new account, usually because of network trouble
1842 * </ul>
1843 */
1844 public AccountManagerFuture<Bundle> addAccount(final String accountType,
1845 final String authTokenType, final String[] requiredFeatures,
1846 final Bundle addAccountOptions,
1847 final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07001848 if (accountType == null) throw new IllegalArgumentException("accountType is null");
Costin Manolachee5847ad2011-09-14 12:52:19 -07001849 final Bundle optionsIn = new Bundle();
1850 if (addAccountOptions != null) {
1851 optionsIn.putAll(addAccountOptions);
1852 }
1853 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
Costin Manolacheb61e8fb2011-09-08 11:26:09 -07001854
Dan Egnor661f0132010-02-19 11:23:00 -08001855 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001856 @Override
Dan Egnor661f0132010-02-19 11:23:00 -08001857 public void doWork() throws RemoteException {
Amith Yamasani27db4682013-03-30 17:07:47 -07001858 mService.addAccount(mResponse, accountType, authTokenType,
Costin Manolachee5847ad2011-09-14 12:52:19 -07001859 requiredFeatures, activity != null, optionsIn);
Dan Egnor661f0132010-02-19 11:23:00 -08001860 }
1861 }.start();
1862 }
1863
1864 /**
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001865 * @see #addAccount(String, String, String[], Bundle, Activity, AccountManagerCallback, Handler)
1866 * @hide
1867 */
1868 public AccountManagerFuture<Bundle> addAccountAsUser(final String accountType,
1869 final String authTokenType, final String[] requiredFeatures,
1870 final Bundle addAccountOptions, final Activity activity,
1871 AccountManagerCallback<Bundle> callback, Handler handler, final UserHandle userHandle) {
1872 if (accountType == null) throw new IllegalArgumentException("accountType is null");
1873 if (userHandle == null) throw new IllegalArgumentException("userHandle is null");
1874 final Bundle optionsIn = new Bundle();
1875 if (addAccountOptions != null) {
1876 optionsIn.putAll(addAccountOptions);
1877 }
1878 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
1879
1880 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08001881 @Override
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001882 public void doWork() throws RemoteException {
1883 mService.addAccountAsUser(mResponse, accountType, authTokenType,
1884 requiredFeatures, activity != null, optionsIn, userHandle.getIdentifier());
1885 }
1886 }.start();
1887 }
1888
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001889
Alexandra Gherghina999d3942014-07-03 11:40:08 +01001890 /**
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001891 * Adds shared accounts from a parent user to a secondary user. Adding the shared account
Amith Yamasani67df64b2012-12-14 12:09:36 -08001892 * doesn't take effect immediately. When the target user starts up, any pending shared accounts
1893 * are attempted to be copied to the target user from the primary via calls to the
1894 * authenticator.
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001895 * @param parentUser parent user
1896 * @param user target user
Amith Yamasani67df64b2012-12-14 12:09:36 -08001897 * @hide
1898 */
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001899 public void addSharedAccountsFromParentUser(UserHandle parentUser, UserHandle user) {
Amith Yamasani67df64b2012-12-14 12:09:36 -08001900 try {
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07001901 mService.addSharedAccountsFromParentUser(parentUser.getIdentifier(),
Sudheer Shankaf88ebeb2017-02-14 18:30:40 -08001902 user.getIdentifier(), mContext.getOpPackageName());
Amith Yamasani67df64b2012-12-14 12:09:36 -08001903 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001904 throw re.rethrowFromSystemServer();
Amith Yamasani67df64b2012-12-14 12:09:36 -08001905 }
1906 }
1907
1908 /**
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001909 * Copies an account from one user to another user.
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001910 * @param account the account to copy
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001911 * @param fromUser the user to copy the account from
1912 * @param toUser the target user
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001913 * @param callback Callback to invoke when the request completes,
1914 * null for no callback
1915 * @param handler {@link Handler} identifying the callback thread,
1916 * null for the main thread
1917 * @return An {@link AccountManagerFuture} which resolves to a Boolean indicated wether it
1918 * succeeded.
1919 * @hide
1920 */
1921 public AccountManagerFuture<Boolean> copyAccountToUser(
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001922 final Account account, final UserHandle fromUser, final UserHandle toUser,
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001923 AccountManagerCallback<Boolean> callback, Handler handler) {
1924 if (account == null) throw new IllegalArgumentException("account is null");
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001925 if (toUser == null || fromUser == null) {
1926 throw new IllegalArgumentException("fromUser and toUser cannot be null");
1927 }
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001928
1929 return new Future2Task<Boolean>(handler, callback) {
1930 @Override
1931 public void doWork() throws RemoteException {
1932 mService.copyAccountToUser(
Xiaohui Chen75f68ce2015-08-14 09:28:07 -07001933 mResponse, account, fromUser.getIdentifier(), toUser.getIdentifier());
Esteban Talavera22dc3b72014-10-31 15:41:12 +00001934 }
1935 @Override
1936 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
1937 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
1938 throw new AuthenticatorException("no result in response");
1939 }
1940 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
1941 }
1942 }.start();
1943 }
1944
1945 /**
Dan Egnor661f0132010-02-19 11:23:00 -08001946 * Confirms that the user knows the password for an account to make extra
1947 * sure they are the owner of the account. The user-entered password can
1948 * be supplied directly, otherwise the authenticator for this account type
1949 * prompts the user with the appropriate interface. This method is
1950 * intended for applications which want extra assurance; for example, the
1951 * phone lock screen uses this to let the user unlock the phone with an
1952 * account password if they forget the lock pattern.
1953 *
1954 * <p>If the user-entered password matches a saved password for this
1955 * account, the request is considered valid; otherwise the authenticator
1956 * verifies the password (usually by contacting the server).
1957 *
1958 * <p>This method may be called from any thread, but the returned
1959 * {@link AccountManagerFuture} must not be used on the main thread.
1960 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07001961 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
1962 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs
1963 * for this function in API level 22.
1964 *
Dan Egnor661f0132010-02-19 11:23:00 -08001965 * @param account The account to confirm password knowledge for
1966 * @param options Authenticator-specific options for the request;
1967 * if the {@link #KEY_PASSWORD} string field is present, the
1968 * authenticator may use it directly rather than prompting the user;
1969 * may be null or empty
1970 * @param activity The {@link Activity} context to use for launching a new
1971 * authenticator-defined sub-Activity to prompt the user to enter a
1972 * password; used only to call startActivity(); if null, the prompt
1973 * will not be launched directly, but the necessary {@link Intent}
1974 * will be returned to the caller instead
1975 * @param callback Callback to invoke when the request completes,
1976 * null for no callback
1977 * @param handler {@link Handler} identifying the callback thread,
1978 * null for the main thread
1979 * @return An {@link AccountManagerFuture} which resolves to a Bundle
1980 * with these fields if activity or password was supplied and
1981 * the account was successfully verified:
1982 * <ul>
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001983 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account verified
Dan Egnor661f0132010-02-19 11:23:00 -08001984 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
1985 * <li> {@link #KEY_BOOLEAN_RESULT} - true to indicate success
1986 * </ul>
1987 *
1988 * If no activity or password was specified, the returned Bundle contains
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001989 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
1990 * password prompt.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001991 *
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001992 * <p>Also the returning Bundle may contain {@link
Simranjit Singh Kohli1663b442015-04-28 11:11:12 -07001993 * #KEY_LAST_AUTHENTICATED_TIME} indicating the last time the
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001994 * credential was validated/created.
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07001995 *
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08001996 * If an error occurred,{@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08001997 * <ul>
1998 * <li> {@link AuthenticatorException} if the authenticator failed to respond
1999 * <li> {@link OperationCanceledException} if the operation was canceled for
2000 * any reason, including the user canceling the password prompt
2001 * <li> {@link IOException} if the authenticator experienced an I/O problem
2002 * verifying the password, usually because of network trouble
2003 * </ul>
Fred Quintana756b7352009-10-21 13:43:10 -07002004 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002005 public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
2006 final Bundle options,
2007 final Activity activity,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002008 final AccountManagerCallback<Bundle> callback,
Fred Quintanaa698f422009-04-08 19:14:54 -07002009 final Handler handler) {
Amith Yamasani2c7bc262012-11-05 16:46:02 -08002010 return confirmCredentialsAsUser(account, options, activity, callback, handler,
Jeff Sharkeyad357d12018-02-02 13:25:31 -07002011 mContext.getUser());
Amith Yamasani2c7bc262012-11-05 16:46:02 -08002012 }
2013
2014 /**
2015 * @hide
2016 * Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)}
2017 * but for the specified user.
2018 */
Mathew Inwood1fde99a2018-08-06 16:43:30 +01002019 @UnsupportedAppUsage
Amith Yamasani2c7bc262012-11-05 16:46:02 -08002020 public AccountManagerFuture<Bundle> confirmCredentialsAsUser(final Account account,
2021 final Bundle options,
2022 final Activity activity,
2023 final AccountManagerCallback<Bundle> callback,
2024 final Handler handler, UserHandle userHandle) {
Fred Quintana382601f2010-03-25 12:25:10 -07002025 if (account == null) throw new IllegalArgumentException("account is null");
Amith Yamasani2c7bc262012-11-05 16:46:02 -08002026 final int userId = userHandle.getIdentifier();
Fred Quintanaa698f422009-04-08 19:14:54 -07002027 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002028 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002029 public void doWork() throws RemoteException {
Amith Yamasani2c7bc262012-11-05 16:46:02 -08002030 mService.confirmCredentialsAsUser(mResponse, account, options, activity != null,
2031 userId);
Fred Quintanaa698f422009-04-08 19:14:54 -07002032 }
Fred Quintana33269202009-04-20 16:05:10 -07002033 }.start();
Fred Quintanaa698f422009-04-08 19:14:54 -07002034 }
2035
Fred Quintana756b7352009-10-21 13:43:10 -07002036 /**
Dan Egnor661f0132010-02-19 11:23:00 -08002037 * Asks the user to enter a new password for an account, updating the
2038 * saved credentials for the account. Normally this happens automatically
2039 * when the server rejects credentials during an auth token fetch, but this
2040 * can be invoked directly to ensure we have the correct credentials stored.
Fred Quintana756b7352009-10-21 13:43:10 -07002041 *
Dan Egnor661f0132010-02-19 11:23:00 -08002042 * <p>This method may be called from any thread, but the returned
2043 * {@link AccountManagerFuture} must not be used on the main thread.
2044 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07002045 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
2046 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
2047 * this function in API level 22.
2048 *
Dan Egnor661f0132010-02-19 11:23:00 -08002049 * @param account The account to update credentials for
2050 * @param authTokenType The credentials entered must allow an auth token
2051 * of this type to be created (but no actual auth token is returned);
2052 * may be null
2053 * @param options Authenticator-specific options for the request;
2054 * may be null or empty
2055 * @param activity The {@link Activity} context to use for launching a new
2056 * authenticator-defined sub-Activity to prompt the user to enter a
2057 * password; used only to call startActivity(); if null, the prompt
2058 * will not be launched directly, but the necessary {@link Intent}
2059 * will be returned to the caller instead
2060 * @param callback Callback to invoke when the request completes,
2061 * null for no callback
2062 * @param handler {@link Handler} identifying the callback thread,
2063 * null for the main thread
2064 * @return An {@link AccountManagerFuture} which resolves to a Bundle
2065 * with these fields if an activity was supplied and the account
2066 * credentials were successfully updated:
Fred Quintana756b7352009-10-21 13:43:10 -07002067 * <ul>
Ian Pedowitz6cc066d2015-08-05 14:23:43 +00002068 * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account
Dan Egnor661f0132010-02-19 11:23:00 -08002069 * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
Fred Quintana756b7352009-10-21 13:43:10 -07002070 * </ul>
Dan Egnor661f0132010-02-19 11:23:00 -08002071 *
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08002072 * If no activity was specified, the returned Bundle contains
Dan Egnor661f0132010-02-19 11:23:00 -08002073 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
Simranjit Singh Kohli6c7c4ad2015-02-23 18:11:14 -08002074 * password prompt. If an error occurred,
Dan Egnor8e4378b2010-08-02 18:22:09 -07002075 * {@link AccountManagerFuture#getResult()} throws:
Dan Egnor661f0132010-02-19 11:23:00 -08002076 * <ul>
2077 * <li> {@link AuthenticatorException} if the authenticator failed to respond
2078 * <li> {@link OperationCanceledException} if the operation was canceled for
2079 * any reason, including the user canceling the password prompt
2080 * <li> {@link IOException} if the authenticator experienced an I/O problem
2081 * verifying the password, usually because of network trouble
2082 * </ul>
Fred Quintana756b7352009-10-21 13:43:10 -07002083 */
2084 public AccountManagerFuture<Bundle> updateCredentials(final Account account,
2085 final String authTokenType,
Fred Quintana31957f12009-10-21 13:43:10 -07002086 final Bundle options, final Activity activity,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002087 final AccountManagerCallback<Bundle> callback,
Fred Quintanaa698f422009-04-08 19:14:54 -07002088 final Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07002089 if (account == null) throw new IllegalArgumentException("account is null");
Fred Quintanaa698f422009-04-08 19:14:54 -07002090 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002091 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002092 public void doWork() throws RemoteException {
2093 mService.updateCredentials(mResponse, account, authTokenType, activity != null,
Fred Quintana31957f12009-10-21 13:43:10 -07002094 options);
Fred Quintanaa698f422009-04-08 19:14:54 -07002095 }
Fred Quintana33269202009-04-20 16:05:10 -07002096 }.start();
Fred Quintanaa698f422009-04-08 19:14:54 -07002097 }
2098
Fred Quintana756b7352009-10-21 13:43:10 -07002099 /**
Dan Egnor661f0132010-02-19 11:23:00 -08002100 * Offers the user an opportunity to change an authenticator's settings.
2101 * These properties are for the authenticator in general, not a particular
2102 * account. Not all authenticators support this method.
Fred Quintana756b7352009-10-21 13:43:10 -07002103 *
Dan Egnor661f0132010-02-19 11:23:00 -08002104 * <p>This method may be called from any thread, but the returned
2105 * {@link AccountManagerFuture} must not be used on the main thread.
2106 *
Carlos Valdivia6eb73a52015-06-11 13:07:11 -07002107 * <p>This method requires the caller to have the same signature as the
2108 * authenticator associated with the specified account type.
Dan Egnor661f0132010-02-19 11:23:00 -08002109 *
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07002110 * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
2111 * MANAGE_ACCOUNTS permission is needed for those platforms. See docs
2112 * for this function in API level 22.
2113 *
Dan Egnor661f0132010-02-19 11:23:00 -08002114 * @param accountType The account type associated with the authenticator
2115 * to adjust
2116 * @param activity The {@link Activity} context to use for launching a new
2117 * authenticator-defined sub-Activity to adjust authenticator settings;
2118 * used only to call startActivity(); if null, the settings dialog will
2119 * not be launched directly, but the necessary {@link Intent} will be
2120 * returned to the caller instead
2121 * @param callback Callback to invoke when the request completes,
2122 * null for no callback
2123 * @param handler {@link Handler} identifying the callback thread,
2124 * null for the main thread
2125 * @return An {@link AccountManagerFuture} which resolves to a Bundle
2126 * which is empty if properties were edited successfully, or
2127 * if no activity was specified, contains only {@link #KEY_INTENT}
2128 * needed to launch the authenticator's settings dialog.
Dan Egnor8e4378b2010-08-02 18:22:09 -07002129 * If an error occurred, {@link AccountManagerFuture#getResult()}
2130 * throws:
Fred Quintana756b7352009-10-21 13:43:10 -07002131 * <ul>
Dan Egnor661f0132010-02-19 11:23:00 -08002132 * <li> {@link AuthenticatorException} if no authenticator was registered for
2133 * this account type or the authenticator failed to respond
2134 * <li> {@link OperationCanceledException} if the operation was canceled for
2135 * any reason, including the user canceling the settings dialog
2136 * <li> {@link IOException} if the authenticator experienced an I/O problem
2137 * updating settings, usually because of network trouble
Fred Quintana756b7352009-10-21 13:43:10 -07002138 * </ul>
Fred Quintana756b7352009-10-21 13:43:10 -07002139 */
2140 public AccountManagerFuture<Bundle> editProperties(final String accountType,
2141 final Activity activity, final AccountManagerCallback<Bundle> callback,
Fred Quintanaa698f422009-04-08 19:14:54 -07002142 final Handler handler) {
Fred Quintana382601f2010-03-25 12:25:10 -07002143 if (accountType == null) throw new IllegalArgumentException("accountType is null");
Fred Quintanaa698f422009-04-08 19:14:54 -07002144 return new AmsTask(activity, handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002145 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002146 public void doWork() throws RemoteException {
2147 mService.editProperties(mResponse, accountType, activity != null);
2148 }
Fred Quintana33269202009-04-20 16:05:10 -07002149 }.start();
Fred Quintanaa698f422009-04-08 19:14:54 -07002150 }
2151
Amith Yamasani12747872015-12-07 14:19:49 -08002152 /**
2153 * @hide
2154 * Checks if the given account exists on any of the users on the device.
2155 * Only the system process can call this method.
2156 *
2157 * @param account The account to check for existence.
2158 * @return whether any user has this account
2159 */
2160 public boolean someUserHasAccount(@NonNull final Account account) {
2161 try {
2162 return mService.someUserHasAccount(account);
2163 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07002164 throw re.rethrowFromSystemServer();
Amith Yamasani12747872015-12-07 14:19:49 -08002165 }
2166 }
2167
Fred Quintanaa698f422009-04-08 19:14:54 -07002168 private void ensureNotOnMainThread() {
2169 final Looper looper = Looper.myLooper();
2170 if (looper != null && looper == mContext.getMainLooper()) {
Fred Quintana53bd2522010-02-05 15:28:12 -08002171 final IllegalStateException exception = new IllegalStateException(
2172 "calling this from your main thread can lead to deadlock");
2173 Log.e(TAG, "calling this from your main thread can lead to deadlock and/or ANRs",
2174 exception);
Fred Quintana751fdc02010-02-09 14:13:18 -08002175 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2176 throw exception;
2177 }
Fred Quintana60307342009-03-24 22:48:12 -07002178 }
2179 }
2180
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002181 private void postToHandler(Handler handler, final AccountManagerCallback<Bundle> callback,
2182 final AccountManagerFuture<Bundle> future) {
Fred Quintanad9d2f112009-04-23 13:36:27 -07002183 handler = handler == null ? mMainHandler : handler;
2184 handler.post(new Runnable() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002185 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002186 public void run() {
2187 callback.run(future);
2188 }
2189 });
2190 }
Fred Quintana60307342009-03-24 22:48:12 -07002191
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002192 private void postToHandler(Handler handler, final OnAccountsUpdateListener listener,
Fred Quintanad9d2f112009-04-23 13:36:27 -07002193 final Account[] accounts) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002194 final Account[] accountsCopy = new Account[accounts.length];
2195 // send a copy to make sure that one doesn't
2196 // change what another sees
2197 System.arraycopy(accounts, 0, accountsCopy, 0, accountsCopy.length);
2198 handler = (handler == null) ? mMainHandler : handler;
Fred Quintanad9d2f112009-04-23 13:36:27 -07002199 handler.post(new Runnable() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002200 @Override
Fred Quintanad9d2f112009-04-23 13:36:27 -07002201 public void run() {
Hiroaki Kuriyama8d3e1592015-10-09 16:30:03 +02002202 synchronized (mAccountsUpdatedListeners) {
2203 try {
2204 if (mAccountsUpdatedListeners.containsKey(listener)) {
Dmitry Dementyev01985ff2017-01-19 16:03:39 -08002205 Set<String> types = mAccountsUpdatedListenersTypes.get(listener);
2206 if (types != null) {
2207 // filter by account type;
2208 ArrayList<Account> filtered = new ArrayList<>();
2209 for (Account account : accountsCopy) {
2210 if (types.contains(account.type)) {
2211 filtered.add(account);
2212 }
2213 }
2214 listener.onAccountsUpdated(
2215 filtered.toArray(new Account[filtered.size()]));
2216 } else {
2217 listener.onAccountsUpdated(accountsCopy);
2218 }
Hiroaki Kuriyama8d3e1592015-10-09 16:30:03 +02002219 }
2220 } catch (SQLException e) {
Dmitry Dementyev01985ff2017-01-19 16:03:39 -08002221 // Better luck next time. If the problem was disk-full,
Hiroaki Kuriyama8d3e1592015-10-09 16:30:03 +02002222 // the STORAGE_OK intent will re-trigger the update.
2223 Log.e(TAG, "Can't update accounts", e);
2224 }
Costin Manolacheb6437242009-09-10 16:14:12 -07002225 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002226 }
2227 });
2228 }
2229
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002230 private abstract class AmsTask extends FutureTask<Bundle> implements AccountManagerFuture<Bundle> {
Mathew Inwood31755f92018-12-20 13:53:36 +00002231 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Fred Quintanaa698f422009-04-08 19:14:54 -07002232 final IAccountManagerResponse mResponse;
Mathew Inwood31755f92018-12-20 13:53:36 +00002233 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Fred Quintanaa698f422009-04-08 19:14:54 -07002234 final Handler mHandler;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002235 final AccountManagerCallback<Bundle> mCallback;
Mathew Inwood31755f92018-12-20 13:53:36 +00002236 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Fred Quintanaa698f422009-04-08 19:14:54 -07002237 final Activity mActivity;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002238 public AmsTask(Activity activity, Handler handler, AccountManagerCallback<Bundle> callback) {
Fred Quintanaa698f422009-04-08 19:14:54 -07002239 super(new Callable<Bundle>() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002240 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002241 public Bundle call() throws Exception {
2242 throw new IllegalStateException("this should never be called");
2243 }
2244 });
2245
2246 mHandler = handler;
2247 mCallback = callback;
2248 mActivity = activity;
2249 mResponse = new Response();
Fred Quintana33269202009-04-20 16:05:10 -07002250 }
2251
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002252 public final AccountManagerFuture<Bundle> start() {
2253 try {
2254 doWork();
2255 } catch (RemoteException e) {
2256 setException(e);
2257 }
Fred Quintana33269202009-04-20 16:05:10 -07002258 return this;
Fred Quintana60307342009-03-24 22:48:12 -07002259 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002260
Sandra Kwan0b84b452016-01-20 15:25:42 -08002261 @Override
Fred Quintana96580e02010-03-04 13:42:42 -08002262 protected void set(Bundle bundle) {
2263 // TODO: somehow a null is being set as the result of the Future. Log this
2264 // case to help debug where this is occurring. When this bug is fixed this
2265 // condition statement should be removed.
2266 if (bundle == null) {
2267 Log.e(TAG, "the bundle must not be null", new Exception());
2268 }
2269 super.set(bundle);
2270 }
2271
Fred Quintanaa698f422009-04-08 19:14:54 -07002272 public abstract void doWork() throws RemoteException;
2273
2274 private Bundle internalGetResult(Long timeout, TimeUnit unit)
2275 throws OperationCanceledException, IOException, AuthenticatorException {
Fred Quintana53bd2522010-02-05 15:28:12 -08002276 if (!isDone()) {
2277 ensureNotOnMainThread();
2278 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002279 try {
2280 if (timeout == null) {
2281 return get();
2282 } else {
2283 return get(timeout, unit);
2284 }
2285 } catch (CancellationException e) {
2286 throw new OperationCanceledException();
2287 } catch (TimeoutException e) {
2288 // fall through and cancel
2289 } catch (InterruptedException e) {
2290 // fall through and cancel
2291 } catch (ExecutionException e) {
2292 final Throwable cause = e.getCause();
2293 if (cause instanceof IOException) {
2294 throw (IOException) cause;
2295 } else if (cause instanceof UnsupportedOperationException) {
2296 throw new AuthenticatorException(cause);
2297 } else if (cause instanceof AuthenticatorException) {
2298 throw (AuthenticatorException) cause;
2299 } else if (cause instanceof RuntimeException) {
2300 throw (RuntimeException) cause;
2301 } else if (cause instanceof Error) {
2302 throw (Error) cause;
2303 } else {
2304 throw new IllegalStateException(cause);
2305 }
2306 } finally {
2307 cancel(true /* interrupt if running */);
2308 }
2309 throw new OperationCanceledException();
2310 }
2311
Sandra Kwan0b84b452016-01-20 15:25:42 -08002312 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002313 public Bundle getResult()
2314 throws OperationCanceledException, IOException, AuthenticatorException {
2315 return internalGetResult(null, null);
2316 }
2317
Sandra Kwan0b84b452016-01-20 15:25:42 -08002318 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002319 public Bundle getResult(long timeout, TimeUnit unit)
2320 throws OperationCanceledException, IOException, AuthenticatorException {
2321 return internalGetResult(timeout, unit);
2322 }
2323
Sandra Kwan0b84b452016-01-20 15:25:42 -08002324 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002325 protected void done() {
2326 if (mCallback != null) {
2327 postToHandler(mHandler, mCallback, this);
2328 }
2329 }
2330
2331 /** Handles the responses from the AccountManager */
2332 private class Response extends IAccountManagerResponse.Stub {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002333 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002334 public void onResult(Bundle bundle) {
tiansimingf58793c2017-09-03 16:48:34 +08002335 if (bundle == null) {
2336 onError(ERROR_CODE_INVALID_RESPONSE, "null bundle returned");
2337 return;
2338 }
Brian Carlstrom46703b02011-04-06 15:41:29 -07002339 Intent intent = bundle.getParcelable(KEY_INTENT);
Fred Quintanaa698f422009-04-08 19:14:54 -07002340 if (intent != null && mActivity != null) {
2341 // since the user provided an Activity we will silently start intents
2342 // that we see
2343 mActivity.startActivity(intent);
2344 // leave the Future running to wait for the real response to this request
Fred Quintanad4a1d2e2009-07-16 16:36:38 -07002345 } else if (bundle.getBoolean("retry")) {
2346 try {
2347 doWork();
2348 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07002349 throw e.rethrowFromSystemServer();
Fred Quintanad4a1d2e2009-07-16 16:36:38 -07002350 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002351 } else {
2352 set(bundle);
2353 }
2354 }
2355
Sandra Kwan0b84b452016-01-20 15:25:42 -08002356 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002357 public void onError(int code, String message) {
Alexandra Gherghina999d3942014-07-03 11:40:08 +01002358 if (code == ERROR_CODE_CANCELED || code == ERROR_CODE_USER_RESTRICTED
2359 || code == ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE) {
2360 // the authenticator indicated that this request was canceled or we were
2361 // forbidden to fulfill; cancel now
Fred Quintanaa698f422009-04-08 19:14:54 -07002362 cancel(true /* mayInterruptIfRunning */);
2363 return;
2364 }
2365 setException(convertErrorToException(code, message));
2366 }
2367 }
2368
Fred Quintana60307342009-03-24 22:48:12 -07002369 }
2370
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002371 private abstract class BaseFutureTask<T> extends FutureTask<T> {
2372 final public IAccountManagerResponse mResponse;
Fred Quintanaa698f422009-04-08 19:14:54 -07002373 final Handler mHandler;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002374
2375 public BaseFutureTask(Handler handler) {
2376 super(new Callable<T>() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002377 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002378 public T call() throws Exception {
Fred Quintanaa698f422009-04-08 19:14:54 -07002379 throw new IllegalStateException("this should never be called");
2380 }
2381 });
Fred Quintanaa698f422009-04-08 19:14:54 -07002382 mHandler = handler;
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002383 mResponse = new Response();
Fred Quintana60307342009-03-24 22:48:12 -07002384 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002385
2386 public abstract void doWork() throws RemoteException;
2387
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002388 public abstract T bundleToResult(Bundle bundle) throws AuthenticatorException;
Fred Quintanaa698f422009-04-08 19:14:54 -07002389
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002390 protected void postRunnableToHandler(Runnable runnable) {
2391 Handler handler = (mHandler == null) ? mMainHandler : mHandler;
2392 handler.post(runnable);
Fred Quintanaa698f422009-04-08 19:14:54 -07002393 }
2394
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002395 protected void startTask() {
Fred Quintanaa698f422009-04-08 19:14:54 -07002396 try {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002397 doWork();
2398 } catch (RemoteException e) {
2399 setException(e);
Fred Quintanaa698f422009-04-08 19:14:54 -07002400 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002401 }
2402
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002403 protected class Response extends IAccountManagerResponse.Stub {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002404 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002405 public void onResult(Bundle bundle) {
2406 try {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002407 T result = bundleToResult(bundle);
2408 if (result == null) {
Fred Quintanaa698f422009-04-08 19:14:54 -07002409 return;
2410 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002411 set(result);
2412 return;
Fred Quintanaa698f422009-04-08 19:14:54 -07002413 } catch (ClassCastException e) {
2414 // we will set the exception below
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002415 } catch (AuthenticatorException e) {
2416 // we will set the exception below
Fred Quintanaa698f422009-04-08 19:14:54 -07002417 }
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002418 onError(ERROR_CODE_INVALID_RESPONSE, "no result in response");
Fred Quintanaa698f422009-04-08 19:14:54 -07002419 }
2420
Sandra Kwan0b84b452016-01-20 15:25:42 -08002421 @Override
Fred Quintanaa698f422009-04-08 19:14:54 -07002422 public void onError(int code, String message) {
Alexandra Gherghina999d3942014-07-03 11:40:08 +01002423 if (code == ERROR_CODE_CANCELED || code == ERROR_CODE_USER_RESTRICTED
2424 || code == ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE) {
2425 // the authenticator indicated that this request was canceled or we were
2426 // forbidden to fulfill; cancel now
Fred Quintanaa698f422009-04-08 19:14:54 -07002427 cancel(true /* mayInterruptIfRunning */);
2428 return;
2429 }
2430 setException(convertErrorToException(code, message));
2431 }
2432 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002433 }
2434
2435 private abstract class Future2Task<T>
2436 extends BaseFutureTask<T> implements AccountManagerFuture<T> {
2437 final AccountManagerCallback<T> mCallback;
2438 public Future2Task(Handler handler, AccountManagerCallback<T> callback) {
2439 super(handler);
2440 mCallback = callback;
2441 }
2442
Sandra Kwan0b84b452016-01-20 15:25:42 -08002443 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002444 protected void done() {
2445 if (mCallback != null) {
2446 postRunnableToHandler(new Runnable() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002447 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002448 public void run() {
2449 mCallback.run(Future2Task.this);
2450 }
2451 });
2452 }
2453 }
2454
2455 public Future2Task<T> start() {
2456 startTask();
2457 return this;
2458 }
2459
2460 private T internalGetResult(Long timeout, TimeUnit unit)
2461 throws OperationCanceledException, IOException, AuthenticatorException {
Fred Quintana53bd2522010-02-05 15:28:12 -08002462 if (!isDone()) {
2463 ensureNotOnMainThread();
2464 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002465 try {
2466 if (timeout == null) {
2467 return get();
2468 } else {
2469 return get(timeout, unit);
2470 }
2471 } catch (InterruptedException e) {
2472 // fall through and cancel
2473 } catch (TimeoutException e) {
2474 // fall through and cancel
2475 } catch (CancellationException e) {
2476 // fall through and cancel
2477 } catch (ExecutionException e) {
2478 final Throwable cause = e.getCause();
2479 if (cause instanceof IOException) {
2480 throw (IOException) cause;
2481 } else if (cause instanceof UnsupportedOperationException) {
2482 throw new AuthenticatorException(cause);
2483 } else if (cause instanceof AuthenticatorException) {
2484 throw (AuthenticatorException) cause;
2485 } else if (cause instanceof RuntimeException) {
2486 throw (RuntimeException) cause;
2487 } else if (cause instanceof Error) {
2488 throw (Error) cause;
2489 } else {
2490 throw new IllegalStateException(cause);
2491 }
2492 } finally {
2493 cancel(true /* interrupt if running */);
2494 }
2495 throw new OperationCanceledException();
2496 }
2497
Sandra Kwan0b84b452016-01-20 15:25:42 -08002498 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002499 public T getResult()
2500 throws OperationCanceledException, IOException, AuthenticatorException {
2501 return internalGetResult(null, null);
2502 }
2503
Sandra Kwan0b84b452016-01-20 15:25:42 -08002504 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002505 public T getResult(long timeout, TimeUnit unit)
2506 throws OperationCanceledException, IOException, AuthenticatorException {
2507 return internalGetResult(timeout, unit);
2508 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002509
Fred Quintana60307342009-03-24 22:48:12 -07002510 }
2511
Fred Quintanaa698f422009-04-08 19:14:54 -07002512 private Exception convertErrorToException(int code, String message) {
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002513 if (code == ERROR_CODE_NETWORK_ERROR) {
Fred Quintanaa698f422009-04-08 19:14:54 -07002514 return new IOException(message);
Fred Quintana60307342009-03-24 22:48:12 -07002515 }
Fred Quintana60307342009-03-24 22:48:12 -07002516
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002517 if (code == ERROR_CODE_UNSUPPORTED_OPERATION) {
Fred Quintana33269202009-04-20 16:05:10 -07002518 return new UnsupportedOperationException(message);
Fred Quintana60307342009-03-24 22:48:12 -07002519 }
Fred Quintanaa698f422009-04-08 19:14:54 -07002520
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002521 if (code == ERROR_CODE_INVALID_RESPONSE) {
Fred Quintana33269202009-04-20 16:05:10 -07002522 return new AuthenticatorException(message);
Fred Quintanaa698f422009-04-08 19:14:54 -07002523 }
2524
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002525 if (code == ERROR_CODE_BAD_ARGUMENTS) {
Fred Quintana33269202009-04-20 16:05:10 -07002526 return new IllegalArgumentException(message);
2527 }
2528
2529 return new AuthenticatorException(message);
2530 }
2531
sunjianf29d5492017-05-11 15:42:31 -07002532 private void getAccountByTypeAndFeatures(String accountType, String[] features,
2533 AccountManagerCallback<Bundle> callback, Handler handler) {
2534 (new AmsTask(null, handler, callback) {
2535 @Override
2536 public void doWork() throws RemoteException {
2537 mService.getAccountByTypeAndFeatures(mResponse, accountType, features,
2538 mContext.getOpPackageName());
2539 }
2540
2541 }).start();
2542 }
2543
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002544 private class GetAuthTokenByTypeAndFeaturesTask
2545 extends AmsTask implements AccountManagerCallback<Bundle> {
Fred Quintana33269202009-04-20 16:05:10 -07002546 GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType,
2547 final String[] features, Activity activityForPrompting,
2548 final Bundle addAccountOptions, final Bundle loginOptions,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002549 AccountManagerCallback<Bundle> callback, Handler handler) {
Fred Quintana33269202009-04-20 16:05:10 -07002550 super(activityForPrompting, handler, callback);
2551 if (accountType == null) throw new IllegalArgumentException("account type is null");
2552 mAccountType = accountType;
2553 mAuthTokenType = authTokenType;
2554 mFeatures = features;
2555 mAddAccountOptions = addAccountOptions;
2556 mLoginOptions = loginOptions;
2557 mMyCallback = this;
2558 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002559 volatile AccountManagerFuture<Bundle> mFuture = null;
Fred Quintana33269202009-04-20 16:05:10 -07002560 final String mAccountType;
Mathew Inwood31755f92018-12-20 13:53:36 +00002561 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Fred Quintana33269202009-04-20 16:05:10 -07002562 final String mAuthTokenType;
2563 final String[] mFeatures;
2564 final Bundle mAddAccountOptions;
Mathew Inwood31755f92018-12-20 13:53:36 +00002565 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Fred Quintana33269202009-04-20 16:05:10 -07002566 final Bundle mLoginOptions;
Mathew Inwood31755f92018-12-20 13:53:36 +00002567 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002568 final AccountManagerCallback<Bundle> mMyCallback;
Fred Quintanaf0fd8432010-03-08 12:48:05 -08002569 private volatile int mNumAccounts = 0;
Fred Quintana33269202009-04-20 16:05:10 -07002570
Sandra Kwan0b84b452016-01-20 15:25:42 -08002571 @Override
Fred Quintana33269202009-04-20 16:05:10 -07002572 public void doWork() throws RemoteException {
sunjianf29d5492017-05-11 15:42:31 -07002573 getAccountByTypeAndFeatures(mAccountType, mFeatures,
2574 new AccountManagerCallback<Bundle>() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002575 @Override
sunjianf29d5492017-05-11 15:42:31 -07002576 public void run(AccountManagerFuture<Bundle> future) {
2577 String accountName = null;
2578 String accountType = null;
Fred Quintana33269202009-04-20 16:05:10 -07002579 try {
sunjianf29d5492017-05-11 15:42:31 -07002580 Bundle result = future.getResult();
2581 accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
2582 accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002583 } catch (OperationCanceledException e) {
2584 setException(e);
2585 return;
2586 } catch (IOException e) {
2587 setException(e);
2588 return;
2589 } catch (AuthenticatorException e) {
2590 setException(e);
2591 return;
Fred Quintana33269202009-04-20 16:05:10 -07002592 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002593
sunjianf29d5492017-05-11 15:42:31 -07002594 if (accountName == null) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002595 if (mActivity != null) {
2596 // no accounts, add one now. pretend that the user directly
2597 // made this request
2598 mFuture = addAccount(mAccountType, mAuthTokenType, mFeatures,
2599 mAddAccountOptions, mActivity, mMyCallback, mHandler);
2600 } else {
2601 // send result since we can't prompt to add an account
2602 Bundle result = new Bundle();
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002603 result.putString(KEY_ACCOUNT_NAME, null);
2604 result.putString(KEY_ACCOUNT_TYPE, null);
2605 result.putString(KEY_AUTHTOKEN, null);
Svet Ganovc1c0d1c2016-09-23 19:15:47 -07002606 result.putBinder(KEY_ACCOUNT_ACCESS_ID, null);
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002607 try {
2608 mResponse.onResult(result);
2609 } catch (RemoteException e) {
2610 // this will never happen
2611 }
2612 // we are done
2613 }
sunjianf29d5492017-05-11 15:42:31 -07002614 } else {
2615 mNumAccounts = 1;
2616 Account account = new Account(accountName, accountType);
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002617 // have a single account, return an authtoken for it
2618 if (mActivity == null) {
sunjianf29d5492017-05-11 15:42:31 -07002619 mFuture = getAuthToken(account, mAuthTokenType,
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002620 false /* notifyAuthFailure */, mMyCallback, mHandler);
2621 } else {
sunjianf29d5492017-05-11 15:42:31 -07002622 mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions,
Fred Quintana33269202009-04-20 16:05:10 -07002623 mActivity, mMyCallback, mHandler);
2624 }
Fred Quintana33269202009-04-20 16:05:10 -07002625 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002626 }}, mHandler);
Fred Quintana33269202009-04-20 16:05:10 -07002627 }
2628
Sandra Kwan0b84b452016-01-20 15:25:42 -08002629 @Override
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002630 public void run(AccountManagerFuture<Bundle> future) {
Fred Quintana33269202009-04-20 16:05:10 -07002631 try {
Fred Quintanaf0fd8432010-03-08 12:48:05 -08002632 final Bundle result = future.getResult();
2633 if (mNumAccounts == 0) {
2634 final String accountName = result.getString(KEY_ACCOUNT_NAME);
2635 final String accountType = result.getString(KEY_ACCOUNT_TYPE);
2636 if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
2637 setException(new AuthenticatorException("account not in result"));
2638 return;
2639 }
Svet Ganovc1c0d1c2016-09-23 19:15:47 -07002640 final String accessId = result.getString(KEY_ACCOUNT_ACCESS_ID);
2641 final Account account = new Account(accountName, accountType, accessId);
Fred Quintanaf0fd8432010-03-08 12:48:05 -08002642 mNumAccounts = 1;
2643 getAuthToken(account, mAuthTokenType, null /* options */, mActivity,
2644 mMyCallback, mHandler);
2645 return;
2646 }
2647 set(result);
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002648 } catch (OperationCanceledException e) {
2649 cancel(true /* mayInterruptIfRUnning */);
2650 } catch (IOException e) {
2651 setException(e);
2652 } catch (AuthenticatorException e) {
2653 setException(e);
Fred Quintana33269202009-04-20 16:05:10 -07002654 }
2655 }
2656 }
2657
Fred Quintana756b7352009-10-21 13:43:10 -07002658 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -08002659 * This convenience helper combines the functionality of {@link #getAccountsByTypeAndFeatures},
2660 * {@link #getAuthToken}, and {@link #addAccount}.
Fred Quintana756b7352009-10-21 13:43:10 -07002661 *
Dmitry Dementyev52745472016-12-02 10:27:45 -08002662 * <p>
2663 * This method gets a list of the accounts matching specific type and feature set which are
Dmitry Dementyev85d8a342017-05-02 17:33:17 -07002664 * visible to the caller (see {@link #getAccountsByType} for details);
2665 * if there is exactly one already visible account, it is used; if there are some
Dmitry Dementyev52745472016-12-02 10:27:45 -08002666 * accounts for which user grant visibility, the user is prompted to pick one; if there are
2667 * none, the user is prompted to add one. Finally, an auth token is acquired for the chosen
2668 * account.
Dan Egnor661f0132010-02-19 11:23:00 -08002669 *
Dmitry Dementyev52745472016-12-02 10:27:45 -08002670 * <p>
2671 * This method may be called from any thread, but the returned {@link AccountManagerFuture} must
2672 * not be used on the main thread.
Dan Egnor661f0132010-02-19 11:23:00 -08002673 *
Dmitry Dementyev52745472016-12-02 10:27:45 -08002674 * <p>
2675 * <b>NOTE:</b> If targeting your app to work on API level 22 and before, MANAGE_ACCOUNTS
2676 * permission is needed for those platforms. See docs for this function in API level 22.
Simranjit Singh Kohli210bace2015-07-29 16:34:49 -07002677 *
Dmitry Dementyev52745472016-12-02 10:27:45 -08002678 * @param accountType The account type required (see {@link #getAccountsByType}), must not be
2679 * null
2680 * @param authTokenType The desired auth token type (see {@link #getAuthToken}), must not be
2681 * null
2682 * @param features Required features for the account (see
2683 * {@link #getAccountsByTypeAndFeatures}), may be null or empty
2684 * @param activity The {@link Activity} context to use for launching new sub-Activities to
2685 * prompt to add an account, select an account, and/or enter a password, as necessary;
2686 * used only to call startActivity(); should not be null
2687 * @param addAccountOptions Authenticator-specific options to use for adding new accounts; may
2688 * be null or empty
2689 * @param getAuthTokenOptions Authenticator-specific options to use for getting auth tokens; may
2690 * be null or empty
2691 * @param callback Callback to invoke when the request completes, null for no callback
2692 * @param handler {@link Handler} identifying the callback thread, null for the main thread
2693 * @return An {@link AccountManagerFuture} which resolves to a Bundle with at least the
2694 * following fields:
2695 * <ul>
2696 * <li>{@link #KEY_ACCOUNT_NAME} - the name of the account
2697 * <li>{@link #KEY_ACCOUNT_TYPE} - the type of the account
2698 * <li>{@link #KEY_AUTHTOKEN} - the auth token you wanted
2699 * </ul>
Dan Egnor661f0132010-02-19 11:23:00 -08002700 *
Dmitry Dementyev52745472016-12-02 10:27:45 -08002701 * If an error occurred, {@link AccountManagerFuture#getResult()} throws:
2702 * <ul>
2703 * <li>{@link AuthenticatorException} if no authenticator was registered for this
2704 * account type or the authenticator failed to respond
2705 * <li>{@link OperationCanceledException} if the operation was canceled for any reason,
2706 * including the user canceling any operation
2707 * <li>{@link IOException} if the authenticator experienced an I/O problem updating
2708 * settings, usually because of network trouble
2709 * </ul>
Fred Quintana756b7352009-10-21 13:43:10 -07002710 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002711 public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
Fred Quintana33269202009-04-20 16:05:10 -07002712 final String accountType, final String authTokenType, final String[] features,
Dan Egnor661f0132010-02-19 11:23:00 -08002713 final Activity activity, final Bundle addAccountOptions,
sunjianf29d5492017-05-11 15:42:31 -07002714 final Bundle getAuthTokenOptions, final AccountManagerCallback<Bundle> callback,
2715 final Handler handler) {
Fred Quintana33269202009-04-20 16:05:10 -07002716 if (accountType == null) throw new IllegalArgumentException("account type is null");
2717 if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002718 final GetAuthTokenByTypeAndFeaturesTask task =
2719 new GetAuthTokenByTypeAndFeaturesTask(accountType, authTokenType, features,
Dan Egnor661f0132010-02-19 11:23:00 -08002720 activity, addAccountOptions, getAuthTokenOptions, callback, handler);
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002721 task.start();
2722 return task;
Fred Quintana60307342009-03-24 22:48:12 -07002723 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002724
Fred Quintana1121bb52011-09-14 23:19:35 -07002725 /**
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002726 * Deprecated in favor of {@link #newChooseAccountIntent(Account, List, String[], String,
2727 * String, String[], Bundle)}.
2728 *
Fred Quintana1121bb52011-09-14 23:19:35 -07002729 * Returns an intent to an {@link Activity} that prompts the user to choose from a list of
2730 * accounts.
2731 * The caller will then typically start the activity by calling
Mark Fickettab249e02012-09-05 09:45:47 -04002732 * <code>startActivityForResult(intent, ...);</code>.
Fred Quintana1121bb52011-09-14 23:19:35 -07002733 * <p>
2734 * On success the activity returns a Bundle with the account name and type specified using
2735 * keys {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE}.
Dmitry Dementyev85d8a342017-05-02 17:33:17 -07002736 * Chosen account is marked as {@link #VISIBILITY_USER_MANAGED_VISIBLE} to the caller
Jeff Sharkey67f9d502017-08-05 13:49:13 -06002737 * (see {@link #setAccountVisibility}) and will be returned to it in consequent
Dmitry Dementyev85d8a342017-05-02 17:33:17 -07002738 * {@link #getAccountsByType}) calls.
Fred Quintana1121bb52011-09-14 23:19:35 -07002739 * <p>
2740 * The most common case is to call this with one account type, e.g.:
2741 * <p>
kmccormickf783ce52013-03-29 14:31:54 -07002742 * <pre> newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null,
Fred Quintanad88324d2011-09-19 11:43:05 -07002743 * null, null, null);</pre>
Fred Quintana1121bb52011-09-14 23:19:35 -07002744 * @param selectedAccount if specified, indicates that the {@link Account} is the currently
2745 * selected one, according to the caller's definition of selected.
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002746 * @param allowableAccounts an optional {@link List} of accounts that are allowed to be
Fred Quintana1121bb52011-09-14 23:19:35 -07002747 * shown. If not specified then this field will not limit the displayed accounts.
2748 * @param allowableAccountTypes an optional string array of account types. These are used
2749 * 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 -07002750 * when adding an account. If not specified then this field will not limit the displayed
2751 * account types when adding an account.
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002752 * @param alwaysPromptForAccount boolean that is ignored.
Fred Quintanad88324d2011-09-19 11:43:05 -07002753 * @param descriptionOverrideText if non-null this string is used as the description in the
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002754 * accounts chooser screen rather than the default
Fred Quintanad88324d2011-09-19 11:43:05 -07002755 * @param addAccountAuthTokenType this string is passed as the {@link #addAccount}
2756 * authTokenType parameter
2757 * @param addAccountRequiredFeatures this string array is passed as the {@link #addAccount}
2758 * requiredFeatures parameter
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002759 * @param addAccountOptions This {@link Bundle} is passed as the {@link #addAccount} options
Fred Quintanad88324d2011-09-19 11:43:05 -07002760 * parameter
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002761 * @return an {@link Intent} that can be used to launch the ChooseAccount activity flow.
Fred Quintana1121bb52011-09-14 23:19:35 -07002762 */
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002763 @Deprecated
2764 static public Intent newChooseAccountIntent(
2765 Account selectedAccount,
Baligh Uddinf2d248d2015-07-10 03:01:47 +00002766 ArrayList<Account> allowableAccounts,
Fred Quintana1121bb52011-09-14 23:19:35 -07002767 String[] allowableAccountTypes,
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002768 boolean alwaysPromptForAccount,
2769 String descriptionOverrideText,
2770 String addAccountAuthTokenType,
2771 String[] addAccountRequiredFeatures,
Fred Quintana1121bb52011-09-14 23:19:35 -07002772 Bundle addAccountOptions) {
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002773 return newChooseAccountIntent(
2774 selectedAccount,
2775 allowableAccounts,
2776 allowableAccountTypes,
2777 descriptionOverrideText,
2778 addAccountAuthTokenType,
2779 addAccountRequiredFeatures,
2780 addAccountOptions);
2781 }
2782
2783 /**
2784 * Returns an intent to an {@link Activity} that prompts the user to choose from a list of
2785 * accounts.
2786 * The caller will then typically start the activity by calling
2787 * <code>startActivityForResult(intent, ...);</code>.
2788 * <p>
2789 * On success the activity returns a Bundle with the account name and type specified using
2790 * keys {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE}.
Dmitry Dementyev85d8a342017-05-02 17:33:17 -07002791 * Chosen account is marked as {@link #VISIBILITY_USER_MANAGED_VISIBLE} to the caller
Jeff Sharkey67f9d502017-08-05 13:49:13 -06002792 * (see {@link #setAccountVisibility}) and will be returned to it in consequent
Dmitry Dementyev85d8a342017-05-02 17:33:17 -07002793 * {@link #getAccountsByType}) calls.
Carlos Valdiviaa3db8ac2015-07-10 13:04:43 -07002794 * <p>
2795 * The most common case is to call this with one account type, e.g.:
2796 * <p>
2797 * <pre> newChooseAccountIntent(null, null, new String[]{"com.google"}, null, null, null,
2798 * null);</pre>
2799 * @param selectedAccount if specified, indicates that the {@link Account} is the currently
2800 * selected one, according to the caller's definition of selected.
2801 * @param allowableAccounts an optional {@link List} of accounts that are allowed to be
2802 * shown. If not specified then this field will not limit the displayed accounts.
2803 * @param allowableAccountTypes an optional string array of account types. These are used
2804 * both to filter the shown accounts and to filter the list of account types that are shown
2805 * when adding an account. If not specified then this field will not limit the displayed
2806 * account types when adding an account.
2807 * @param descriptionOverrideText if non-null this string is used as the description in the
2808 * accounts chooser screen rather than the default
2809 * @param addAccountAuthTokenType this string is passed as the {@link #addAccount}
2810 * authTokenType parameter
2811 * @param addAccountRequiredFeatures this string array is passed as the {@link #addAccount}
2812 * requiredFeatures parameter
2813 * @param addAccountOptions This {@link Bundle} is passed as the {@link #addAccount} options
2814 * parameter
2815 * @return an {@link Intent} that can be used to launch the ChooseAccount activity flow.
2816 */
2817 static public Intent newChooseAccountIntent(
2818 Account selectedAccount,
2819 List<Account> allowableAccounts,
2820 String[] allowableAccountTypes,
2821 String descriptionOverrideText,
2822 String addAccountAuthTokenType,
2823 String[] addAccountRequiredFeatures,
2824 Bundle addAccountOptions) {
Fred Quintana1121bb52011-09-14 23:19:35 -07002825 Intent intent = new Intent();
Amith Yamasani12b8e132013-03-14 10:48:07 -07002826 ComponentName componentName = ComponentName.unflattenFromString(
2827 Resources.getSystem().getString(R.string.config_chooseTypeAndAccountActivity));
2828 intent.setClassName(componentName.getPackageName(),
2829 componentName.getClassName());
Fred Quintana1121bb52011-09-14 23:19:35 -07002830 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ALLOWABLE_ACCOUNTS_ARRAYLIST,
Craig Lafayette3c9c71d2015-07-14 10:48:46 -04002831 allowableAccounts == null ? null : new ArrayList<Account>(allowableAccounts));
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002832 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY,
2833 allowableAccountTypes);
Fred Quintana1121bb52011-09-14 23:19:35 -07002834 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_OPTIONS_BUNDLE,
2835 addAccountOptions);
2836 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_SELECTED_ACCOUNT, selectedAccount);
Fred Quintanab04fe4e2011-09-16 21:17:21 -07002837 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_DESCRIPTION_TEXT_OVERRIDE,
2838 descriptionOverrideText);
2839 intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_AUTH_TOKEN_TYPE_STRING,
2840 addAccountAuthTokenType);
2841 intent.putExtra(
2842 ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_REQUIRED_FEATURES_STRING_ARRAY,
2843 addAccountRequiredFeatures);
Fred Quintana1121bb52011-09-14 23:19:35 -07002844 return intent;
2845 }
2846
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002847 private final HashMap<OnAccountsUpdateListener, Handler> mAccountsUpdatedListeners =
Fred Quintanad9d2f112009-04-23 13:36:27 -07002848 Maps.newHashMap();
2849
Dmitry Dementyev01985ff2017-01-19 16:03:39 -08002850 private final HashMap<OnAccountsUpdateListener, Set<String> > mAccountsUpdatedListenersTypes =
2851 Maps.newHashMap();
2852
Fred Quintanad9d2f112009-04-23 13:36:27 -07002853 /**
Dmitry Dementyev8882d882017-03-14 17:25:46 -07002854 * BroadcastReceiver that listens for the ACTION_VISIBLE_ACCOUNTS_CHANGED intent
Fred Quintanad9d2f112009-04-23 13:36:27 -07002855 * so that it can read the updated list of accounts and send them to the listener
2856 * in mAccountsUpdatedListeners.
2857 */
2858 private final BroadcastReceiver mAccountsChangedBroadcastReceiver = new BroadcastReceiver() {
Sandra Kwan0b84b452016-01-20 15:25:42 -08002859 @Override
Fred Quintanad9d2f112009-04-23 13:36:27 -07002860 public void onReceive(final Context context, final Intent intent) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002861 final Account[] accounts = getAccounts();
2862 // send the result to the listeners
2863 synchronized (mAccountsUpdatedListeners) {
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002864 for (Map.Entry<OnAccountsUpdateListener, Handler> entry :
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002865 mAccountsUpdatedListeners.entrySet()) {
2866 postToHandler(entry.getValue(), entry.getKey(), accounts);
Fred Quintanad9d2f112009-04-23 13:36:27 -07002867 }
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002868 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002869 }
2870 };
2871
2872 /**
Dmitry Dementyev52745472016-12-02 10:27:45 -08002873 * Adds an {@link OnAccountsUpdateListener} to this instance of the {@link AccountManager}. This
2874 * listener will be notified whenever user or AbstractAcccountAuthenticator made changes to
Dmitry Dementyev2ae64092017-01-09 12:48:18 -08002875 * accounts of any type related to the caller. This method is equivalent to
2876 * addOnAccountsUpdatedListener(listener, handler, updateImmediately, null)
Dan Egnor661f0132010-02-19 11:23:00 -08002877 *
Dmitry Dementyev01985ff2017-01-19 16:03:39 -08002878 * @see #addOnAccountsUpdatedListener(OnAccountsUpdateListener, Handler, boolean,
Dmitry Dementyev2ae64092017-01-09 12:48:18 -08002879 * String[])
2880 */
2881 public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
2882 Handler handler, boolean updateImmediately) {
2883 addOnAccountsUpdatedListener(listener, handler,updateImmediately, null);
2884 }
2885
2886 /**
2887 * Adds an {@link OnAccountsUpdateListener} to this instance of the {@link AccountManager}. This
2888 * listener will be notified whenever user or AbstractAcccountAuthenticator made changes to
2889 * accounts of given types related to the caller -
2890 * either list of accounts returned by {@link #getAccounts()}
2891 * was changed, or new account was added for which user can grant access to the caller.
Dmitry Dementyev52745472016-12-02 10:27:45 -08002892 * <p>
2893 * As long as this listener is present, the AccountManager instance will not be
2894 * garbage-collected, and neither will the {@link Context} used to retrieve it, which may be a
2895 * large Activity instance. To avoid memory leaks, you must remove this listener before then.
2896 * Normally listeners are added in an Activity or Service's {@link Activity#onCreate} and
2897 * removed in {@link Activity#onDestroy}.
Dmitry Dementyev52745472016-12-02 10:27:45 -08002898 * <p>
2899 * It is safe to call this method from the main thread.
Ian Pedowitz845d14d2015-08-04 07:47:37 -07002900 *
Dan Egnor661f0132010-02-19 11:23:00 -08002901 * @param listener The listener to send notifications to
Dmitry Dementyev52745472016-12-02 10:27:45 -08002902 * @param handler {@link Handler} identifying the thread to use for notifications, null for the
2903 * main thread
2904 * @param updateImmediately If true, the listener will be invoked (on the handler thread) right
2905 * away with the current account list
Dmitry Dementyev2ae64092017-01-09 12:48:18 -08002906 * @param accountTypes If set, only changes to accounts of given types will be reported.
Fred Quintanad9d2f112009-04-23 13:36:27 -07002907 * @throws IllegalArgumentException if listener is null
2908 * @throws IllegalStateException if listener was already added
2909 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002910 public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
Dmitry Dementyev2ae64092017-01-09 12:48:18 -08002911 Handler handler, boolean updateImmediately, String[] accountTypes) {
Fred Quintanad9d2f112009-04-23 13:36:27 -07002912 if (listener == null) {
2913 throw new IllegalArgumentException("the listener is null");
2914 }
2915 synchronized (mAccountsUpdatedListeners) {
2916 if (mAccountsUpdatedListeners.containsKey(listener)) {
2917 throw new IllegalStateException("this listener is already added");
2918 }
2919 final boolean wasEmpty = mAccountsUpdatedListeners.isEmpty();
2920
2921 mAccountsUpdatedListeners.put(listener, handler);
Dmitry Dementyev01985ff2017-01-19 16:03:39 -08002922 if (accountTypes != null) {
2923 mAccountsUpdatedListenersTypes.put(listener,
Dmitry Dementyev8882d882017-03-14 17:25:46 -07002924 new HashSet<String>(Arrays.asList(accountTypes)));
2925 } else {
2926 mAccountsUpdatedListenersTypes.put(listener, null);
Dmitry Dementyev01985ff2017-01-19 16:03:39 -08002927 }
Dmitry Dementyev52745472016-12-02 10:27:45 -08002928
Fred Quintanad9d2f112009-04-23 13:36:27 -07002929 if (wasEmpty) {
2930 // Register a broadcast receiver to monitor account changes
2931 IntentFilter intentFilter = new IntentFilter();
Dmitry Dementyev8882d882017-03-14 17:25:46 -07002932 intentFilter.addAction(ACTION_VISIBLE_ACCOUNTS_CHANGED);
Costin Manolacheb6437242009-09-10 16:14:12 -07002933 // To recover from disk-full.
Fred Quintanac5d1c6d2010-01-27 12:17:49 -08002934 intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
Fred Quintanad9d2f112009-04-23 13:36:27 -07002935 mContext.registerReceiver(mAccountsChangedBroadcastReceiver, intentFilter);
2936 }
Dmitry Dementyev8882d882017-03-14 17:25:46 -07002937
2938 try {
2939 // Notify AccountManagedService about new receiver.
2940 // The receiver must be unregistered later exactly one time
2941 mService.registerAccountListener(accountTypes, mContext.getOpPackageName());
2942 } catch (RemoteException e) {
2943 throw e.rethrowFromSystemServer();
2944 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002945 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002946 if (updateImmediately) {
Fred Quintanaffd0cb042009-08-15 21:45:26 -07002947 postToHandler(handler, listener, getAccounts());
Fred Quintanad9d2f112009-04-23 13:36:27 -07002948 }
2949 }
2950
2951 /**
Dan Egnor661f0132010-02-19 11:23:00 -08002952 * Removes an {@link OnAccountsUpdateListener} previously registered with
2953 * {@link #addOnAccountsUpdatedListener}. The listener will no longer
2954 * receive notifications of account changes.
2955 *
2956 * <p>It is safe to call this method from the main thread.
2957 *
2958 * <p>No permission is required to call this method.
2959 *
2960 * @param listener The previously added listener to remove
Fred Quintanad9d2f112009-04-23 13:36:27 -07002961 * @throws IllegalArgumentException if listener is null
2962 * @throws IllegalStateException if listener was not already added
2963 */
Fred Quintanaf7ae77c2009-10-02 17:19:31 -07002964 public void removeOnAccountsUpdatedListener(OnAccountsUpdateListener listener) {
Fred Quintana382601f2010-03-25 12:25:10 -07002965 if (listener == null) throw new IllegalArgumentException("listener is null");
Fred Quintanad9d2f112009-04-23 13:36:27 -07002966 synchronized (mAccountsUpdatedListeners) {
Bryan Mawhinney5be61f52009-09-24 14:50:25 +01002967 if (!mAccountsUpdatedListeners.containsKey(listener)) {
Costin Manolache88a211b2009-10-29 11:30:11 -07002968 Log.e(TAG, "Listener was not previously added");
2969 return;
Fred Quintanad9d2f112009-04-23 13:36:27 -07002970 }
Dmitry Dementyev8882d882017-03-14 17:25:46 -07002971 Set<String> accountTypes = mAccountsUpdatedListenersTypes.get(listener);
2972 String[] accountsArray;
2973 if (accountTypes != null) {
2974 accountsArray = accountTypes.toArray(new String[accountTypes.size()]);
2975 } else {
2976 accountsArray = null;
2977 }
Bryan Mawhinney5be61f52009-09-24 14:50:25 +01002978 mAccountsUpdatedListeners.remove(listener);
Dmitry Dementyev01985ff2017-01-19 16:03:39 -08002979 mAccountsUpdatedListenersTypes.remove(listener);
Fred Quintanad9d2f112009-04-23 13:36:27 -07002980 if (mAccountsUpdatedListeners.isEmpty()) {
2981 mContext.unregisterReceiver(mAccountsChangedBroadcastReceiver);
2982 }
Dmitry Dementyev8882d882017-03-14 17:25:46 -07002983 try {
2984 mService.unregisterAccountListener(accountsArray, mContext.getOpPackageName());
2985 } catch (RemoteException e) {
2986 throw e.rethrowFromSystemServer();
2987 }
Fred Quintanad9d2f112009-04-23 13:36:27 -07002988 }
2989 }
Sandra Kwan78812282015-11-04 11:19:47 -08002990
2991 /**
2992 * Asks the user to authenticate with an account of a specified type. The
2993 * authenticator for this account type processes this request with the
2994 * appropriate user interface. If the user does elect to authenticate with a
2995 * new account, a bundle of session data for installing the account later is
2996 * returned with optional account password and account status token.
2997 * <p>
2998 * This method may be called from any thread, but the returned
2999 * {@link AccountManagerFuture} must not be used on the main thread.
3000 * <p>
3001 * <p>
3002 * <b>NOTE:</b> The account will not be installed to the device by calling
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003003 * this api alone. #finishSession should be called after this to install the
3004 * account on device.
Sandra Kwan78812282015-11-04 11:19:47 -08003005 *
3006 * @param accountType The type of account to add; must not be null
3007 * @param authTokenType The type of auth token (see {@link #getAuthToken})
3008 * this account will need to be able to generate, null for none
3009 * @param requiredFeatures The features (see {@link #hasFeatures}) this
3010 * account must have, null for none
3011 * @param options Authenticator-specific options for the request, may be
3012 * null or empty
3013 * @param activity The {@link Activity} context to use for launching a new
3014 * authenticator-defined sub-Activity to prompt the user to
3015 * create an account; used only to call startActivity(); if null,
3016 * the prompt will not be launched directly, but the necessary
3017 * {@link Intent} will be returned to the caller instead
3018 * @param callback Callback to invoke when the request completes, null for
3019 * no callback
3020 * @param handler {@link Handler} identifying the callback thread, null for
3021 * the main thread
3022 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
3023 * these fields if activity was specified and user was authenticated
3024 * with an account:
3025 * <ul>
3026 * <li>{@link #KEY_ACCOUNT_SESSION_BUNDLE} - encrypted Bundle for
3027 * adding the the to the device later.
Sandra Kwan78812282015-11-04 11:19:47 -08003028 * <li>{@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check
3029 * status of the account
3030 * </ul>
3031 * If no activity was specified, the returned Bundle contains only
3032 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
3033 * actual account creation process. If authenticator doesn't support
3034 * this method, the returned Bundle contains only
3035 * {@link #KEY_ACCOUNT_SESSION_BUNDLE} with encrypted
3036 * {@code options} needed to add account later. If an error
3037 * occurred, {@link AccountManagerFuture#getResult()} throws:
3038 * <ul>
3039 * <li>{@link AuthenticatorException} if no authenticator was
3040 * registered for this account type or the authenticator failed to
3041 * respond
3042 * <li>{@link OperationCanceledException} if the operation was
3043 * canceled for any reason, including the user canceling the
3044 * creation process or adding accounts (of this type) has been
3045 * disabled by policy
3046 * <li>{@link IOException} if the authenticator experienced an I/O
3047 * problem creating a new account, usually because of network
3048 * trouble
3049 * </ul>
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003050 * @see #finishSession
Sandra Kwan78812282015-11-04 11:19:47 -08003051 */
Sandra Kwane68c37e2015-11-12 17:11:49 -08003052 public AccountManagerFuture<Bundle> startAddAccountSession(
3053 final String accountType,
3054 final String authTokenType,
3055 final String[] requiredFeatures,
3056 final Bundle options,
3057 final Activity activity,
3058 AccountManagerCallback<Bundle> callback,
3059 Handler handler) {
Sandra Kwan78812282015-11-04 11:19:47 -08003060 if (accountType == null) throw new IllegalArgumentException("accountType is null");
3061 final Bundle optionsIn = new Bundle();
3062 if (options != null) {
3063 optionsIn.putAll(options);
3064 }
3065 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
3066
3067 return new AmsTask(activity, handler, callback) {
3068 @Override
3069 public void doWork() throws RemoteException {
Sandra Kwane68c37e2015-11-12 17:11:49 -08003070 mService.startAddAccountSession(
3071 mResponse,
3072 accountType,
3073 authTokenType,
3074 requiredFeatures,
3075 activity != null,
3076 optionsIn);
3077 }
3078 }.start();
3079 }
3080
3081 /**
Dmitry Dementyev16d69752018-10-30 14:56:53 -07003082 * Asks the user to enter a new password for the account but not updating the
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003083 * saved credentials for the account until {@link #finishSession} is called.
Sandra Kwane68c37e2015-11-12 17:11:49 -08003084 * <p>
3085 * This method may be called from any thread, but the returned
3086 * {@link AccountManagerFuture} must not be used on the main thread.
3087 * <p>
3088 * <b>NOTE:</b> The saved credentials for the account alone will not be
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003089 * updated by calling this API alone. #finishSession should be called after
3090 * this to update local credentials
Sandra Kwane68c37e2015-11-12 17:11:49 -08003091 *
3092 * @param account The account to update credentials for
3093 * @param authTokenType The credentials entered must allow an auth token of
3094 * this type to be created (but no actual auth token is
3095 * returned); may be null
3096 * @param options Authenticator-specific options for the request; may be
3097 * null or empty
3098 * @param activity The {@link Activity} context to use for launching a new
3099 * authenticator-defined sub-Activity to prompt the user to enter
3100 * a password; used only to call startActivity(); if null, the
3101 * prompt will not be launched directly, but the necessary
3102 * {@link Intent} will be returned to the caller instead
3103 * @param callback Callback to invoke when the request completes, null for
3104 * no callback
3105 * @param handler {@link Handler} identifying the callback thread, null for
3106 * the main thread
3107 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
3108 * these fields if an activity was supplied and user was
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003109 * successfully re-authenticated to the account:
Sandra Kwane68c37e2015-11-12 17:11:49 -08003110 * <ul>
3111 * <li>{@link #KEY_ACCOUNT_SESSION_BUNDLE} - encrypted Bundle for
3112 * updating the local credentials on device later.
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003113 * <li>{@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check
3114 * status of the account
Sandra Kwane68c37e2015-11-12 17:11:49 -08003115 * </ul>
3116 * If no activity was specified, the returned Bundle contains
3117 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
3118 * password prompt. If an error occurred,
3119 * {@link AccountManagerFuture#getResult()} throws:
3120 * <ul>
3121 * <li>{@link AuthenticatorException} if the authenticator failed to
3122 * respond
3123 * <li>{@link OperationCanceledException} if the operation was
3124 * canceled for any reason, including the user canceling the
3125 * password prompt
3126 * <li>{@link IOException} if the authenticator experienced an I/O
3127 * problem verifying the password, usually because of network
3128 * trouble
3129 * </ul>
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003130 * @see #finishSession
Sandra Kwane68c37e2015-11-12 17:11:49 -08003131 */
3132 public AccountManagerFuture<Bundle> startUpdateCredentialsSession(
3133 final Account account,
3134 final String authTokenType,
3135 final Bundle options,
3136 final Activity activity,
3137 final AccountManagerCallback<Bundle> callback,
3138 final Handler handler) {
3139 if (account == null) {
3140 throw new IllegalArgumentException("account is null");
3141 }
Carlos Valdivia51b651a2016-03-30 13:44:28 -07003142
3143 // Always include the calling package name. This just makes life easier
3144 // down stream.
3145 final Bundle optionsIn = new Bundle();
3146 if (options != null) {
3147 optionsIn.putAll(options);
3148 }
3149 optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
3150
Sandra Kwane68c37e2015-11-12 17:11:49 -08003151 return new AmsTask(activity, handler, callback) {
3152 @Override
3153 public void doWork() throws RemoteException {
3154 mService.startUpdateCredentialsSession(
3155 mResponse,
3156 account,
3157 authTokenType,
3158 activity != null,
Carlos Valdivia51b651a2016-03-30 13:44:28 -07003159 optionsIn);
Sandra Kwan78812282015-11-04 11:19:47 -08003160 }
3161 }.start();
3162 }
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003163
3164 /**
3165 * Finishes the session started by {@link #startAddAccountSession} or
3166 * {@link #startUpdateCredentialsSession}. This will either add the account
3167 * to AccountManager or update the local credentials stored.
3168 * <p>
3169 * This method may be called from any thread, but the returned
3170 * {@link AccountManagerFuture} must not be used on the main thread.
3171 *
3172 * @param sessionBundle a {@link Bundle} created by {@link #startAddAccountSession} or
3173 * {@link #startUpdateCredentialsSession}
3174 * @param activity The {@link Activity} context to use for launching a new
3175 * authenticator-defined sub-Activity to prompt the user to
3176 * create an account or reauthenticate existing account; used
3177 * only to call startActivity(); if null, the prompt will not
3178 * be launched directly, but the necessary {@link Intent} will
3179 * be returned to the caller instead
3180 * @param callback Callback to invoke when the request completes, null for
3181 * no callback
3182 * @param handler {@link Handler} identifying the callback thread, null for
3183 * the main thread
3184 * @return An {@link AccountManagerFuture} which resolves to a Bundle with
3185 * these fields if an activity was supplied and an account was added
3186 * to device or local credentials were updated::
3187 * <ul>
3188 * <li>{@link #KEY_ACCOUNT_NAME} - the name of the account created
3189 * <li>{@link #KEY_ACCOUNT_TYPE} - the type of the account
Hongming Jin8b442752016-06-26 10:36:21 -07003190 * <li>{@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check
3191 * status of the account
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003192 * </ul>
3193 * If no activity was specified and additional information is needed
3194 * from user, the returned Bundle may contains only
3195 * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
3196 * actual account creation process. If an error occurred,
3197 * {@link AccountManagerFuture#getResult()} throws:
3198 * <ul>
3199 * <li>{@link AuthenticatorException} if no authenticator was
3200 * registered for this account type or the authenticator failed to
3201 * respond
3202 * <li>{@link OperationCanceledException} if the operation was
3203 * canceled for any reason, including the user canceling the
3204 * creation process or adding accounts (of this type) has been
3205 * disabled by policy
3206 * <li>{@link IOException} if the authenticator experienced an I/O
3207 * problem creating a new account, usually because of network
3208 * trouble
3209 * </ul>
3210 * @see #startAddAccountSession and #startUpdateCredentialsSession
3211 */
3212 public AccountManagerFuture<Bundle> finishSession(
3213 final Bundle sessionBundle,
3214 final Activity activity,
3215 AccountManagerCallback<Bundle> callback,
3216 Handler handler) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08003217 return finishSessionAsUser(
3218 sessionBundle,
3219 activity,
Jeff Sharkeyad357d12018-02-02 13:25:31 -07003220 mContext.getUser(),
Sandra Kwan0b84b452016-01-20 15:25:42 -08003221 callback,
3222 handler);
3223 }
3224
3225 /**
3226 * @see #finishSession
3227 * @hide
3228 */
3229 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -06003230 @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
Sandra Kwan0b84b452016-01-20 15:25:42 -08003231 public AccountManagerFuture<Bundle> finishSessionAsUser(
3232 final Bundle sessionBundle,
3233 final Activity activity,
3234 final UserHandle userHandle,
3235 AccountManagerCallback<Bundle> callback,
3236 Handler handler) {
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003237 if (sessionBundle == null) {
3238 throw new IllegalArgumentException("sessionBundle is null");
3239 }
3240
3241 /* Add information required by add account flow */
3242 final Bundle appInfo = new Bundle();
3243 appInfo.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
3244
3245 return new AmsTask(activity, handler, callback) {
3246 @Override
3247 public void doWork() throws RemoteException {
Sandra Kwan0b84b452016-01-20 15:25:42 -08003248 mService.finishSessionAsUser(
3249 mResponse,
3250 sessionBundle,
3251 activity != null,
3252 appInfo,
3253 userHandle.getIdentifier());
Sandra Kwan920f6ef2015-11-10 14:13:29 -08003254 }
3255 }.start();
3256 }
Sandra Kwan390c9d22016-01-12 14:13:37 -08003257
3258 /**
3259 * Checks whether {@link #updateCredentials} or {@link #startUpdateCredentialsSession} should be
3260 * called with respect to the specified account.
3261 * <p>
3262 * This method may be called from any thread, but the returned {@link AccountManagerFuture} must
3263 * not be used on the main thread.
3264 *
3265 * @param account The {@link Account} to be checked whether {@link #updateCredentials} or
3266 * {@link #startUpdateCredentialsSession} should be called
3267 * @param statusToken a String of token to check account staus
3268 * @param callback Callback to invoke when the request completes, null for no callback
3269 * @param handler {@link Handler} identifying the callback thread, null for the main thread
3270 * @return An {@link AccountManagerFuture} which resolves to a Boolean, true if the credentials
3271 * of the account should be updated.
Sandra Kwan390c9d22016-01-12 14:13:37 -08003272 */
Sandra Kwan390c9d22016-01-12 14:13:37 -08003273 public AccountManagerFuture<Boolean> isCredentialsUpdateSuggested(
3274 final Account account,
3275 final String statusToken,
3276 AccountManagerCallback<Boolean> callback,
3277 Handler handler) {
3278 if (account == null) {
3279 throw new IllegalArgumentException("account is null");
3280 }
3281
3282 if (TextUtils.isEmpty(statusToken)) {
3283 throw new IllegalArgumentException("status token is empty");
3284 }
3285
3286 return new Future2Task<Boolean>(handler, callback) {
Sandra Kwan0b84b452016-01-20 15:25:42 -08003287 @Override
Sandra Kwan390c9d22016-01-12 14:13:37 -08003288 public void doWork() throws RemoteException {
3289 mService.isCredentialsUpdateSuggested(
3290 mResponse,
3291 account,
3292 statusToken);
3293 }
Sandra Kwan0b84b452016-01-20 15:25:42 -08003294 @Override
Sandra Kwan390c9d22016-01-12 14:13:37 -08003295 public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
3296 if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
3297 throw new AuthenticatorException("no result in response");
3298 }
3299 return bundle.getBoolean(KEY_BOOLEAN_RESULT);
3300 }
3301 }.start();
3302 }
Svetoslav Ganov5cb29732016-07-11 19:32:30 -07003303
3304 /**
3305 * Gets whether a given package under a user has access to an account.
3306 * Can be called only from the system UID.
3307 *
3308 * @param account The account for which to check.
3309 * @param packageName The package for which to check.
3310 * @param userHandle The user for which to check.
3311 * @return True if the package can access the account.
3312 *
3313 * @hide
3314 */
3315 public boolean hasAccountAccess(@NonNull Account account, @NonNull String packageName,
3316 @NonNull UserHandle userHandle) {
3317 try {
3318 return mService.hasAccountAccess(account, packageName, userHandle);
3319 } catch (RemoteException e) {
3320 throw e.rethrowFromSystemServer();
3321 }
3322 }
3323
3324 /**
3325 * Creates an intent to request access to a given account for a UID.
3326 * The returned intent should be stated for a result where {@link
3327 * Activity#RESULT_OK} result means access was granted whereas {@link
3328 * Activity#RESULT_CANCELED} result means access wasn't granted. Can
3329 * be called only from the system UID.
3330 *
3331 * @param account The account for which to request.
3332 * @param packageName The package name which to request.
3333 * @param userHandle The user for which to request.
3334 * @return The intent to request account access or null if the package
3335 * doesn't exist.
3336 *
3337 * @hide
3338 */
3339 public IntentSender createRequestAccountAccessIntentSenderAsUser(@NonNull Account account,
3340 @NonNull String packageName, @NonNull UserHandle userHandle) {
3341 try {
3342 return mService.createRequestAccountAccessIntentSenderAsUser(account, packageName,
3343 userHandle);
3344 } catch (RemoteException e) {
3345 throw e.rethrowFromSystemServer();
3346 }
3347 }
Fred Quintana60307342009-03-24 22:48:12 -07003348}