am bf13850b: am f7ae77cd: account manager api review changes

Merge commit 'bf13850bed17d994077d1e6226b6330dd960bf26' into eclair-mr2-plus-aosp

* commit 'bf13850bed17d994077d1e6226b6330dd960bf26':
  account manager api review changes
This commit is contained in:
Fred Quintana
2009-10-05 11:46:07 -07:00
committed by Android Git Automerger
23 changed files with 660 additions and 1059 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -19,9 +19,10 @@ package android.accounts;
import android.os.Bundle; import android.os.Bundle;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.Binder; import android.os.Binder;
import android.util.Log; import android.os.IBinder;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.Manifest; import android.Manifest;
/** /**
@@ -36,7 +37,7 @@ public abstract class AbstractAccountAuthenticator {
mContext = context; mContext = context;
} }
class Transport extends IAccountAuthenticator.Stub { private class Transport extends IAccountAuthenticator.Stub {
public void addAccount(IAccountAuthenticatorResponse response, String accountType, public void addAccount(IAccountAuthenticatorResponse response, String accountType,
String authTokenType, String[] requiredFeatures, Bundle options) String authTokenType, String[] requiredFeatures, Bundle options)
throws RemoteException { throws RemoteException {
@@ -47,53 +48,38 @@ public abstract class AbstractAccountAuthenticator {
new AccountAuthenticatorResponse(response), new AccountAuthenticatorResponse(response),
accountType, authTokenType, requiredFeatures, options); accountType, authTokenType, requiredFeatures, options);
} catch (NetworkErrorException e) { } catch (NetworkErrorException e) {
response.onError(Constants.ERROR_CODE_NETWORK_ERROR, e.getMessage()); response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
return; return;
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION, response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"addAccount not supported"); "addAccount not supported");
return; return;
} }
if (result != null) { if (result != null) {
response.onResult(result); response.onResult(result);
} else {
response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"no response from the authenticator");
} }
} }
public void confirmPassword(IAccountAuthenticatorResponse response,
Account account, String password) throws RemoteException {
checkBinderPermission();
boolean result;
try {
result = AbstractAccountAuthenticator.this.confirmPassword(
new AccountAuthenticatorResponse(response),
account, password);
} catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION,
"confirmPassword not supported");
return;
} catch (NetworkErrorException e) {
response.onError(Constants.ERROR_CODE_NETWORK_ERROR, e.getMessage());
return;
}
Bundle bundle = new Bundle();
bundle.putBoolean(Constants.BOOLEAN_RESULT_KEY, result);
response.onResult(bundle);
}
public void confirmCredentials(IAccountAuthenticatorResponse response, public void confirmCredentials(IAccountAuthenticatorResponse response,
Account account) throws RemoteException { Account account, Bundle options) throws RemoteException {
checkBinderPermission(); checkBinderPermission();
final Bundle result; final Bundle result;
try { try {
result = AbstractAccountAuthenticator.this.confirmCredentials( result = AbstractAccountAuthenticator.this.confirmCredentials(
new AccountAuthenticatorResponse(response), account); new AccountAuthenticatorResponse(response), account, options);
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION, response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"confirmCredentials not supported"); "confirmCredentials not supported");
return; return;
} }
if (result != null) { if (result != null) {
response.onResult(result); response.onResult(result);
} else {
response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"no response from the authenticator");
} }
} }
@@ -103,14 +89,14 @@ public abstract class AbstractAccountAuthenticator {
checkBinderPermission(); checkBinderPermission();
try { try {
Bundle result = new Bundle(); Bundle result = new Bundle();
result.putString(Constants.AUTH_TOKEN_LABEL_KEY, result.putString(AccountManager.KEY_AUTH_TOKEN_LABEL,
AbstractAccountAuthenticator.this.getAuthTokenLabel(authTokenType)); AbstractAccountAuthenticator.this.getAuthTokenLabel(authTokenType));
response.onResult(result); response.onResult(result);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
response.onError(Constants.ERROR_CODE_BAD_ARGUMENTS, response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
"unknown authTokenType"); "unknown authTokenType");
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION, response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"getAuthTokenTypeLabel not supported"); "getAuthTokenTypeLabel not supported");
} }
} }
@@ -125,12 +111,15 @@ public abstract class AbstractAccountAuthenticator {
authTokenType, loginOptions); authTokenType, loginOptions);
if (result != null) { if (result != null) {
response.onResult(result); response.onResult(result);
} else {
response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"no response from the authenticator");
} }
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION, response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"getAuthToken not supported"); "getAuthToken not supported");
} catch (NetworkErrorException e) { } catch (NetworkErrorException e) {
response.onError(Constants.ERROR_CODE_NETWORK_ERROR, e.getMessage()); response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
} }
} }
@@ -143,12 +132,15 @@ public abstract class AbstractAccountAuthenticator {
new AccountAuthenticatorResponse(response), account, new AccountAuthenticatorResponse(response), account,
authTokenType, loginOptions); authTokenType, loginOptions);
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION, response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"updateCredentials not supported"); "updateCredentials not supported");
return; return;
} }
if (result != null) { if (result != null) {
response.onResult(result); response.onResult(result);
} else {
response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"no response from the authenticator");
} }
} }
@@ -160,12 +152,15 @@ public abstract class AbstractAccountAuthenticator {
result = AbstractAccountAuthenticator.this.editProperties( result = AbstractAccountAuthenticator.this.editProperties(
new AccountAuthenticatorResponse(response), accountType); new AccountAuthenticatorResponse(response), accountType);
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION, response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"editProperties not supported"); "editProperties not supported");
return; return;
} }
if (result != null) { if (result != null) {
response.onResult(result); response.onResult(result);
} else {
response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"no response from the authenticator");
} }
} }
@@ -177,15 +172,18 @@ public abstract class AbstractAccountAuthenticator {
result = AbstractAccountAuthenticator.this.hasFeatures( result = AbstractAccountAuthenticator.this.hasFeatures(
new AccountAuthenticatorResponse(response), account, features); new AccountAuthenticatorResponse(response), account, features);
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION, response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"hasFeatures not supported"); "hasFeatures not supported");
return; return;
} catch (NetworkErrorException e) { } catch (NetworkErrorException e) {
response.onError(Constants.ERROR_CODE_NETWORK_ERROR, e.getMessage()); response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
return; return;
} }
if (result != null) { if (result != null) {
response.onResult(result); response.onResult(result);
} else {
response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"no response from the authenticator");
} }
} }
@@ -197,34 +195,34 @@ public abstract class AbstractAccountAuthenticator {
new AccountAuthenticatorResponse(response), account); new AccountAuthenticatorResponse(response), account);
if (result != null) { if (result != null) {
response.onResult(result); response.onResult(result);
} else {
response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"no response from the authenticator");
} }
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION, response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"getAccountRemovalAllowed not supported"); "getAccountRemovalAllowed not supported");
return;
} catch (NetworkErrorException e) { } catch (NetworkErrorException e) {
response.onError(Constants.ERROR_CODE_NETWORK_ERROR, e.getMessage()); response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
return;
} }
} }
} }
private void checkBinderPermission() { private void checkBinderPermission() {
final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid();
final String perm = Manifest.permission.ACCOUNT_MANAGER_SERVICE; final String perm = Manifest.permission.ACCOUNT_MANAGER;
if (mContext.checkCallingOrSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) { if (mContext.checkCallingOrSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("caller uid " + uid + " lacks " + perm); throw new SecurityException("caller uid " + uid + " lacks " + perm);
} }
} }
Transport mTransport = new Transport(); private Transport mTransport = new Transport();
/** /**
* @return the IAccountAuthenticator binder transport object * @return the IBinder for the AccountAuthenticator
*/ */
public final IAccountAuthenticator getIAccountAuthenticator() public final IBinder getIBinder() {
{ return mTransport.asBinder();
return mTransport;
} }
/** /**
@@ -244,11 +242,8 @@ public abstract class AbstractAccountAuthenticator {
public abstract Bundle addAccount(AccountAuthenticatorResponse response, String accountType, public abstract Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
String authTokenType, String[] requiredFeatures, Bundle options) String authTokenType, String[] requiredFeatures, Bundle options)
throws NetworkErrorException; throws NetworkErrorException;
/* @deprecated */
public abstract boolean confirmPassword(AccountAuthenticatorResponse response,
Account account, String password) throws NetworkErrorException;
public abstract Bundle confirmCredentials(AccountAuthenticatorResponse response, public abstract Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account); Account account, Bundle options);
public abstract Bundle getAuthToken(AccountAuthenticatorResponse response, public abstract Bundle getAuthToken(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle loginOptions) Account account, String authTokenType, Bundle loginOptions)
throws NetworkErrorException; throws NetworkErrorException;
@@ -260,7 +255,7 @@ public abstract class AbstractAccountAuthenticator {
public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response,
Account account) throws NetworkErrorException { Account account) throws NetworkErrorException {
final Bundle result = new Bundle(); final Bundle result = new Bundle();
result.putBoolean(Constants.BOOLEAN_RESULT_KEY, true); result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
return result; return result;
} }
} }

View File

@@ -63,10 +63,10 @@ public class AccountAuthenticatorActivity extends Activity {
if (icicle == null) { if (icicle == null) {
Intent intent = getIntent(); Intent intent = getIntent();
mAccountAuthenticatorResponse = mAccountAuthenticatorResponse =
intent.getParcelableExtra(Constants.ACCOUNT_AUTHENTICATOR_RESPONSE_KEY); intent.getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
} else { } else {
mAccountAuthenticatorResponse = mAccountAuthenticatorResponse =
icicle.getParcelable(Constants.ACCOUNT_AUTHENTICATOR_RESPONSE_KEY); icicle.getParcelable(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
} }
if (mAccountAuthenticatorResponse != null) { if (mAccountAuthenticatorResponse != null) {
@@ -79,7 +79,7 @@ public class AccountAuthenticatorActivity extends Activity {
* @param outState where to store any instance data * @param outState where to store any instance data
*/ */
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(Bundle outState) {
outState.putParcelable(Constants.ACCOUNT_AUTHENTICATOR_RESPONSE_KEY, outState.putParcelable(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
mAccountAuthenticatorResponse); mAccountAuthenticatorResponse);
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@@ -93,7 +93,7 @@ public class AccountAuthenticatorActivity extends Activity {
if (mResultBundle != null) { if (mResultBundle != null) {
mAccountAuthenticatorResponse.onResult(mResultBundle); mAccountAuthenticatorResponse.onResult(mResultBundle);
} else { } else {
mAccountAuthenticatorResponse.onError(Constants.ERROR_CODE_CANCELED, "canceled"); mAccountAuthenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
} }
mAccountAuthenticatorResponse = null; mAccountAuthenticatorResponse = null;
} }

View File

@@ -35,8 +35,8 @@ import android.text.TextUtils;
private static final String TAG = "Account"; private static final String TAG = "Account";
public AccountAuthenticatorCache(Context context) { public AccountAuthenticatorCache(Context context) {
super(context, Constants.AUTHENTICATOR_INTENT_ACTION, super(context, AccountManager.ACTION_AUTHENTICATOR_INTENT,
Constants.AUTHENTICATOR_META_DATA_NAME, Constants.AUTHENTICATOR_ATTRIBUTES_NAME); AccountManager.AUTHENTICATOR_META_DATA_NAME, AccountManager.AUTHENTICATOR_ATTRIBUTES_NAME);
} }
public AuthenticatorDescription parseServiceAttributes(String packageName, AttributeSet attrs) { public AuthenticatorDescription parseServiceAttributes(String packageName, AttributeSet attrs) {

View File

@@ -28,7 +28,10 @@ import android.os.RemoteException;
public class AccountAuthenticatorResponse implements Parcelable { public class AccountAuthenticatorResponse implements Parcelable {
private IAccountAuthenticatorResponse mAccountAuthenticatorResponse; private IAccountAuthenticatorResponse mAccountAuthenticatorResponse;
public AccountAuthenticatorResponse(IAccountAuthenticatorResponse response) { /**
* @hide
*/
/* package private */ AccountAuthenticatorResponse(IAccountAuthenticatorResponse response) {
mAccountAuthenticatorResponse = response; mAccountAuthenticatorResponse = response;
} }

View File

@@ -54,9 +54,44 @@ import com.google.android.collect.Maps;
public class AccountManager { public class AccountManager {
private static final String TAG = "AccountManager"; private static final String TAG = "AccountManager";
public static final int ERROR_CODE_REMOTE_EXCEPTION = 1;
public static final int ERROR_CODE_NETWORK_ERROR = 3;
public static final int ERROR_CODE_CANCELED = 4;
public static final int ERROR_CODE_INVALID_RESPONSE = 5;
public static final int ERROR_CODE_UNSUPPORTED_OPERATION = 6;
public static final int ERROR_CODE_BAD_ARGUMENTS = 7;
public static final int ERROR_CODE_BAD_REQUEST = 8;
public static final String KEY_ACCOUNTS = "accounts";
public static final String KEY_AUTHENTICATOR_TYPES = "authenticator_types";
public static final String KEY_USERDATA = "userdata";
public static final String KEY_AUTHTOKEN = "authtoken";
public static final String KEY_PASSWORD = "password";
public static final String KEY_ACCOUNT_NAME = "authAccount";
public static final String KEY_ACCOUNT_TYPE = "accountType";
public static final String KEY_ERROR_CODE = "errorCode";
public static final String KEY_ERROR_MESSAGE = "errorMessage";
public static final String KEY_INTENT = "intent";
public static final String KEY_BOOLEAN_RESULT = "booleanResult";
public static final String KEY_ACCOUNT_AUTHENTICATOR_RESPONSE = "accountAuthenticatorResponse";
public static final String KEY_ACCOUNT_MANAGER_RESPONSE = "accountManagerResponse";
public static final String KEY_AUTH_FAILED_MESSAGE = "authFailedMessage";
public static final String KEY_AUTH_TOKEN_LABEL = "authTokenLabelKey";
public static final String ACTION_AUTHENTICATOR_INTENT =
"android.accounts.AccountAuthenticator";
public static final String AUTHENTICATOR_META_DATA_NAME =
"android.accounts.AccountAuthenticator";
public static final String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
private final Context mContext; private final Context mContext;
private final IAccountManager mService; private final IAccountManager mService;
private final Handler mMainHandler; private final Handler mMainHandler;
/**
* Action sent as a broadcast Intent by the AccountsService
* when accounts are added to and/or removed from the device's
* database.
*/
public static final String LOGIN_ACCOUNTS_CHANGED_ACTION =
"android.accounts.LOGIN_ACCOUNTS_CHANGED";
/** /**
* @hide * @hide
@@ -141,10 +176,10 @@ public class AccountManager {
mService.removeAccount(mResponse, account); mService.removeAccount(mResponse, account);
} }
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException { public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
if (!bundle.containsKey(Constants.BOOLEAN_RESULT_KEY)) { if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
throw new AuthenticatorException("no result in response"); throw new AuthenticatorException("no result in response");
} }
return bundle.getBoolean(Constants.BOOLEAN_RESULT_KEY); return bundle.getBoolean(KEY_BOOLEAN_RESULT);
} }
}.start(); }.start();
} }
@@ -208,7 +243,7 @@ public class AccountManager {
throws OperationCanceledException, IOException, AuthenticatorException { throws OperationCanceledException, IOException, AuthenticatorException {
Bundle bundle = getAuthToken(account, authTokenType, notifyAuthFailure, null /* callback */, Bundle bundle = getAuthToken(account, authTokenType, notifyAuthFailure, null /* callback */,
null /* handler */).getResult(); null /* handler */).getResult();
return bundle.getString(Constants.AUTHTOKEN_KEY); return bundle.getString(KEY_AUTHTOKEN);
} }
/** /**
@@ -262,23 +297,6 @@ public class AccountManager {
}.start(); }.start();
} }
/** @deprecated use {@link #confirmCredentials} instead */
@Deprecated
public AccountManagerFuture<Boolean> confirmPassword(final Account account, final String password,
AccountManagerCallback<Boolean> callback, Handler handler) {
return new Future2Task<Boolean>(handler, callback) {
public void doWork() throws RemoteException {
mService.confirmPassword(mResponse, account, password);
}
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
if (!bundle.containsKey(Constants.BOOLEAN_RESULT_KEY)) {
throw new AuthenticatorException("no result in response");
}
return bundle.getBoolean(Constants.BOOLEAN_RESULT_KEY);
}
}.start();
}
public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures( public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
final String type, final String[] features, final String type, final String[] features,
AccountManagerCallback<Account[]> callback, Handler handler) { AccountManagerCallback<Account[]> callback, Handler handler) {
@@ -288,10 +306,10 @@ public class AccountManager {
mService.getAccountsByFeatures(mResponse, type, features); mService.getAccountsByFeatures(mResponse, type, features);
} }
public Account[] bundleToResult(Bundle bundle) throws AuthenticatorException { public Account[] bundleToResult(Bundle bundle) throws AuthenticatorException {
if (!bundle.containsKey(Constants.ACCOUNTS_KEY)) { if (!bundle.containsKey(KEY_ACCOUNTS)) {
throw new AuthenticatorException("no result in response"); throw new AuthenticatorException("no result in response");
} }
final Parcelable[] parcelables = bundle.getParcelableArray(Constants.ACCOUNTS_KEY); final Parcelable[] parcelables = bundle.getParcelableArray(KEY_ACCOUNTS);
Account[] descs = new Account[parcelables.length]; Account[] descs = new Account[parcelables.length];
for (int i = 0; i < parcelables.length; i++) { for (int i = 0; i < parcelables.length; i++) {
descs[i] = (Account) parcelables[i]; descs[i] = (Account) parcelables[i];
@@ -301,12 +319,14 @@ public class AccountManager {
}.start(); }.start();
} }
public AccountManagerFuture<Bundle> confirmCredentials(final Account account, final Activity activity, public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
final Bundle options,
final Activity activity,
final AccountManagerCallback<Bundle> callback, final AccountManagerCallback<Bundle> callback,
final Handler handler) { final Handler handler) {
return new AmsTask(activity, handler, callback) { return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException { public void doWork() throws RemoteException {
mService.confirmCredentials(mResponse, account, activity != null); mService.confirmCredentials(mResponse, account, options, activity != null);
} }
}.start(); }.start();
} }
@@ -357,7 +377,7 @@ public class AccountManager {
}); });
} }
private void postToHandler(Handler handler, final OnAccountsUpdatedListener listener, private void postToHandler(Handler handler, final OnAccountsUpdateListener listener,
final Account[] accounts) { final Account[] accounts) {
final Account[] accountsCopy = new Account[accounts.length]; final Account[] accountsCopy = new Account[accounts.length];
// send a copy to make sure that one doesn't // send a copy to make sure that one doesn't
@@ -480,7 +500,7 @@ public class AccountManager {
} }
public void onError(int code, String message) { public void onError(int code, String message) {
if (code == Constants.ERROR_CODE_CANCELED) { if (code == ERROR_CODE_CANCELED) {
// the authenticator indicated that this request was canceled, do so now // the authenticator indicated that this request was canceled, do so now
cancel(true /* mayInterruptIfRunning */); cancel(true /* mayInterruptIfRunning */);
return; return;
@@ -536,11 +556,11 @@ public class AccountManager {
} catch (AuthenticatorException e) { } catch (AuthenticatorException e) {
// we will set the exception below // we will set the exception below
} }
onError(Constants.ERROR_CODE_INVALID_RESPONSE, "no result in response"); onError(ERROR_CODE_INVALID_RESPONSE, "no result in response");
} }
public void onError(int code, String message) { public void onError(int code, String message) {
if (code == Constants.ERROR_CODE_CANCELED) { if (code == ERROR_CODE_CANCELED) {
cancel(true /* mayInterruptIfRunning */); cancel(true /* mayInterruptIfRunning */);
return; return;
} }
@@ -621,19 +641,19 @@ public class AccountManager {
} }
private Exception convertErrorToException(int code, String message) { private Exception convertErrorToException(int code, String message) {
if (code == Constants.ERROR_CODE_NETWORK_ERROR) { if (code == ERROR_CODE_NETWORK_ERROR) {
return new IOException(message); return new IOException(message);
} }
if (code == Constants.ERROR_CODE_UNSUPPORTED_OPERATION) { if (code == ERROR_CODE_UNSUPPORTED_OPERATION) {
return new UnsupportedOperationException(message); return new UnsupportedOperationException(message);
} }
if (code == Constants.ERROR_CODE_INVALID_RESPONSE) { if (code == ERROR_CODE_INVALID_RESPONSE) {
return new AuthenticatorException(message); return new AuthenticatorException(message);
} }
if (code == Constants.ERROR_CODE_BAD_ARGUMENTS) { if (code == ERROR_CODE_BAD_ARGUMENTS) {
return new IllegalArgumentException(message); return new IllegalArgumentException(message);
} }
@@ -690,9 +710,9 @@ public class AccountManager {
} else { } else {
// send result since we can't prompt to add an account // send result since we can't prompt to add an account
Bundle result = new Bundle(); Bundle result = new Bundle();
result.putString(Constants.ACCOUNT_NAME_KEY, null); result.putString(KEY_ACCOUNT_NAME, null);
result.putString(Constants.ACCOUNT_TYPE_KEY, null); result.putString(KEY_ACCOUNT_TYPE, null);
result.putString(Constants.AUTHTOKEN_KEY, null); result.putString(KEY_AUTHTOKEN, null);
try { try {
mResponse.onResult(result); mResponse.onResult(result);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -716,8 +736,8 @@ public class AccountManager {
new IAccountManagerResponse.Stub() { new IAccountManagerResponse.Stub() {
public void onResult(Bundle value) throws RemoteException { public void onResult(Bundle value) throws RemoteException {
Account account = new Account( Account account = new Account(
value.getString(Constants.ACCOUNT_NAME_KEY), value.getString(KEY_ACCOUNT_NAME),
value.getString(Constants.ACCOUNT_TYPE_KEY)); value.getString(KEY_ACCOUNT_TYPE));
mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions, mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions,
mActivity, mMyCallback, mHandler); mActivity, mMyCallback, mHandler);
} }
@@ -731,15 +751,15 @@ public class AccountManager {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setClassName("android", intent.setClassName("android",
"android.accounts.ChooseAccountActivity"); "android.accounts.ChooseAccountActivity");
intent.putExtra(Constants.ACCOUNTS_KEY, accounts); intent.putExtra(KEY_ACCOUNTS, accounts);
intent.putExtra(Constants.ACCOUNT_MANAGER_RESPONSE_KEY, intent.putExtra(KEY_ACCOUNT_MANAGER_RESPONSE,
new AccountManagerResponse(chooseResponse)); new AccountManagerResponse(chooseResponse));
mActivity.startActivity(intent); mActivity.startActivity(intent);
// the result will arrive via the IAccountManagerResponse // the result will arrive via the IAccountManagerResponse
} else { } else {
// send result since we can't prompt to select an account // send result since we can't prompt to select an account
Bundle result = new Bundle(); Bundle result = new Bundle();
result.putString(Constants.ACCOUNTS_KEY, null); result.putString(KEY_ACCOUNTS, null);
try { try {
mResponse.onResult(result); mResponse.onResult(result);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -751,38 +771,34 @@ public class AccountManager {
}}, mHandler); }}, mHandler);
} }
// TODO(fredq) pass through the calls to our implemention of Future2 to the underlying
// future that we create. We need to do things like have cancel cancel the mFuture, if set
// or to cause this to be canceled if mFuture isn't set.
// Once this is done then getAuthTokenByFeatures can be changed to return a Future2.
public void run(AccountManagerFuture<Bundle> future) { public void run(AccountManagerFuture<Bundle> future) {
try { try {
set(future.get()); set(future.getResult());
} catch (InterruptedException e) { } catch (OperationCanceledException e) {
cancel(true); cancel(true /* mayInterruptIfRUnning */);
} catch (CancellationException e) { } catch (IOException e) {
cancel(true); setException(e);
} catch (ExecutionException e) { } catch (AuthenticatorException e) {
setException(e.getCause()); setException(e);
} }
} }
} }
public void getAuthTokenByFeatures( public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
final String accountType, final String authTokenType, final String[] features, final String accountType, final String authTokenType, final String[] features,
final Activity activityForPrompting, final Bundle addAccountOptions, final Activity activityForPrompting, final Bundle addAccountOptions,
final Bundle loginOptions, final Bundle loginOptions,
final AccountManagerCallback<Bundle> callback, final Handler handler) { final AccountManagerCallback<Bundle> callback, final Handler handler) {
if (accountType == null) throw new IllegalArgumentException("account type is null"); if (accountType == null) throw new IllegalArgumentException("account type is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
new GetAuthTokenByTypeAndFeaturesTask(accountType, authTokenType, features, final GetAuthTokenByTypeAndFeaturesTask task =
activityForPrompting, addAccountOptions, loginOptions, callback, handler).start(); new GetAuthTokenByTypeAndFeaturesTask(accountType, authTokenType, features,
activityForPrompting, addAccountOptions, loginOptions, callback, handler);
task.start();
return task;
} }
private final HashMap<OnAccountsUpdatedListener, Handler> mAccountsUpdatedListeners = private final HashMap<OnAccountsUpdateListener, Handler> mAccountsUpdatedListeners =
Maps.newHashMap(); Maps.newHashMap();
/** /**
@@ -795,7 +811,7 @@ public class AccountManager {
final Account[] accounts = getAccounts(); final Account[] accounts = getAccounts();
// send the result to the listeners // send the result to the listeners
synchronized (mAccountsUpdatedListeners) { synchronized (mAccountsUpdatedListeners) {
for (Map.Entry<OnAccountsUpdatedListener, Handler> entry : for (Map.Entry<OnAccountsUpdateListener, Handler> entry :
mAccountsUpdatedListeners.entrySet()) { mAccountsUpdatedListeners.entrySet()) {
postToHandler(entry.getValue(), entry.getKey(), accounts); postToHandler(entry.getValue(), entry.getKey(), accounts);
} }
@@ -804,7 +820,7 @@ public class AccountManager {
}; };
/** /**
* Add a {@link OnAccountsUpdatedListener} to this instance of the {@link AccountManager}. * Add a {@link OnAccountsUpdateListener} to this instance of the {@link AccountManager}.
* The listener is guaranteed to be invoked on the thread of the Handler that is passed * The listener is guaranteed to be invoked on the thread of the Handler that is passed
* in or the main thread's Handler if handler is null. * in or the main thread's Handler if handler is null.
* <p> * <p>
@@ -819,7 +835,7 @@ public class AccountManager {
* @throws IllegalArgumentException if listener is null * @throws IllegalArgumentException if listener is null
* @throws IllegalStateException if listener was already added * @throws IllegalStateException if listener was already added
*/ */
public void addOnAccountsUpdatedListener(final OnAccountsUpdatedListener listener, public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
Handler handler, boolean updateImmediately) { Handler handler, boolean updateImmediately) {
if (listener == null) { if (listener == null) {
throw new IllegalArgumentException("the listener is null"); throw new IllegalArgumentException("the listener is null");
@@ -835,7 +851,7 @@ public class AccountManager {
if (wasEmpty) { if (wasEmpty) {
// Register a broadcast receiver to monitor account changes // Register a broadcast receiver to monitor account changes
IntentFilter intentFilter = new IntentFilter(); IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Constants.LOGIN_ACCOUNTS_CHANGED_ACTION); intentFilter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION);
// To recover from disk-full. // To recover from disk-full.
intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
mContext.registerReceiver(mAccountsChangedBroadcastReceiver, intentFilter); mContext.registerReceiver(mAccountsChangedBroadcastReceiver, intentFilter);
@@ -848,13 +864,13 @@ public class AccountManager {
} }
/** /**
* Remove an {@link OnAccountsUpdatedListener} that was previously registered with * Remove an {@link OnAccountsUpdateListener} that was previously registered with
* {@link #addOnAccountsUpdatedListener}. * {@link #addOnAccountsUpdatedListener}.
* @param listener the listener to remove * @param listener the listener to remove
* @throws IllegalArgumentException if listener is null * @throws IllegalArgumentException if listener is null
* @throws IllegalStateException if listener was not already added * @throws IllegalStateException if listener was not already added
*/ */
public void removeOnAccountsUpdatedListener(OnAccountsUpdatedListener listener) { public void removeOnAccountsUpdatedListener(OnAccountsUpdateListener listener) {
if (listener == null) { if (listener == null) {
throw new IllegalArgumentException("the listener is null"); throw new IllegalArgumentException("the listener is null");
} }

View File

@@ -22,12 +22,63 @@ import java.util.concurrent.TimeoutException;
import java.io.IOException; import java.io.IOException;
/** /**
* An extension of {@link java.util.concurrent.Future} that provides wrappers for {@link #get()} * A <tt>AccountManagerFuture</tt> represents the result of an asynchronous
* that handle the various * {@link AccountManager} call. Methods are provided to check if the computation is
* exceptions that {@link #get()} may return and rethrows them as exceptions specific to * complete, to wait for its completion, and to retrieve the result of
* {@link android.accounts.AccountManager}. * the computation. The result can only be retrieved using method
* <tt>get</tt> when the computation has completed, blocking if
* necessary until it is ready. Cancellation is performed by the
* <tt>cancel</tt> method. Additional methods are provided to
* determine if the task completed normally or was cancelled. Once a
* computation has completed, the computation cannot be cancelled.
* If you would like to use a <tt>Future</tt> for the sake
* of cancellability but not provide a usable result, you can
* declare types of the form <tt>Future&lt;?&gt;</tt> and
* return <tt>null</tt> as a result of the underlying task.
*/ */
public interface AccountManagerFuture<V> extends Future<V> { public interface AccountManagerFuture<V> {
/**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when <tt>cancel</tt> is called,
* this task should never run. If the task has already started,
* then the <tt>mayInterruptIfRunning</tt> parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return <tt>true</tt>. Subsequent calls to {@link #isCancelled}
* will always return <tt>true</tt> if this method returned <tt>true</tt>.
*
* @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* @return <tt>false</tt> if the task could not be cancelled,
* typically because it has already completed normally;
* <tt>true</tt> otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* Returns <tt>true</tt> if this task was cancelled before it completed
* normally.
*
* @return <tt>true</tt> if this task was cancelled before it completed
*/
boolean isCancelled();
/**
* Returns <tt>true</tt> if this task completed.
*
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
* <tt>true</tt>.
*
* @return <tt>true</tt> if this task completed
*/
boolean isDone();
/** /**
* Wrapper for {@link java.util.concurrent.Future#get()}. If the get() throws * Wrapper for {@link java.util.concurrent.Future#get()}. If the get() throws
* {@link InterruptedException} then the * {@link InterruptedException} then the
@@ -55,13 +106,4 @@ public interface AccountManagerFuture<V> extends Future<V> {
*/ */
V getResult(long timeout, TimeUnit unit) V getResult(long timeout, TimeUnit unit)
throws OperationCanceledException, IOException, AuthenticatorException; throws OperationCanceledException, IOException, AuthenticatorException;
/** @deprecated Use {@link #getResult} */
@Deprecated
V get() throws InterruptedException, ExecutionException;
/** @deprecated Use {@link #getResult} */
@Deprecated
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
} }

View File

@@ -156,7 +156,7 @@ public class AccountManagerService
&& SystemProperties.getBoolean("ro.debuggable", false); && SystemProperties.getBoolean("ro.debuggable", false);
static { static {
ACCOUNTS_CHANGED_INTENT = new Intent(Constants.LOGIN_ACCOUNTS_CHANGED_ACTION); ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
} }
@@ -440,16 +440,16 @@ public class AccountManagerService
} }
public void onResult(Bundle result) { public void onResult(Bundle result) {
if (result != null && result.containsKey(Constants.BOOLEAN_RESULT_KEY) if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT)
&& !result.containsKey(Constants.INTENT_KEY)) { && !result.containsKey(AccountManager.KEY_INTENT)) {
final boolean removalAllowed = result.getBoolean(Constants.BOOLEAN_RESULT_KEY); final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
if (removalAllowed) { if (removalAllowed) {
removeAccount(mAccount); removeAccount(mAccount);
} }
IAccountManagerResponse response = getResponseAndClose(); IAccountManagerResponse response = getResponseAndClose();
if (response != null) { if (response != null) {
Bundle result2 = new Bundle(); Bundle result2 = new Bundle();
result2.putBoolean(Constants.BOOLEAN_RESULT_KEY, removalAllowed); result2.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, removalAllowed);
try { try {
response.onResult(result2); response.onResult(result2);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -691,9 +691,9 @@ public class AccountManagerService
String authToken = readAuthTokenFromDatabase(account, authTokenType); String authToken = readAuthTokenFromDatabase(account, authTokenType);
if (authToken != null) { if (authToken != null) {
Bundle result = new Bundle(); Bundle result = new Bundle();
result.putString(Constants.AUTHTOKEN_KEY, authToken); result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
result.putString(Constants.ACCOUNT_NAME_KEY, account.name); result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(Constants.ACCOUNT_TYPE_KEY, account.type); result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
onResult(response, result); onResult(response, result);
return; return;
} }
@@ -721,22 +721,22 @@ public class AccountManagerService
public void onResult(Bundle result) { public void onResult(Bundle result) {
if (result != null) { if (result != null) {
if (result.containsKey(Constants.AUTH_TOKEN_LABEL_KEY)) { if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
Intent intent = newGrantCredentialsPermissionIntent(account, callerUid, Intent intent = newGrantCredentialsPermissionIntent(account, callerUid,
new AccountAuthenticatorResponse(this), new AccountAuthenticatorResponse(this),
authTokenType, authTokenType,
result.getString(Constants.AUTH_TOKEN_LABEL_KEY)); result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL));
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable(Constants.INTENT_KEY, intent); bundle.putParcelable(AccountManager.KEY_INTENT, intent);
onResult(bundle); onResult(bundle);
return; return;
} }
String authToken = result.getString(Constants.AUTHTOKEN_KEY); String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
if (authToken != null) { if (authToken != null) {
String name = result.getString(Constants.ACCOUNT_NAME_KEY); String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
String type = result.getString(Constants.ACCOUNT_TYPE_KEY); String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) { if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) {
onError(Constants.ERROR_CODE_INVALID_RESPONSE, onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"the type and name should not be empty"); "the type and name should not be empty");
return; return;
} }
@@ -744,10 +744,10 @@ public class AccountManagerService
authTokenType, authToken); authTokenType, authToken);
} }
Intent intent = result.getParcelable(Constants.INTENT_KEY); Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
if (intent != null && notifyOnAuthFailure) { if (intent != null && notifyOnAuthFailure) {
doNotification( doNotification(
account, result.getString(Constants.AUTH_FAILED_MESSAGE_KEY), account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
intent); intent);
} }
} }
@@ -871,13 +871,13 @@ public class AccountManagerService
} }
public void confirmCredentials(IAccountManagerResponse response, public void confirmCredentials(IAccountManagerResponse response,
final Account account, final boolean expectActivityLaunch) { final Account account, final Bundle options, final boolean expectActivityLaunch) {
checkManageAccountsPermission(); checkManageAccountsPermission();
long identityToken = clearCallingIdentity(); long identityToken = clearCallingIdentity();
try { try {
new Session(response, account.type, expectActivityLaunch) { new Session(response, account.type, expectActivityLaunch) {
public void run() throws RemoteException { public void run() throws RemoteException {
mAuthenticator.confirmCredentials(this, account); mAuthenticator.confirmCredentials(this, account, options);
} }
protected String toDebugString(long now) { protected String toDebugString(long now) {
return super.toDebugString(now) + ", confirmCredentials" return super.toDebugString(now) + ", confirmCredentials"
@@ -889,25 +889,6 @@ public class AccountManagerService
} }
} }
public void confirmPassword(IAccountManagerResponse response, final Account account,
final String password) {
checkManageAccountsPermission();
long identityToken = clearCallingIdentity();
try {
new Session(response, account.type, false /* expectActivityLaunch */) {
public void run() throws RemoteException {
mAuthenticator.confirmPassword(this, account, password);
}
protected String toDebugString(long now) {
return super.toDebugString(now) + ", confirmPassword"
+ ", " + account;
}
}.bind();
} finally {
restoreCallingIdentity(identityToken);
}
}
public void updateCredentials(IAccountManagerResponse response, final Account account, public void updateCredentials(IAccountManagerResponse response, final Account account,
final String authTokenType, final boolean expectActivityLaunch, final String authTokenType, final boolean expectActivityLaunch,
final Bundle loginOptions) { final Bundle loginOptions) {
@@ -980,17 +961,17 @@ public class AccountManagerService
try { try {
mAuthenticator.hasFeatures(this, mAccountsOfType[mCurrentAccount], mFeatures); mAuthenticator.hasFeatures(this, mAccountsOfType[mCurrentAccount], mFeatures);
} catch (RemoteException e) { } catch (RemoteException e) {
onError(Constants.ERROR_CODE_REMOTE_EXCEPTION, "remote exception"); onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception");
} }
} }
public void onResult(Bundle result) { public void onResult(Bundle result) {
mNumResults++; mNumResults++;
if (result == null) { if (result == null) {
onError(Constants.ERROR_CODE_INVALID_RESPONSE, "null bundle"); onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
return; return;
} }
if (result.getBoolean(Constants.BOOLEAN_RESULT_KEY, false)) { if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
mAccountsWithFeatures.add(mAccountsOfType[mCurrentAccount]); mAccountsWithFeatures.add(mAccountsOfType[mCurrentAccount]);
} }
mCurrentAccount++; mCurrentAccount++;
@@ -1006,7 +987,7 @@ public class AccountManagerService
accounts[i] = mAccountsWithFeatures.get(i); accounts[i] = mAccountsWithFeatures.get(i);
} }
Bundle result = new Bundle(); Bundle result = new Bundle();
result.putParcelableArray(Constants.ACCOUNTS_KEY, accounts); result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
response.onResult(result); response.onResult(result);
} catch (RemoteException e) { } catch (RemoteException e) {
// if the caller is dead then there is no one to care about remote exceptions // if the caller is dead then there is no one to care about remote exceptions
@@ -1040,7 +1021,7 @@ public class AccountManagerService
if (features != null && type == null) { if (features != null && type == null) {
if (response != null) { if (response != null) {
try { try {
response.onError(Constants.ERROR_CODE_BAD_ARGUMENTS, "type is null"); response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "type is null");
} catch (RemoteException e) { } catch (RemoteException e) {
// ignore this // ignore this
} }
@@ -1171,7 +1152,7 @@ public class AccountManagerService
} }
if (!mBindHelper.bind(mAccountType, this)) { if (!mBindHelper.bind(mAccountType, this)) {
Log.d(TAG, "bind attempt failed for " + toDebugString()); Log.d(TAG, "bind attempt failed for " + toDebugString());
onError(Constants.ERROR_CODE_REMOTE_EXCEPTION, "bind failure"); onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure");
} }
} }
@@ -1196,7 +1177,7 @@ public class AccountManagerService
try { try {
run(); run();
} catch (RemoteException e) { } catch (RemoteException e) {
onError(Constants.ERROR_CODE_REMOTE_EXCEPTION, onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
"remote exception"); "remote exception");
} }
} }
@@ -1207,7 +1188,7 @@ public class AccountManagerService
mAuthenticator = null; mAuthenticator = null;
IAccountManagerResponse response = getResponseAndClose(); IAccountManagerResponse response = getResponseAndClose();
if (response != null) { if (response != null) {
onError(Constants.ERROR_CODE_REMOTE_EXCEPTION, onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
"disconnected"); "disconnected");
} }
} }
@@ -1215,16 +1196,16 @@ public class AccountManagerService
public void onTimedOut() { public void onTimedOut() {
IAccountManagerResponse response = getResponseAndClose(); IAccountManagerResponse response = getResponseAndClose();
if (response != null) { if (response != null) {
onError(Constants.ERROR_CODE_REMOTE_EXCEPTION, onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
"timeout"); "timeout");
} }
} }
public void onResult(Bundle result) { public void onResult(Bundle result) {
mNumResults++; mNumResults++;
if (result != null && !TextUtils.isEmpty(result.getString(Constants.AUTHTOKEN_KEY))) { if (result != null && !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) {
String accountName = result.getString(Constants.ACCOUNT_NAME_KEY); String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
String accountType = result.getString(Constants.ACCOUNT_TYPE_KEY); String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
Account account = new Account(accountName, accountType); Account account = new Account(accountName, accountType);
cancelNotification(getSigninRequiredNotificationId(account)); cancelNotification(getSigninRequiredNotificationId(account));
@@ -1232,7 +1213,7 @@ public class AccountManagerService
} }
IAccountManagerResponse response; IAccountManagerResponse response;
if (mExpectActivityLaunch && result != null if (mExpectActivityLaunch && result != null
&& result.containsKey(Constants.INTENT_KEY)) { && result.containsKey(AccountManager.KEY_INTENT)) {
response = mResponse; response = mResponse;
} else { } else {
response = getResponseAndClose(); response = getResponseAndClose();
@@ -1240,7 +1221,7 @@ public class AccountManagerService
if (response != null) { if (response != null) {
try { try {
if (result == null) { if (result == null) {
response.onError(Constants.ERROR_CODE_INVALID_RESPONSE, response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"null bundle returned"); "null bundle returned");
} else { } else {
response.onResult(result); response.onResult(result);

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.accounts;
public class AccountsException extends Exception {
public AccountsException() {
super();
}
public AccountsException(String message) {
super(message);
}
public AccountsException(String message, Throwable cause) {
super(message, cause);
}
public AccountsException(Throwable cause) {
super(cause);
}
}

View File

@@ -16,7 +16,7 @@
package android.accounts; package android.accounts;
public class AuthenticatorException extends Exception { public class AuthenticatorException extends AccountsException {
public AuthenticatorException() { public AuthenticatorException() {
super(); super();
} }

View File

@@ -23,6 +23,9 @@ import android.widget.ListView;
import android.view.View; import android.view.View;
import android.util.Log; import android.util.Log;
/**
* @hide
*/
public class ChooseAccountActivity extends ListActivity { public class ChooseAccountActivity extends ListActivity {
private static final String TAG = "AccountManager"; private static final String TAG = "AccountManager";
private Parcelable[] mAccounts = null; private Parcelable[] mAccounts = null;
@@ -34,13 +37,13 @@ public class ChooseAccountActivity extends ListActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (savedInstanceState == null) { if (savedInstanceState == null) {
mAccounts = getIntent().getParcelableArrayExtra(Constants.ACCOUNTS_KEY); mAccounts = getIntent().getParcelableArrayExtra(AccountManager.KEY_ACCOUNTS);
mAccountManagerResponse = mAccountManagerResponse =
getIntent().getParcelableExtra(Constants.ACCOUNT_MANAGER_RESPONSE_KEY); getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE);
} else { } else {
mAccounts = savedInstanceState.getParcelableArray(Constants.ACCOUNTS_KEY); mAccounts = savedInstanceState.getParcelableArray(AccountManager.KEY_ACCOUNTS);
mAccountManagerResponse = mAccountManagerResponse =
savedInstanceState.getParcelable(Constants.ACCOUNT_MANAGER_RESPONSE_KEY); savedInstanceState.getParcelable(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE);
} }
String[] mAccountNames = new String[mAccounts.length]; String[] mAccountNames = new String[mAccounts.length];
@@ -59,8 +62,8 @@ public class ChooseAccountActivity extends ListActivity {
Account account = (Account) mAccounts[position]; Account account = (Account) mAccounts[position];
Log.d(TAG, "selected account " + account); Log.d(TAG, "selected account " + account);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(Constants.ACCOUNT_NAME_KEY, account.name); bundle.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
bundle.putString(Constants.ACCOUNT_TYPE_KEY, account.type); bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
mResult = bundle; mResult = bundle;
finish(); finish();
} }
@@ -70,7 +73,7 @@ public class ChooseAccountActivity extends ListActivity {
if (mResult != null) { if (mResult != null) {
mAccountManagerResponse.onResult(mResult); mAccountManagerResponse.onResult(mResult);
} else { } else {
mAccountManagerResponse.onError(Constants.ERROR_CODE_CANCELED, "canceled"); mAccountManagerResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
} }
} }
super.finish(); super.finish();

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.accounts;
public class Constants {
// this should never be instantiated
private Constants() {}
public static final int ERROR_CODE_REMOTE_EXCEPTION = 1;
public static final int ERROR_CODE_NETWORK_ERROR = 3;
public static final int ERROR_CODE_CANCELED = 4;
public static final int ERROR_CODE_INVALID_RESPONSE = 5;
public static final int ERROR_CODE_UNSUPPORTED_OPERATION = 6;
public static final int ERROR_CODE_BAD_ARGUMENTS = 7;
public static final int ERROR_CODE_BAD_REQUEST = 8;
public static final String ACCOUNTS_KEY = "accounts";
public static final String AUTHENTICATOR_TYPES_KEY = "authenticator_types";
public static final String USERDATA_KEY = "userdata";
public static final String AUTHTOKEN_KEY = "authtoken";
public static final String PASSWORD_KEY = "password";
public static final String ACCOUNT_NAME_KEY = "authAccount";
public static final String ACCOUNT_TYPE_KEY = "accountType";
public static final String ERROR_CODE_KEY = "errorCode";
public static final String ERROR_MESSAGE_KEY = "errorMessage";
public static final String INTENT_KEY = "intent";
public static final String BOOLEAN_RESULT_KEY = "booleanResult";
public static final String ACCOUNT_AUTHENTICATOR_RESPONSE_KEY = "accountAuthenticatorResponse";
public static final String ACCOUNT_MANAGER_RESPONSE_KEY = "accountManagerResponse";
public static final String AUTH_FAILED_MESSAGE_KEY = "authFailedMessage";
public static final String AUTH_TOKEN_LABEL_KEY = "authTokenLabelKey";
public static final String AUTHENTICATOR_INTENT_ACTION =
"android.accounts.AccountAuthenticator";
public static final String AUTHENTICATOR_META_DATA_NAME =
"android.accounts.AccountAuthenticator";
public static final String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
/**
* Action sent as a broadcast Intent by the AccountsService
* when accounts are added to and/or removed from the device's
* database.
*/
public static final String LOGIN_ACCOUNTS_CHANGED_ACTION =
"android.accounts.LOGIN_ACCOUNTS_CHANGED";
}

View File

@@ -121,7 +121,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
if (mResultBundle != null) { if (mResultBundle != null) {
accountAuthenticatorResponse.onResult(mResultBundle); accountAuthenticatorResponse.onResult(mResultBundle);
} else { } else {
accountAuthenticatorResponse.onError(Constants.ERROR_CODE_CANCELED, "canceled"); accountAuthenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
} }
} }
super.finish(); super.finish();

View File

@@ -22,6 +22,7 @@ import android.os.Bundle;
/** /**
* Service that allows the interaction with an authentication server. * Service that allows the interaction with an authentication server.
* @hide
*/ */
oneway interface IAccountAuthenticator { oneway interface IAccountAuthenticator {
/** /**
@@ -30,17 +31,11 @@ oneway interface IAccountAuthenticator {
void addAccount(in IAccountAuthenticatorResponse response, String accountType, void addAccount(in IAccountAuthenticatorResponse response, String accountType,
String authTokenType, in String[] requiredFeatures, in Bundle options); String authTokenType, in String[] requiredFeatures, in Bundle options);
/**
* Checks that the account/password combination is valid.
* note -- deprecated
*/
void confirmPassword(in IAccountAuthenticatorResponse response,
in Account account, String password);
/** /**
* prompts the user for the credentials of the account * prompts the user for the credentials of the account
*/ */
void confirmCredentials(in IAccountAuthenticatorResponse response, in Account account); void confirmCredentials(in IAccountAuthenticatorResponse response, in Account account,
in Bundle options);
/** /**
* gets the password by either prompting the user or querying the IAccountManager * gets the password by either prompting the user or querying the IAccountManager

View File

@@ -19,6 +19,7 @@ import android.os.Bundle;
/** /**
* The interface used to return responses from an {@link IAccountAuthenticator} * The interface used to return responses from an {@link IAccountAuthenticator}
* @hide
*/ */
oneway interface IAccountAuthenticatorResponse { oneway interface IAccountAuthenticatorResponse {
void onResult(in Bundle value); void onResult(in Bundle value);

View File

@@ -52,11 +52,5 @@ interface IAccountManager {
void editProperties(in IAccountManagerResponse response, String accountType, void editProperties(in IAccountManagerResponse response, String accountType,
boolean expectActivityLaunch); boolean expectActivityLaunch);
void confirmCredentials(in IAccountManagerResponse response, in Account account, void confirmCredentials(in IAccountManagerResponse response, in Account account,
boolean expectActivityLaunch); in Bundle options, boolean expectActivityLaunch);
/*
* @deprecated
*/
void confirmPassword(in IAccountManagerResponse response, in Account account,
String password);
} }

View File

@@ -15,7 +15,7 @@
*/ */
package android.accounts; package android.accounts;
public class NetworkErrorException extends Exception { public class NetworkErrorException extends AccountsException {
public NetworkErrorException() { public NetworkErrorException() {
super(); super();
} }

View File

@@ -19,7 +19,7 @@ package android.accounts;
/** /**
* An interface that contains the callback used by the AccountMonitor * An interface that contains the callback used by the AccountMonitor
*/ */
public interface OnAccountsUpdatedListener { public interface OnAccountsUpdateListener {
/** /**
* This invoked when the AccountMonitor starts up and whenever the account * This invoked when the AccountMonitor starts up and whenever the account
* set changes. * set changes.

View File

@@ -15,7 +15,7 @@
*/ */
package android.accounts; package android.accounts;
public class OperationCanceledException extends Exception { public class OperationCanceledException extends AccountsException {
public OperationCanceledException() { public OperationCanceledException() {
super(); super();
} }

View File

@@ -4,7 +4,7 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.accounts.OnAccountsUpdatedListener; import android.accounts.OnAccountsUpdateListener;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.provider.SyncConstValue; import android.provider.SyncConstValue;
@@ -160,7 +160,7 @@ public abstract class AbstractSyncableContentProvider extends SyncableContentPro
mDatabaseName); mDatabaseName);
mSyncState = new SyncStateContentProviderHelper(mOpenHelper); mSyncState = new SyncStateContentProviderHelper(mOpenHelper);
AccountManager.get(getContext()).addOnAccountsUpdatedListener( AccountManager.get(getContext()).addOnAccountsUpdatedListener(
new OnAccountsUpdatedListener() { new OnAccountsUpdateListener() {
public void onAccountsUpdated(Account[] accounts) { public void onAccountsUpdated(Account[] accounts) {
// Some providers override onAccountsChanged(); give them a database to // Some providers override onAccountsChanged(); give them a database to
// work with. // work with.

View File

@@ -23,7 +23,7 @@ import com.android.internal.util.ArrayUtils;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdatedListener; import android.accounts.OnAccountsUpdateListener;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
@@ -78,7 +78,7 @@ import java.util.concurrent.CountDownLatch;
/** /**
* @hide * @hide
*/ */
class SyncManager implements OnAccountsUpdatedListener { class SyncManager implements OnAccountsUpdateListener {
private static final String TAG = "SyncManager"; private static final String TAG = "SyncManager";
// used during dumping of the Sync history // used during dumping of the Sync history

View File

@@ -331,7 +331,7 @@
<!-- Allows applications to call into AccountAuthenticators. Only <!-- Allows applications to call into AccountAuthenticators. Only
the system can get this permission. --> the system can get this permission. -->
<permission android:name="android.permission.ACCOUNT_MANAGER_SERVICE" <permission android:name="android.permission.ACCOUNT_MANAGER"
android:permissionGroup="android.permission-group.ACCOUNTS" android:permissionGroup="android.permission-group.ACCOUNTS"
android:protectionLevel="signature" android:protectionLevel="signature"
android:description="@string/permdesc_accountManagerService" android:description="@string/permdesc_accountManagerService"

View File

@@ -3,7 +3,7 @@ package android.test;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdatedListener; import android.accounts.OnAccountsUpdateListener;
import android.accounts.Account; import android.accounts.Account;
import android.content.ContextWrapper; import android.content.ContextWrapper;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -15,7 +15,6 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.Looper;
import java.util.List; import java.util.List;
import java.io.File; import java.io.File;
@@ -98,7 +97,7 @@ public class IsolatedContext extends ContextWrapper {
super(IsolatedContext.this, null /* IAccountManager */, null /* handler */); super(IsolatedContext.this, null /* IAccountManager */, null /* handler */);
} }
public void addOnAccountsUpdatedListener(OnAccountsUpdatedListener listener, public void addOnAccountsUpdatedListener(OnAccountsUpdateListener listener,
Handler handler, boolean updateImmediately) { Handler handler, boolean updateImmediately) {
// do nothing // do nothing
} }