AccountManager.java revision 751fdc09bb7ab0ce6feac7b7a823e38ed858feb0
1603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/* 2603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Copyright (C) 2009 The Android Open Source Project 3603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * 4603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Licensed under the Apache License, Version 2.0 (the "License"); 5603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * you may not use this file except in compliance with the License. 6603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * You may obtain a copy of the License at 7603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * 8603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * http://www.apache.org/licenses/LICENSE-2.0 9603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * 10603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Unless required by applicable law or agreed to in writing, software 11603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * distributed under the License is distributed on an "AS IS" BASIS, 12603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * See the License for the specific language governing permissions and 14603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * limitations under the License. 15603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */ 16603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 17603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanapackage android.accounts; 18603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 19603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.app.Activity; 20603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.content.Intent; 21603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.content.Context; 22d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport android.content.IntentFilter; 23d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport android.content.BroadcastReceiver; 24b6437245c280596d0a580b8d67189739cf793250Costin Manolacheimport android.database.SQLException; 25a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Bundle; 26a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Handler; 27a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Looper; 28a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.RemoteException; 293326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintanaimport android.os.Parcelable; 30751fdc09bb7ab0ce6feac7b7a823e38ed858feb0Fred Quintanaimport android.os.Build; 31b6437245c280596d0a580b8d67189739cf793250Costin Manolacheimport android.util.Log; 32603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 33a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.IOException; 34a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.concurrent.Callable; 35a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.concurrent.CancellationException; 36a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.concurrent.ExecutionException; 37a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.concurrent.FutureTask; 38a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.concurrent.TimeoutException; 39a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.concurrent.TimeUnit; 40d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport java.util.HashMap; 41d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport java.util.Map; 42d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana 43d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport com.google.android.collect.Maps; 44603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 45603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/** 46756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * A class that helps with interactions with the AccountManager Service. It provides 47603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * methods to allow for account, password, and authtoken management for all accounts on the 484db3a5b327038e4dc1bc58e3213bb9ad0719bcc1Fred Quintana * device. One accesses the {@link AccountManager} by calling: 49756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <pre> 50a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana * AccountManager accountManager = AccountManager.get(context); 51756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * </pre> 52603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * 53603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * <p> 54756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The AccountManager Service provides storage for the accounts known to the system, 55756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * provides methods to manage them, and allows the registration of authenticators to 56756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which operations such as addAccount and getAuthToken are delegated. 57756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 58756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Many of the calls take an {@link AccountManagerCallback} and {@link Handler} as parameters. 59756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * These calls return immediately but run asynchronously. If a callback is provided then 60756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerCallback#run} will be invoked wen the request completes, successfully 61756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * or not. An {@link AccountManagerFuture} is returned by these requests and also passed into the 62756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * callback. The result if retrieved by calling {@link AccountManagerFuture#getResult()} which 63756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * either returns the result or throws an exception as appropriate. 64756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 65756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The asynchronous request can be made blocking by not providing a callback and instead 66756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * calling {@link AccountManagerFuture#getResult()} on the future that is returned. This will 67756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * cause the running thread to block until the result is returned. Keep in mind that one 68756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * should not block the main thread in this way. Instead one should either use a callback, 69756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * thus making the call asynchronous, or make the blocking call on a separate thread. 70756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 71756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If one wants to ensure that the callback is invoked from a specific handler then they should 72756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * pass the handler to the request. This makes it easier to ensure thread-safety by running 73756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * all of one's logic from a single handler. 74603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */ 75603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanapublic class AccountManager { 76603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String TAG = "AccountManager"; 77603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 78f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final int ERROR_CODE_REMOTE_EXCEPTION = 1; 79f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final int ERROR_CODE_NETWORK_ERROR = 3; 80f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final int ERROR_CODE_CANCELED = 4; 81f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final int ERROR_CODE_INVALID_RESPONSE = 5; 82f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final int ERROR_CODE_UNSUPPORTED_OPERATION = 6; 83f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final int ERROR_CODE_BAD_ARGUMENTS = 7; 84f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final int ERROR_CODE_BAD_REQUEST = 8; 85756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana 86f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_ACCOUNTS = "accounts"; 87f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_AUTHENTICATOR_TYPES = "authenticator_types"; 88f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_USERDATA = "userdata"; 89f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_AUTHTOKEN = "authtoken"; 90f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_PASSWORD = "password"; 91f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_ACCOUNT_NAME = "authAccount"; 92f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_ACCOUNT_TYPE = "accountType"; 93f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_ERROR_CODE = "errorCode"; 94f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_ERROR_MESSAGE = "errorMessage"; 95f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_INTENT = "intent"; 96f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_BOOLEAN_RESULT = "booleanResult"; 97f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_ACCOUNT_AUTHENTICATOR_RESPONSE = "accountAuthenticatorResponse"; 98f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_ACCOUNT_MANAGER_RESPONSE = "accountManagerResponse"; 99f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_AUTH_FAILED_MESSAGE = "authFailedMessage"; 100f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String KEY_AUTH_TOKEN_LABEL = "authTokenLabelKey"; 101f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String ACTION_AUTHENTICATOR_INTENT = 102f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana "android.accounts.AccountAuthenticator"; 103f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String AUTHENTICATOR_META_DATA_NAME = 104f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana "android.accounts.AccountAuthenticator"; 105f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator"; 106f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana 107603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private final Context mContext; 108603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private final IAccountManager mService; 109d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana private final Handler mMainHandler; 110f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana /** 111f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana * Action sent as a broadcast Intent by the AccountsService 112f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana * when accounts are added to and/or removed from the device's 113f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana * database. 114f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana */ 115f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public static final String LOGIN_ACCOUNTS_CHANGED_ACTION = 116f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana "android.accounts.LOGIN_ACCOUNTS_CHANGED"; 117603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1183326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana /** 1193326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana * @hide 1203326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana */ 121603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public AccountManager(Context context, IAccountManager service) { 122603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mContext = context; 123603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mService = service; 124d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana mMainHandler = new Handler(mContext.getMainLooper()); 125603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1270eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana /** 1280eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana * @hide used for testing only 1290eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana */ 1300eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana public AccountManager(Context context, IAccountManager service, Handler handler) { 1310eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana mContext = context; 1320eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana mService = service; 1330eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana mMainHandler = handler; 1340eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana } 1350eabf0228a17e07ef831bc1ee1951c9697d2a079Fred Quintana 136756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 137756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Retrieve an AccountManager instance that is associated with the context that is passed in. 138756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Certain calls such as {@link #addOnAccountsUpdatedListener} use this context internally, 139756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * so the caller must take care to use a {@link Context} whose lifetime is associated with 140756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * the listener registration. 141756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param context The {@link Context} to use when necessary 142756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManager} instance that is associated with context 143756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 144a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public static AccountManager get(Context context) { 145a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE); 146a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 147a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 148756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 149756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Get the password that is associated with the account. Returns null if the account does 150756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * not exist. 151756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 152756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission 153756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running 154756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * with the same UID as the Authenticator for the account. 155756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 156ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public String getPassword(final Account account) { 157603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 158603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return mService.getPassword(account); 159603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 160ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // will never happen 161603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana throw new RuntimeException(e); 162603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 163603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 164603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 165756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 166756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Get the user data named by "key" that is associated with the account. 167756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Returns null if the account does not exist or if it does not have a value for key. 168756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 169756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission 170756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running 171756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * with the same UID as the Authenticator for the account. 172756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 173ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public String getUserData(final Account account, final String key) { 174603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 175603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return mService.getUserData(account, key); 176603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 177ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // will never happen 178603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana throw new RuntimeException(e); 179603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 180603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 181603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 182756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 183756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Query the AccountManager Service for an array that contains a 184756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AuthenticatorDescription} for each registered authenticator. 185756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an array that contains all the authenticators known to the AccountManager service. 186756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This array will be empty if there are no authenticators and will never return null. 187756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 188756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * No permission is required to make this call. 189756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 190ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public AuthenticatorDescription[] getAuthenticatorTypes() { 191603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 192a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return mService.getAuthenticatorTypes(); 193603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 194ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // will never happen 195603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana throw new RuntimeException(e); 196603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 197603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 198603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 199756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 200756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Query the AccountManager Service for all accounts. 201756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an array that contains all the accounts known to the AccountManager service. 202756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This array will be empty if there are no accounts and will never return null. 203756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 204756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS} 205756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 206ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public Account[] getAccounts() { 207a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana try { 208ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return mService.getAccounts(null); 209a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (RemoteException e) { 210ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 211a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw new RuntimeException(e); 212a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 213603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 214603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 215756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 216756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Query the AccountManager for the set of accounts that have a given type. If null 217756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * is passed as the type than all accounts are returned. 218756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param type the account type by which to filter, or null to get all accounts 219756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an array that contains the accounts that match the specified type. This array 220756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * will be empty if no accounts match. It will never return null. 221756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 222756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS} 223756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 224ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public Account[] getAccountsByType(String type) { 225603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 226ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return mService.getAccounts(type); 227603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 228ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 229603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana throw new RuntimeException(e); 230603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 231603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 232603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 233756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 234bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * Tests that the given account has the specified features. If this account does not exist 235bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * then this call returns false. 236bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * <p> 237bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 238bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 239bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 240bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 241bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 242bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * they will generally pass null for the callback and instead call 243bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 244bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * which will then block until the request completes. 245bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * <p> 246bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS}. 247bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * 248bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * @param account The {@link Account} to test 249bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * @param features the features for which to test 250bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * @param callback A callback to invoke when the request completes. If null then 251bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * no callback is invoked. 252bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 253bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * main thread's {@link Handler} is used. 254bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 255bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * The future result is a {@link Boolean} that is true if the account exists and has the 256bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana * specified features. 257bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana */ 2583084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana public AccountManagerFuture<Boolean> hasFeatures(final Account account, 259bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana final String[] features, 260bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana AccountManagerCallback<Boolean> callback, Handler handler) { 261bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana return new Future2Task<Boolean>(handler, callback) { 262bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana public void doWork() throws RemoteException { 2633084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana mService.hasFeatures(mResponse, account, features); 264bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 265bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException { 266bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) { 267bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana throw new AuthenticatorException("no result in response"); 268bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 269bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana return bundle.getBoolean(KEY_BOOLEAN_RESULT); 270bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 271bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana }.start(); 272bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 273bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana 274bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana /** 275c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * Add an account to the AccountManager's set of known accounts. 276756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 277756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission 278756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running 279756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * with the same UID as the Authenticator for the account. 280756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account The account to add 281756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param password The password to associate with the account. May be null. 28231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana * @param userdata A bundle of key/value pairs to set as the account's userdata. May be null. 283756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return true if the account was sucessfully added, false otherwise, for example, 284756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * if the account already exists or if the account is null 285756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 28631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana public boolean addAccountExplicitly(Account account, String password, Bundle userdata) { 287603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 28831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return mService.addAccount(account, password, userdata); 289603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 290ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 291603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana throw new RuntimeException(e); 292603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 293603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 294603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 295756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 296756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Removes the given account. If this account does not exist then this call has no effect. 297756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 298756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 299756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 300756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 301756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 302756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 303756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * they will generally pass null for the callback and instead call 304756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 305756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which will then block until the request completes. 306756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 307756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. 308756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * 309756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account The {@link Account} to remove 310756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param callback A callback to invoke when the request completes. If null then 311756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * no callback is invoked. 312756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 313756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * main thread's {@link Handler} is used. 314756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 315756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The future result is a {@link Boolean} that is true if the account is successfully removed 316756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * or false if the authenticator refuses to remove the account. 317756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 318ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public AccountManagerFuture<Boolean> removeAccount(final Account account, 319ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana AccountManagerCallback<Boolean> callback, Handler handler) { 320ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return new Future2Task<Boolean>(handler, callback) { 321ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void doWork() throws RemoteException { 322ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mService.removeAccount(mResponse, account); 323a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 324ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException { 325f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) { 326ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new AuthenticatorException("no result in response"); 327ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 328f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana return bundle.getBoolean(KEY_BOOLEAN_RESULT); 329a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 330ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana }.start(); 331a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 332a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 333756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 334756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Removes the given authtoken. If this authtoken does not exist for the given account type 335756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * then this call has no effect. 336756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 337756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. 338756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param accountType the account type of the authtoken to invalidate 339756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authToken the authtoken to invalidate 340756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 341ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void invalidateAuthToken(final String accountType, final String authToken) { 342603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 343603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mService.invalidateAuthToken(accountType, authToken); 344603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 345ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 346ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new RuntimeException(e); 347603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 348603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 349603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 350756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 351756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Gets the authtoken named by "authTokenType" for the specified account if it is cached 352756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * by the AccountManager. If no authtoken is cached then null is returned rather than 353756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * asking the authenticaticor to generate one. If the account or the 354756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * authtoken do not exist then null is returned. 355756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 356756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission 357756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running 358756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * with the same UID as the Authenticator for the account. 359756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account the account whose authtoken is to be retrieved, must not be null 360756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authTokenType the type of authtoken to retrieve 361756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an authtoken for the given account and authTokenType, if one is cached by the 362756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * AccountManager, null otherwise. 363756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 364ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public String peekAuthToken(final Account account, final String authTokenType) { 36531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 36688a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "peekAuthToken: the account must not be null"); 36788a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return null; 36831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 36931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (authTokenType == null) { 37031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return null; 37131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 372603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 373603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return mService.peekAuthToken(account, authTokenType); 374603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 375ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 376603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana throw new RuntimeException(e); 377603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 378603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 379603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 380756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 381756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Sets the password for the account. The password may be null. If the account does not exist 382756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * then this call has no affect. 383756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 384756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission 385756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running 386756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * with the same UID as the Authenticator for the account. 387756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account the account whose password is to be set. Must not be null. 388756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param password the password to set for the account. May be null. 389756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 390ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void setPassword(final Account account, final String password) { 39131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 39288a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "the account must not be null"); 39388a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return; 39431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 395603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 396603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mService.setPassword(account, password); 397603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 398ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 399ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new RuntimeException(e); 400603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 401603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 402603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 403756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 404756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Sets the password for account to null. If the account does not exist then this call 405756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * has no effect. 406756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 407756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. 408756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account the account whose password is to be cleared. Must not be null. 409756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 410ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void clearPassword(final Account account) { 41131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 41288a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "the account must not be null"); 41388a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return; 41431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 415603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 416603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mService.clearPassword(account); 417603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 418ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 419ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new RuntimeException(e); 420603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 421603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 422603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 423756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 424756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Sets account's userdata named "key" to the specified value. If the account does not 425756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * exist then this call has no effect. 426756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 427756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission 428756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running 429756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * with the same UID as the Authenticator for the account. 430756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account the account whose userdata is to be set. Must not be null. 431756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param key the key of the userdata to set. Must not be null. 432756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param value the value to set. May be null. 433756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 434ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void setUserData(final Account account, final String key, final String value) { 43531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 43688a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "the account must not be null"); 43788a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return; 43831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 43931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (key == null) { 44088a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "the key must not be null"); 44188a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return; 44231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 443603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 444603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mService.setUserData(account, key, value); 445603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 446ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 447ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new RuntimeException(e); 448603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 449603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 450603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 451756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 452756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Sets the authtoken named by "authTokenType" to the value specified by authToken. 453756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the account does not exist then this call has no effect. 454756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 455756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission 456756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running 457756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * with the same UID as the Authenticator for the account. 458756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account the account whose authtoken is to be set. Must not be null. 459756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authTokenType the type of the authtoken to set. Must not be null. 460756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authToken the authToken to set. May be null. 461756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 462ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void setAuthToken(Account account, final String authTokenType, final String authToken) { 463603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 464603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mService.setAuthToken(account, authTokenType, authToken); 465603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 466ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // won't ever happen 467ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new RuntimeException(e); 468603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 469603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 470603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 471756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 472756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Convenience method that makes a blocking call to 473756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link #getAuthToken(Account, String, boolean, AccountManagerCallback, Handler)} 474756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * then extracts and returns the value of {@link #KEY_AUTHTOKEN} from its result. 475756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 476756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}. 477756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account the account whose authtoken is to be retrieved, must not be null 478756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authTokenType the type of authtoken to retrieve 479756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param notifyAuthFailure if true, cause the AccountManager to put up a "sign-on" notification 480756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * for the account if no authtoken is cached by the AccountManager and the the authenticator 481756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * does not have valid credentials to get an authtoken. 482756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an authtoken for the given account and authTokenType, if one is cached by the 483756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * AccountManager, null otherwise. 484756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @throws AuthenticatorException if the authenticator is not present, unreachable or returns 485756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * an invalid response. 486756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @throws OperationCanceledException if the request is canceled for any reason 487756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @throws java.io.IOException if the authenticator experiences an IOException while attempting 488756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * to communicate with its backend server. 489756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 490a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public String blockingGetAuthToken(Account account, String authTokenType, 491a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana boolean notifyAuthFailure) 492a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throws OperationCanceledException, IOException, AuthenticatorException { 493a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Bundle bundle = getAuthToken(account, authTokenType, notifyAuthFailure, null /* callback */, 494a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana null /* handler */).getResult(); 495f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana return bundle.getString(KEY_AUTHTOKEN); 496a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 497a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 498a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana /** 499756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Request that an authtoken of the specified type be returned for an account. 500756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the Account Manager has a cached authtoken of the requested type then it will 501756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * service the request itself. Otherwise it will pass the request on to the authenticator. 502756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The authenticator can try to service this request with information it already has stored 503756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * in the AccountManager but may need to launch an activity to prompt the 504756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * user to enter credentials. If it is able to retrieve the authtoken it will be returned 505756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * in the result. 506756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 507756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the authenticator needs to prompt the user for credentials it will return an intent to 508756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * the activity that will do the prompting. If an activity is supplied then that activity 509756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * will be used to launch the intent and the result will come from it. Otherwise a result will 510756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * be returned that contains the intent. 511756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 512756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 513756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 514756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 515756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 516756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 517756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * they will generally pass null for the callback and instead call 518756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 519756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which will then block until the request completes. 520756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 521756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}. 522a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana * 523756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account The account whose credentials are to be updated. 524756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authTokenType the auth token to retrieve as part of updating the credentials. 525756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * May be null. 52631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana * @param options authenticator specific options for the request 527756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param activity If the authenticator returns a {@link #KEY_INTENT} in the result then 528756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * the intent will be started with this activity. If activity is null then the result will 529756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * be returned as-is. 530756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param callback A callback to invoke when the request completes. If null then 531756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * no callback is invoked. 532756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 533756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * main thread's {@link Handler} is used. 534756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 535756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The future result is a {@link Bundle} that contains: 536756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <ul> 537756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_ACCOUNT_NAME}, {@link #KEY_ACCOUNT_TYPE} and {@link #KEY_AUTHTOKEN} 538756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * </ul> 539756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the user presses "back" then the request will be canceled. 540a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana */ 541ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public AccountManagerFuture<Bundle> getAuthToken( 54231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana final Account account, final String authTokenType, final Bundle options, 543ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { 544a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (activity == null) throw new IllegalArgumentException("activity is null"); 545a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); 546a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return new AmsTask(activity, handler, callback) { 547a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void doWork() throws RemoteException { 548a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mService.getAuthToken(mResponse, account, authTokenType, 549a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana false /* notifyOnAuthFailure */, true /* expectActivityLaunch */, 55031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana options); 551a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 5523326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana }.start(); 553a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 554a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 555756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 556756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Request that an authtoken of the specified type be returned for an account. 557756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the Account Manager has a cached authtoken of the requested type then it will 558756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * service the request itself. Otherwise it will pass the request on to the authenticator. 559756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The authenticator can try to service this request with information it already has stored 560756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * in the AccountManager but may need to launch an activity to prompt the 561756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * user to enter credentials. If it is able to retrieve the authtoken it will be returned 562756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * in the result. 563756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 564c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * If the authenticator needs to prompt the user for credentials, rather than returning the 565c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * authtoken it will instead return an intent for 566756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * an activity that will do the prompting. If an intent is returned and notifyAuthFailure 567c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * is true then a notification will be created that launches this intent. This intent can be 568c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * invoked by the caller directly to start the activity that prompts the user for the 569c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * updated credentials. Otherwise this activity will not be run until the user activates 570c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * the notification. 571756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 572756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 573756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 574756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 575756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 576756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 577756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * they will generally pass null for the callback and instead call 578756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 579756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which will then block until the request completes. 580756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 581756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}. 582756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * 583756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account The account whose credentials are to be updated. 584756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authTokenType the auth token to retrieve as part of updating the credentials. 585756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * May be null. 586756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param notifyAuthFailure if true and the authenticator returns a {@link #KEY_INTENT} in the 587756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * result then a "sign-on needed" notification will be created that will launch this intent. 588756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param callback A callback to invoke when the request completes. If null then 589756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * no callback is invoked. 590756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 591756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * main thread's {@link Handler} is used. 592756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 593756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The future result is a {@link Bundle} that contains either: 594756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <ul> 595756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_INTENT}, which is to be used to prompt the user for the credentials 596756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_ACCOUNT_NAME}, {@link #KEY_ACCOUNT_TYPE} and {@link #KEY_AUTHTOKEN} 597756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * if the authenticator is able to retrieve the auth token 598756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * </ul> 599756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the user presses "back" then the request will be canceled. 600756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 601ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public AccountManagerFuture<Bundle> getAuthToken( 602a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Account account, final String authTokenType, final boolean notifyAuthFailure, 603ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana AccountManagerCallback<Bundle> callback, Handler handler) { 604a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (account == null) throw new IllegalArgumentException("account is null"); 605a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); 606a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return new AmsTask(null, handler, callback) { 607a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void doWork() throws RemoteException { 608a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mService.getAuthToken(mResponse, account, authTokenType, 609a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana notifyAuthFailure, false /* expectActivityLaunch */, null /* options */); 610a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 6113326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana }.start(); 612a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 613a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 614756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 615756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Request that an account be added with the given accountType. This request 616756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * is processed by the authenticator for the account type. If no authenticator is registered 617756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * in the system then {@link AuthenticatorException} is thrown. 618756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 619756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 620756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 621756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 622756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 623756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 624756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * they will generally pass null for the callback and instead call 625756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 626756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which will then block until the request completes. 627756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 628756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. 629756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * 630756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param accountType The type of account to add. This must not be null. 631756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authTokenType The account that is added should be able to service this auth token 632756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * type. This may be null. 633756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param requiredFeatures The account that is added should support these features. 634756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This array may be null or empty. 635756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param addAccountOptions A bundle of authenticator-specific options that is passed on 636756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * to the authenticator. This may be null. 637756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param activity If the authenticator returns a {@link #KEY_INTENT} in the result then 638756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * the intent will be started with this activity. If activity is null then the result will 639756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * be returned as-is. 640756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param callback A callback to invoke when the request completes. If null then 641756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * no callback is invoked. 642756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 643756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * main thread's {@link Handler} is used. 644756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 645756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The future result is a {@link Bundle} that contains either: 646756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <ul> 647756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_INTENT}, or 648756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_ACCOUNT_NAME}, {@link #KEY_ACCOUNT_TYPE} 649756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * and {@link #KEY_AUTHTOKEN} (if an authTokenType was specified). 650756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * </ul> 651756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 652ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public AccountManagerFuture<Bundle> addAccount(final String accountType, 6533326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final String authTokenType, final String[] requiredFeatures, 6543326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final Bundle addAccountOptions, 655ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { 656a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return new AmsTask(activity, handler, callback) { 657a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void doWork() throws RemoteException { 65888a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache if (accountType == null) { 65988a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "the account must not be null"); 66088a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache // to unblock caller waiting on Future.get() 661c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana set(new Bundle()); 66288a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return; 66388a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache } 664a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mService.addAcount(mResponse, accountType, authTokenType, 6653326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana requiredFeatures, activity != null, addAccountOptions); 666a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 6673326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana }.start(); 668a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 669a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 670ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures( 6713326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final String type, final String[] features, 672ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana AccountManagerCallback<Account[]> callback, Handler handler) { 673ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return new Future2Task<Account[]>(handler, callback) { 6743326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public void doWork() throws RemoteException { 67588a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache if (type == null) { 67688a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "Type is null"); 67788a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache set(new Account[0]); 67888a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return; 67988a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache } 680ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mService.getAccountsByFeatures(mResponse, type, features); 681ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 682ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public Account[] bundleToResult(Bundle bundle) throws AuthenticatorException { 683f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (!bundle.containsKey(KEY_ACCOUNTS)) { 684ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new AuthenticatorException("no result in response"); 685ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 686f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana final Parcelable[] parcelables = bundle.getParcelableArray(KEY_ACCOUNTS); 687ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Account[] descs = new Account[parcelables.length]; 688ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana for (int i = 0; i < parcelables.length; i++) { 689ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana descs[i] = (Account) parcelables[i]; 690ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 691ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return descs; 6923326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 6933326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana }.start(); 6943326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 6953326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 696756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 697756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requests that the authenticator checks that the user knows the credentials for the account. 698756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This is typically done by returning an intent to an activity that prompts the user to 699756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * enter the credentials. This request 700756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * is processed by the authenticator for the account. If no matching authenticator is 701756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * registered in the system then {@link AuthenticatorException} is thrown. 702756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 703756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 704756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 705756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 706756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 707756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 708756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * they will generally pass null for the callback and instead call 709756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 710756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which will then block until the request completes. 711756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 712756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. 713756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * 714756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account The account whose credentials are to be checked 715756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param options authenticator specific options for the request 716756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param activity If the authenticator returns a {@link #KEY_INTENT} in the result then 717756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * the intent will be started with this activity. If activity is null then the result will 718756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * be returned as-is. 719756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param callback A callback to invoke when the request completes. If null then 720756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * no callback is invoked. 721756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 722756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * main thread's {@link Handler} is used. 723756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 724756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The future result is a {@link Bundle} that contains either: 725756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <ul> 726756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_INTENT}, which is to be used to prompt the user for the credentials 727756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE} if the user enters the correct 728756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * credentials 729756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * </ul> 730756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the user presses "back" then the request will be canceled. 731756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 732f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public AccountManagerFuture<Bundle> confirmCredentials(final Account account, 733f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana final Bundle options, 734f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana final Activity activity, 735ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final AccountManagerCallback<Bundle> callback, 736a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Handler handler) { 737a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return new AmsTask(activity, handler, callback) { 738a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void doWork() throws RemoteException { 739f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana mService.confirmCredentials(mResponse, account, options, activity != null); 740a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 7413326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana }.start(); 742a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 743a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 744756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 745756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requests that the authenticator update the the credentials for a user. This is typically 746756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * done by returning an intent to an activity that will prompt the user to update the stored 747756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * credentials for the account. This request 748756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * is processed by the authenticator for the account. If no matching authenticator is 749756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * registered in the system then {@link AuthenticatorException} is thrown. 750756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 751756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 752756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 753756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 754756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 755756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 756756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * they will generally pass null for the callback and instead call 757756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 758756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which will then block until the request completes. 759756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 760756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. 761756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * 762756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param account The account whose credentials are to be updated. 763756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authTokenType the auth token to retrieve as part of updating the credentials. 764756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * May be null. 76531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana * @param options authenticator specific options for the request 766756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param activity If the authenticator returns a {@link #KEY_INTENT} in the result then 767756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * the intent will be started with this activity. If activity is null then the result will 768756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * be returned as-is. 769756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param callback A callback to invoke when the request completes. If null then 770756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * no callback is invoked. 771756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 772756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * main thread's {@link Handler} is used. 773756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 774756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The future result is a {@link Bundle} that contains either: 775756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <ul> 776756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_INTENT}, which is to be used to prompt the user for the credentials 777756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE} if the user enters the correct 778756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * credentials, and optionally a {@link #KEY_AUTHTOKEN} if an authTokenType was provided. 779756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * </ul> 780756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the user presses "back" then the request will be canceled. 781756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 782756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana public AccountManagerFuture<Bundle> updateCredentials(final Account account, 783756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana final String authTokenType, 78431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana final Bundle options, final Activity activity, 785ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final AccountManagerCallback<Bundle> callback, 786a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Handler handler) { 787a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return new AmsTask(activity, handler, callback) { 788a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void doWork() throws RemoteException { 789a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mService.updateCredentials(mResponse, account, authTokenType, activity != null, 79031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana options); 791a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 7923326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana }.start(); 793a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 794a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 795756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 796756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Request that the properties for an authenticator be updated. This is typically done by 797756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * returning an intent to an activity that will allow the user to make changes. This request 798756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * is processed by the authenticator for the account. If no matching authenticator is 799756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * registered in the system then {@link AuthenticatorException} is thrown. 800756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 801756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 802756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 803756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 804756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 805756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 806756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * they will generally pass null for the callback and instead call 807756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 808756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which will then block until the request completes. 809756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 810756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. 811756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * 812756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param accountType The account type of the authenticator whose properties are to be edited. 813756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param activity If the authenticator returns a {@link #KEY_INTENT} in the result then 814756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * the intent will be started with this activity. If activity is null then the result will 815756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * be returned as-is. 816756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param callback A callback to invoke when the request completes. If null then 817756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * no callback is invoked. 818756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 819756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * main thread's {@link Handler} is used. 820756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 821756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The future result is a {@link Bundle} that contains either: 822756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <ul> 823756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_INTENT}, which is to be used to prompt the user for the credentials 824756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> nothing, returned if the edit completes successfully 825756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * </ul> 826756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the user presses "back" then the request will be canceled. 827756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 828756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana public AccountManagerFuture<Bundle> editProperties(final String accountType, 829756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana final Activity activity, final AccountManagerCallback<Bundle> callback, 830a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Handler handler) { 831a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return new AmsTask(activity, handler, callback) { 832a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void doWork() throws RemoteException { 833a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mService.editProperties(mResponse, accountType, activity != null); 834a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 8353326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana }.start(); 836a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 837a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 838a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private void ensureNotOnMainThread() { 839a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Looper looper = Looper.myLooper(); 840a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (looper != null && looper == mContext.getMainLooper()) { 84153bd2522ca7767f46646606123b6e2689b811850Fred Quintana final IllegalStateException exception = new IllegalStateException( 84253bd2522ca7767f46646606123b6e2689b811850Fred Quintana "calling this from your main thread can lead to deadlock"); 84353bd2522ca7767f46646606123b6e2689b811850Fred Quintana Log.e(TAG, "calling this from your main thread can lead to deadlock and/or ANRs", 84453bd2522ca7767f46646606123b6e2689b811850Fred Quintana exception); 845751fdc09bb7ab0ce6feac7b7a823e38ed858feb0Fred Quintana if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO) { 846751fdc09bb7ab0ce6feac7b7a823e38ed858feb0Fred Quintana throw exception; 847751fdc09bb7ab0ce6feac7b7a823e38ed858feb0Fred Quintana } 848a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 849a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 850a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 851ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private void postToHandler(Handler handler, final AccountManagerCallback<Bundle> callback, 852ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final AccountManagerFuture<Bundle> future) { 853d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana handler = handler == null ? mMainHandler : handler; 854d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana handler.post(new Runnable() { 855a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void run() { 856a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana callback.run(future); 857a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 858a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana }); 859603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 860603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 861f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana private void postToHandler(Handler handler, final OnAccountsUpdateListener listener, 862d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana final Account[] accounts) { 863ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final Account[] accountsCopy = new Account[accounts.length]; 864ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // send a copy to make sure that one doesn't 865ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // change what another sees 866ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana System.arraycopy(accounts, 0, accountsCopy, 0, accountsCopy.length); 867ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana handler = (handler == null) ? mMainHandler : handler; 868d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana handler.post(new Runnable() { 869a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void run() { 870b6437245c280596d0a580b8d67189739cf793250Costin Manolache try { 871b6437245c280596d0a580b8d67189739cf793250Costin Manolache listener.onAccountsUpdated(accountsCopy); 872b6437245c280596d0a580b8d67189739cf793250Costin Manolache } catch (SQLException e) { 873b6437245c280596d0a580b8d67189739cf793250Costin Manolache // Better luck next time. If the problem was disk-full, 874b6437245c280596d0a580b8d67189739cf793250Costin Manolache // the STORAGE_OK intent will re-trigger the update. 875b6437245c280596d0a580b8d67189739cf793250Costin Manolache Log.e(TAG, "Can't update accounts", e); 876b6437245c280596d0a580b8d67189739cf793250Costin Manolache } 877a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 878a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana }); 879a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 880a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 881ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private abstract class AmsTask extends FutureTask<Bundle> implements AccountManagerFuture<Bundle> { 882a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final IAccountManagerResponse mResponse; 883a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Handler mHandler; 884ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final AccountManagerCallback<Bundle> mCallback; 885a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Activity mActivity; 886ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public AmsTask(Activity activity, Handler handler, AccountManagerCallback<Bundle> callback) { 887a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana super(new Callable<Bundle>() { 888a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public Bundle call() throws Exception { 889a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw new IllegalStateException("this should never be called"); 890a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 891a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana }); 892a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 893a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mHandler = handler; 894a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mCallback = callback; 895a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mActivity = activity; 896a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mResponse = new Response(); 8973326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 8983326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 899ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public final AccountManagerFuture<Bundle> start() { 900ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 901ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana doWork(); 902ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (RemoteException e) { 903ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana setException(e); 904ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 9053326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return this; 906a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 907a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 908a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public abstract void doWork() throws RemoteException; 909603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 910a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private Bundle internalGetResult(Long timeout, TimeUnit unit) 911a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throws OperationCanceledException, IOException, AuthenticatorException { 91253bd2522ca7767f46646606123b6e2689b811850Fred Quintana if (!isDone()) { 91353bd2522ca7767f46646606123b6e2689b811850Fred Quintana ensureNotOnMainThread(); 91453bd2522ca7767f46646606123b6e2689b811850Fred Quintana } 915a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana try { 916a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (timeout == null) { 917a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return get(); 918a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else { 919a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return get(timeout, unit); 920a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 921a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (CancellationException e) { 922a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw new OperationCanceledException(); 923a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (TimeoutException e) { 924a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // fall through and cancel 925a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (InterruptedException e) { 926a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // fall through and cancel 927a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (ExecutionException e) { 928a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Throwable cause = e.getCause(); 929a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (cause instanceof IOException) { 930a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw (IOException) cause; 931a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else if (cause instanceof UnsupportedOperationException) { 932a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw new AuthenticatorException(cause); 933a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else if (cause instanceof AuthenticatorException) { 934a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw (AuthenticatorException) cause; 935a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else if (cause instanceof RuntimeException) { 936a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw (RuntimeException) cause; 937a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else if (cause instanceof Error) { 938a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw (Error) cause; 939a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else { 940a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw new IllegalStateException(cause); 941a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 942a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } finally { 943a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana cancel(true /* interrupt if running */); 944603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 945a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw new OperationCanceledException(); 946603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 947603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 948a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public Bundle getResult() 949a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throws OperationCanceledException, IOException, AuthenticatorException { 950a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return internalGetResult(null, null); 951603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 952603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 953a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public Bundle getResult(long timeout, TimeUnit unit) 954a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throws OperationCanceledException, IOException, AuthenticatorException { 955a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return internalGetResult(timeout, unit); 956603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 957603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 958a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana protected void done() { 959a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (mCallback != null) { 960a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana postToHandler(mHandler, mCallback, this); 961a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 962a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 963a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 964a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana /** Handles the responses from the AccountManager */ 965a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private class Response extends IAccountManagerResponse.Stub { 966a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void onResult(Bundle bundle) { 967a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Intent intent = bundle.getParcelable("intent"); 968a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (intent != null && mActivity != null) { 969a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // since the user provided an Activity we will silently start intents 970a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // that we see 971a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mActivity.startActivity(intent); 972a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // leave the Future running to wait for the real response to this request 973d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } else if (bundle.getBoolean("retry")) { 974d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana try { 975d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana doWork(); 976d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } catch (RemoteException e) { 977d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // this will only happen if the system process is dead, which means 978d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // we will be dying ourselves 979d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 980a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else { 981a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana set(bundle); 982a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 983a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 984a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 985a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void onError(int code, String message) { 986f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (code == ERROR_CODE_CANCELED) { 987a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // the authenticator indicated that this request was canceled, do so now 988a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana cancel(true /* mayInterruptIfRunning */); 989a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return; 990a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 991a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana setException(convertErrorToException(code, message)); 992a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 993603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 994a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 995603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 996603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 997ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private abstract class BaseFutureTask<T> extends FutureTask<T> { 998ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final public IAccountManagerResponse mResponse; 999a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Handler mHandler; 1000ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1001ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public BaseFutureTask(Handler handler) { 1002ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana super(new Callable<T>() { 1003ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public T call() throws Exception { 1004a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw new IllegalStateException("this should never be called"); 1005a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1006a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana }); 1007a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mHandler = handler; 1008ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mResponse = new Response(); 1009ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1010a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1011ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public abstract void doWork() throws RemoteException; 1012ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1013ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public abstract T bundleToResult(Bundle bundle) throws AuthenticatorException; 1014ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1015ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana protected void postRunnableToHandler(Runnable runnable) { 1016ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Handler handler = (mHandler == null) ? mMainHandler : mHandler; 1017ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana handler.post(runnable); 1018ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1019ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1020ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana protected void startTask() { 1021ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 1022ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana doWork(); 1023ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (RemoteException e) { 1024ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana setException(e); 1025ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1026ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1027ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1028ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana protected class Response extends IAccountManagerResponse.Stub { 1029ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void onResult(Bundle bundle) { 1030ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 1031ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana T result = bundleToResult(bundle); 1032ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (result == null) { 1033ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 1034a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1035ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana set(result); 1036ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 1037ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (ClassCastException e) { 1038ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // we will set the exception below 1039ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (AuthenticatorException e) { 1040ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // we will set the exception below 1041a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1042f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana onError(ERROR_CODE_INVALID_RESPONSE, "no result in response"); 1043ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1044a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1045ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void onError(int code, String message) { 1046f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (code == ERROR_CODE_CANCELED) { 1047ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana cancel(true /* mayInterruptIfRunning */); 1048ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 1049ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1050ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana setException(convertErrorToException(code, message)); 1051ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1052ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1053ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1054a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1055ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private abstract class Future2Task<T> 1056ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana extends BaseFutureTask<T> implements AccountManagerFuture<T> { 1057ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final AccountManagerCallback<T> mCallback; 1058ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public Future2Task(Handler handler, AccountManagerCallback<T> callback) { 1059ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana super(handler); 1060ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mCallback = callback; 1061ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1062a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1063a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana protected void done() { 1064a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (mCallback != null) { 1065ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana postRunnableToHandler(new Runnable() { 1066ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void run() { 1067ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mCallback.run(Future2Task.this); 1068ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1069ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana }); 1070a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1071a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1072a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1073ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public Future2Task<T> start() { 1074ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana startTask(); 1075ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return this; 1076ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1077ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1078ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private T internalGetResult(Long timeout, TimeUnit unit) 1079ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throws OperationCanceledException, IOException, AuthenticatorException { 108053bd2522ca7767f46646606123b6e2689b811850Fred Quintana if (!isDone()) { 108153bd2522ca7767f46646606123b6e2689b811850Fred Quintana ensureNotOnMainThread(); 108253bd2522ca7767f46646606123b6e2689b811850Fred Quintana } 1083a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana try { 1084a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (timeout == null) { 1085a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return get(); 1086a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else { 1087a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return get(timeout, unit); 1088a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1089a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (InterruptedException e) { 1090a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // fall through and cancel 1091a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (TimeoutException e) { 1092a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // fall through and cancel 1093a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (CancellationException e) { 1094ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // fall through and cancel 1095a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (ExecutionException e) { 1096a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Throwable cause = e.getCause(); 1097a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (cause instanceof IOException) { 1098ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw (IOException) cause; 1099a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else if (cause instanceof UnsupportedOperationException) { 1100ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new AuthenticatorException(cause); 1101a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else if (cause instanceof AuthenticatorException) { 1102ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw (AuthenticatorException) cause; 1103a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else if (cause instanceof RuntimeException) { 1104a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw (RuntimeException) cause; 1105a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else if (cause instanceof Error) { 1106a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw (Error) cause; 1107a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else { 1108a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana throw new IllegalStateException(cause); 1109a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1110a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } finally { 1111a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana cancel(true /* interrupt if running */); 1112a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1113ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new OperationCanceledException(); 1114a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1115a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1116ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public T getResult() 1117ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throws OperationCanceledException, IOException, AuthenticatorException { 1118a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return internalGetResult(null, null); 1119603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1120a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1121ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public T getResult(long timeout, TimeUnit unit) 1122ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throws OperationCanceledException, IOException, AuthenticatorException { 1123a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return internalGetResult(timeout, unit); 1124a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1125a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1127603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1128a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private Exception convertErrorToException(int code, String message) { 1129f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (code == ERROR_CODE_NETWORK_ERROR) { 1130a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return new IOException(message); 1131603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1132a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1133f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (code == ERROR_CODE_UNSUPPORTED_OPERATION) { 11343326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return new UnsupportedOperationException(message); 1135a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1136a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1137f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (code == ERROR_CODE_INVALID_RESPONSE) { 11383326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return new AuthenticatorException(message); 11393326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11403326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 1141f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (code == ERROR_CODE_BAD_ARGUMENTS) { 11423326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return new IllegalArgumentException(message); 11433326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11443326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 11453326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return new AuthenticatorException(message); 11463326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11473326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 1148ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private class GetAuthTokenByTypeAndFeaturesTask 1149ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana extends AmsTask implements AccountManagerCallback<Bundle> { 11503326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType, 11513326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final String[] features, Activity activityForPrompting, 11523326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final Bundle addAccountOptions, final Bundle loginOptions, 1153ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana AccountManagerCallback<Bundle> callback, Handler handler) { 11543326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana super(activityForPrompting, handler, callback); 11553326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (accountType == null) throw new IllegalArgumentException("account type is null"); 11563326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mAccountType = accountType; 11573326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mAuthTokenType = authTokenType; 11583326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mFeatures = features; 11593326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mAddAccountOptions = addAccountOptions; 11603326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mLoginOptions = loginOptions; 11613326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mMyCallback = this; 11623326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 1163ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana volatile AccountManagerFuture<Bundle> mFuture = null; 11643326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final String mAccountType; 11653326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final String mAuthTokenType; 11663326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final String[] mFeatures; 11673326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final Bundle mAddAccountOptions; 11683326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final Bundle mLoginOptions; 1169ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final AccountManagerCallback<Bundle> mMyCallback; 11703326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 11713326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public void doWork() throws RemoteException { 1172ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana getAccountsByTypeAndFeatures(mAccountType, mFeatures, 1173ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new AccountManagerCallback<Account[]>() { 1174ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void run(AccountManagerFuture<Account[]> future) { 1175ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Account[] accounts; 11763326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana try { 1177ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana accounts = future.getResult(); 1178ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (OperationCanceledException e) { 1179ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana setException(e); 1180ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 1181ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (IOException e) { 1182ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana setException(e); 1183ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 1184ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (AuthenticatorException e) { 1185ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana setException(e); 1186ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 11873326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 1188ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1189ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (accounts.length == 0) { 1190ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (mActivity != null) { 1191ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // no accounts, add one now. pretend that the user directly 1192ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // made this request 1193ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mFuture = addAccount(mAccountType, mAuthTokenType, mFeatures, 1194ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mAddAccountOptions, mActivity, mMyCallback, mHandler); 1195ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } else { 1196ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // send result since we can't prompt to add an account 1197ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Bundle result = new Bundle(); 1198f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.putString(KEY_ACCOUNT_NAME, null); 1199f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.putString(KEY_ACCOUNT_TYPE, null); 1200f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.putString(KEY_AUTHTOKEN, null); 1201ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 1202ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mResponse.onResult(result); 1203ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (RemoteException e) { 1204ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // this will never happen 1205ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1206ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // we are done 1207ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1208ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } else if (accounts.length == 1) { 1209ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // have a single account, return an authtoken for it 1210ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (mActivity == null) { 1211ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mFuture = getAuthToken(accounts[0], mAuthTokenType, 1212ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana false /* notifyAuthFailure */, mMyCallback, mHandler); 1213ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } else { 1214ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mFuture = getAuthToken(accounts[0], 1215ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mAuthTokenType, mLoginOptions, 12163326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mActivity, mMyCallback, mHandler); 12173326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 1218ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } else { 1219ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (mActivity != null) { 1220ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana IAccountManagerResponse chooseResponse = 1221ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new IAccountManagerResponse.Stub() { 1222ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void onResult(Bundle value) throws RemoteException { 1223ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Account account = new Account( 1224f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana value.getString(KEY_ACCOUNT_NAME), 1225f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana value.getString(KEY_ACCOUNT_TYPE)); 1226ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions, 1227ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mActivity, mMyCallback, mHandler); 1228ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1229ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1230ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void onError(int errorCode, String errorMessage) 1231ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throws RemoteException { 1232ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mResponse.onError(errorCode, errorMessage); 1233ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1234ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana }; 1235ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // have many accounts, launch the chooser 1236ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Intent intent = new Intent(); 1237ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana intent.setClassName("android", 1238ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana "android.accounts.ChooseAccountActivity"); 1239f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana intent.putExtra(KEY_ACCOUNTS, accounts); 1240f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana intent.putExtra(KEY_ACCOUNT_MANAGER_RESPONSE, 1241ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new AccountManagerResponse(chooseResponse)); 1242ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mActivity.startActivity(intent); 1243ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // the result will arrive via the IAccountManagerResponse 1244ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } else { 1245ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // send result since we can't prompt to select an account 1246ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Bundle result = new Bundle(); 1247f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.putString(KEY_ACCOUNTS, null); 1248ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 1249ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mResponse.onResult(result); 1250ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (RemoteException e) { 1251ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // this will never happen 1252ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1253ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // we are done 12543326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 12553326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 1256ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana }}, mHandler); 12573326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 12583326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 1259ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void run(AccountManagerFuture<Bundle> future) { 12603326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana try { 1261f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana set(future.getResult()); 1262f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana } catch (OperationCanceledException e) { 1263f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana cancel(true /* mayInterruptIfRUnning */); 1264f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana } catch (IOException e) { 1265f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana setException(e); 1266f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana } catch (AuthenticatorException e) { 1267f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana setException(e); 12683326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 1269a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 12703326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 1271a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1272756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana /** 1273756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Convenience method that combines the functionality of {@link #getAccountsByTypeAndFeatures}, 1274756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link #getAuthToken(Account, String, Bundle, Activity, AccountManagerCallback, Handler)}, 1275756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * and {@link #addAccount}. It first gets the list of accounts that match accountType and the 1276756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * feature set. If there are none then {@link #addAccount} is invoked with the authTokenType 1277756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * feature set, and addAccountOptions. If there is exactly one then 1278756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link #getAuthToken(Account, String, Bundle, Activity, AccountManagerCallback, Handler)} is 1279756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * called with that account. If there are more than one then a chooser activity is launched 1280756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * to prompt the user to select one of them and then the authtoken is retrieved for it, 1281756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 1282756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * This call returns immediately but runs asynchronously and the result is accessed via the 1283756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link AccountManagerFuture} that is returned. This future is also passed as the sole 1284756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * parameter to the {@link AccountManagerCallback}. If the caller wished to use this 1285756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * method asynchronously then they will generally pass in a callback object that will get 1286756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then 1287756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * they will generally pass null for the callback and instead call 1288756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, 1289756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * which will then block until the request completes. 1290756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <p> 1291756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. 1292756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * 1293756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param accountType the accountType to query; this must be non-null 1294756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param authTokenType the type of authtoken to retrieve; this must be non-null 1295756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param features a filter for the accounts. See {@link #getAccountsByTypeAndFeatures}. 1296756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param activityForPrompting The activity used to start any account management 1297756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * activities that are required to fulfill this request. This may be null. 1298756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param addAccountOptions authenticator-specific options used if an account needs to be added 129931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana * @param getAuthTokenOptions authenticator-specific options passed to getAuthToken 1300756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param callback A callback to invoke when the request completes. If null then 1301756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * no callback is invoked. 1302756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @param handler The {@link Handler} to use to invoke the callback. If null then the 1303756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * main thread's {@link Handler} is used. 1304756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * @return an {@link AccountManagerFuture} that represents the future result of the call. 1305756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * The future result is a {@link Bundle} that contains either: 1306756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <ul> 1307756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_INTENT}, if no activity is supplied yet an activity needs to launched to 1308756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * fulfill the request. 1309756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * <li> {@link #KEY_ACCOUNT_NAME}, {@link #KEY_ACCOUNT_TYPE} and {@link #KEY_AUTHTOKEN} if the 1310756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * request completes successfully. 1311756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * </ul> 1312756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana * If the user presses "back" then the request will be canceled. 1313756b735e9312ee52618158270f0bdd0ec691a712Fred Quintana */ 1314f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public AccountManagerFuture<Bundle> getAuthTokenByFeatures( 13153326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final String accountType, final String authTokenType, final String[] features, 13163326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final Activity activityForPrompting, final Bundle addAccountOptions, 131731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana final Bundle getAuthTokenOptions, 1318ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final AccountManagerCallback<Bundle> callback, final Handler handler) { 13193326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (accountType == null) throw new IllegalArgumentException("account type is null"); 13203326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); 1321f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana final GetAuthTokenByTypeAndFeaturesTask task = 1322f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana new GetAuthTokenByTypeAndFeaturesTask(accountType, authTokenType, features, 132331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana activityForPrompting, addAccountOptions, getAuthTokenOptions, callback, handler); 1324f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana task.start(); 1325f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana return task; 1326603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1327d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana 1328f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana private final HashMap<OnAccountsUpdateListener, Handler> mAccountsUpdatedListeners = 1329d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana Maps.newHashMap(); 1330d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana 1331d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana /** 1332d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * BroadcastReceiver that listens for the LOGIN_ACCOUNTS_CHANGED_ACTION intent 1333d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * so that it can read the updated list of accounts and send them to the listener 1334d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * in mAccountsUpdatedListeners. 1335d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana */ 1336d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana private final BroadcastReceiver mAccountsChangedBroadcastReceiver = new BroadcastReceiver() { 1337d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana public void onReceive(final Context context, final Intent intent) { 1338ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final Account[] accounts = getAccounts(); 1339ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // send the result to the listeners 1340ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana synchronized (mAccountsUpdatedListeners) { 1341f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana for (Map.Entry<OnAccountsUpdateListener, Handler> entry : 1342ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mAccountsUpdatedListeners.entrySet()) { 1343ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana postToHandler(entry.getValue(), entry.getKey(), accounts); 1344d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1345ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1346d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1347d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana }; 1348d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana 1349d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana /** 1350f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana * Add a {@link OnAccountsUpdateListener} to this instance of the {@link AccountManager}. 1351d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * The listener is guaranteed to be invoked on the thread of the Handler that is passed 1352d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * in or the main thread's Handler if handler is null. 1353e00a31155b95686eecc6e1999e904472f8f300caFred Quintana * <p> 1354e00a31155b95686eecc6e1999e904472f8f300caFred Quintana * You must remove this listener before the context that was used to retrieve this 1355e00a31155b95686eecc6e1999e904472f8f300caFred Quintana * {@link AccountManager} instance goes away. This generally means when the Activity 1356e00a31155b95686eecc6e1999e904472f8f300caFred Quintana * or Service you are running is stopped. 1357d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * @param listener the listener to add 1358d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * @param handler the Handler whose thread will be used to invoke the listener. If null 1359d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * the AccountManager context's main thread will be used. 1360d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * @param updateImmediately if true then the listener will be invoked as a result of this 1361d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * call. 1362d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * @throws IllegalArgumentException if listener is null 1363d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * @throws IllegalStateException if listener was already added 1364d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana */ 1365f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener, 1366d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana Handler handler, boolean updateImmediately) { 1367d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana if (listener == null) { 1368d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana throw new IllegalArgumentException("the listener is null"); 1369d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1370d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana synchronized (mAccountsUpdatedListeners) { 1371d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana if (mAccountsUpdatedListeners.containsKey(listener)) { 1372d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana throw new IllegalStateException("this listener is already added"); 1373d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1374d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana final boolean wasEmpty = mAccountsUpdatedListeners.isEmpty(); 1375d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana 1376d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana mAccountsUpdatedListeners.put(listener, handler); 1377d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana 1378d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana if (wasEmpty) { 1379d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana // Register a broadcast receiver to monitor account changes 1380d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana IntentFilter intentFilter = new IntentFilter(); 1381f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana intentFilter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION); 1382b6437245c280596d0a580b8d67189739cf793250Costin Manolache // To recover from disk-full. 1383c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); 1384d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana mContext.registerReceiver(mAccountsChangedBroadcastReceiver, intentFilter); 1385d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1386d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1387d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana 1388d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana if (updateImmediately) { 1389ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana postToHandler(handler, listener, getAccounts()); 1390d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1391d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1392d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana 1393d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana /** 1394f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana * Remove an {@link OnAccountsUpdateListener} that was previously registered with 1395d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * {@link #addOnAccountsUpdatedListener}. 1396d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * @param listener the listener to remove 1397d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * @throws IllegalArgumentException if listener is null 1398d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana * @throws IllegalStateException if listener was not already added 1399d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana */ 1400f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana public void removeOnAccountsUpdatedListener(OnAccountsUpdateListener listener) { 1401d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana if (listener == null) { 140288a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "Missing listener"); 140388a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return; 1404d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1405d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana synchronized (mAccountsUpdatedListeners) { 14065be61f5b3ad61706b72c1f6b00914ab042dc6bedBryan Mawhinney if (!mAccountsUpdatedListeners.containsKey(listener)) { 140788a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache Log.e(TAG, "Listener was not previously added"); 140888a211b148dd94df1f178338c94fdd7d01f53863Costin Manolache return; 1409d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 14105be61f5b3ad61706b72c1f6b00914ab042dc6bedBryan Mawhinney mAccountsUpdatedListeners.remove(listener); 1411d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana if (mAccountsUpdatedListeners.isEmpty()) { 1412d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana mContext.unregisterReceiver(mAccountsChangedBroadcastReceiver); 1413d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1414d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1415d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintana } 1416603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana} 1417