- add verbose logging to the authenticator

- fix a bug in AccountManager.getAuthTokenByFeatures() where getAuthToken()
  isn't called after adding the account when necessary
This commit is contained in:
Fred Quintana
2010-03-08 12:48:05 -08:00
parent a9fb0a2497
commit f0fd8436b3
3 changed files with 129 additions and 4 deletions

View File

@@ -24,6 +24,10 @@ import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Intent;
import android.Manifest;
import android.text.TextUtils;
import android.util.Log;
import java.util.Arrays;
/**
* Abstract base class for creating AccountAuthenticators.
@@ -103,6 +107,8 @@ import android.Manifest;
* writing activities to handle these requests.
*/
public abstract class AbstractAccountAuthenticator {
private static final String TAG = "AccountAuthenticator";
private final Context mContext;
public AbstractAccountAuthenticator(Context context) {
@@ -111,19 +117,34 @@ public abstract class AbstractAccountAuthenticator {
private class Transport extends IAccountAuthenticator.Stub {
public void addAccount(IAccountAuthenticatorResponse response, String accountType,
String authTokenType, String[] requiredFeatures, Bundle options)
String authTokenType, String[] features, Bundle options)
throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "addAccount: accountType " + accountType
+ ", authTokenType " + authTokenType
+ ", features " + (features == null ? "[]" : Arrays.toString(features)));
}
checkBinderPermission();
try {
final Bundle result = AbstractAccountAuthenticator.this.addAccount(
new AccountAuthenticatorResponse(response),
accountType, authTokenType, requiredFeatures, options);
accountType, authTokenType, features, options);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
result.keySet(); // force it to be unparcelled
Log.v(TAG, "addAccount: result " + AccountManager.sanitizeResult(result));
}
if (result != null) {
response.onResult(result);
}
} catch (NetworkErrorException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "addAccount", e);
}
response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
} catch (UnsupportedOperationException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "addAccount", e);
}
response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"addAccount not supported");
}
@@ -131,16 +152,30 @@ public abstract class AbstractAccountAuthenticator {
public void confirmCredentials(IAccountAuthenticatorResponse response,
Account account, Bundle options) throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "confirmCredentials: " + account);
}
checkBinderPermission();
try {
final Bundle result = AbstractAccountAuthenticator.this.confirmCredentials(
new AccountAuthenticatorResponse(response), account, options);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
result.keySet(); // force it to be unparcelled
Log.v(TAG, "confirmCredentials: result "
+ AccountManager.sanitizeResult(result));
}
if (result != null) {
response.onResult(result);
}
} catch (NetworkErrorException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "confirmCredentials", e);
}
response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
} catch (UnsupportedOperationException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "confirmCredentials", e);
}
response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"confirmCredentials not supported");
}
@@ -149,16 +184,32 @@ public abstract class AbstractAccountAuthenticator {
public void getAuthTokenLabel(IAccountAuthenticatorResponse response,
String authTokenType)
throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthTokenLabel: authTokenType " + authTokenType);
}
checkBinderPermission();
try {
Bundle result = new Bundle();
result.putString(AccountManager.KEY_AUTH_TOKEN_LABEL,
AbstractAccountAuthenticator.this.getAuthTokenLabel(authTokenType));
response.onResult(result);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
result.keySet(); // force it to be unparcelled
Log.v(TAG, "getAuthTokenLabel: result "
+ AccountManager.sanitizeResult(result));
}
if (result != null) {
response.onResult(result);
}
} catch (IllegalArgumentException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthTokenLabel", e);
}
response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
"unknown authTokenType");
} catch (UnsupportedOperationException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthTokenLabel", e);
}
response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"getAuthTokenTypeLabel not supported");
}
@@ -167,35 +218,64 @@ public abstract class AbstractAccountAuthenticator {
public void getAuthToken(IAccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle loginOptions)
throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken: " + account
+ ", authTokenType " + authTokenType);
}
checkBinderPermission();
try {
final Bundle result = AbstractAccountAuthenticator.this.getAuthToken(
new AccountAuthenticatorResponse(response), account,
authTokenType, loginOptions);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
result.keySet(); // force it to be unparcelled
Log.v(TAG, "getAuthToken: result " + AccountManager.sanitizeResult(result));
}
if (result != null) {
response.onResult(result);
}
} catch (UnsupportedOperationException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken", e);
}
response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"getAuthToken not supported");
} catch (NetworkErrorException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken", e);
}
response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
}
}
public void updateCredentials(IAccountAuthenticatorResponse response, Account account,
String authTokenType, Bundle loginOptions) throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "updateCredentials: " + account
+ ", authTokenType " + authTokenType);
}
checkBinderPermission();
try {
final Bundle result = AbstractAccountAuthenticator.this.updateCredentials(
new AccountAuthenticatorResponse(response), account,
authTokenType, loginOptions);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
result.keySet(); // force it to be unparcelled
Log.v(TAG, "updateCredentials: result "
+ AccountManager.sanitizeResult(result));
}
if (result != null) {
response.onResult(result);
}
} catch (NetworkErrorException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "updateCredentials", e);
}
response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
} catch (UnsupportedOperationException e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "updateCredentials", e);
}
response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
"updateCredentials not supported");
}

View File

@@ -20,11 +20,14 @@ import android.os.Bundle;
import android.os.Parcelable;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
/**
* Object used to communicate responses back to the AccountManager
*/
public class AccountAuthenticatorResponse implements Parcelable {
private static final String TAG = "AccountAuthenticator";
private IAccountAuthenticatorResponse mAccountAuthenticatorResponse;
/**
@@ -40,6 +43,11 @@ public class AccountAuthenticatorResponse implements Parcelable {
}
public void onResult(Bundle result) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
result.keySet(); // force it to be unparcelled
Log.v(TAG, "AccountAuthenticatorResponse.onResult: "
+ AccountManager.sanitizeResult(result));
}
try {
mAccountAuthenticatorResponse.onResult(result);
} catch (RemoteException e) {
@@ -48,6 +56,9 @@ public class AccountAuthenticatorResponse implements Parcelable {
}
public void onRequestContinued() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "AccountAuthenticatorResponse.onRequestContinued");
}
try {
mAccountAuthenticatorResponse.onRequestContinued();
} catch (RemoteException e) {
@@ -56,6 +67,9 @@ public class AccountAuthenticatorResponse implements Parcelable {
}
public void onError(int errorCode, String errorMessage) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "AccountAuthenticatorResponse.onError: " + errorCode + ", " + errorMessage);
}
try {
mAccountAuthenticatorResponse.onError(errorCode, errorMessage);
} catch (RemoteException e) {

View File

@@ -29,6 +29,7 @@ import android.os.RemoteException;
import android.os.Parcelable;
import android.os.Build;
import android.util.Log;
import android.text.TextUtils;
import java.io.IOException;
import java.util.concurrent.Callable;
@@ -222,6 +223,19 @@ public class AccountManager {
mMainHandler = handler;
}
/**
* @hide for internal use only
*/
public static Bundle sanitizeResult(Bundle result) {
if (result.containsKey(KEY_AUTHTOKEN)
&& !TextUtils.isEmpty(result.getString(KEY_AUTHTOKEN))) {
final Bundle newResult = new Bundle(result);
newResult.putString(KEY_AUTHTOKEN, "<omitted for logging purposes>");
return newResult;
}
return result;
}
/**
* Gets an AccountManager instance associated with a Context.
* The {@link Context} will be used as long as the AccountManager is
@@ -1447,6 +1461,7 @@ public class AccountManager {
final Bundle mAddAccountOptions;
final Bundle mLoginOptions;
final AccountManagerCallback<Bundle> mMyCallback;
private volatile int mNumAccounts = 0;
public void doWork() throws RemoteException {
getAccountsByTypeAndFeatures(mAccountType, mFeatures,
@@ -1466,6 +1481,8 @@ public class AccountManager {
return;
}
mNumAccounts = accounts.length;
if (accounts.length == 0) {
if (mActivity != null) {
// no accounts, add one now. pretend that the user directly
@@ -1538,7 +1555,21 @@ public class AccountManager {
public void run(AccountManagerFuture<Bundle> future) {
try {
set(future.getResult());
final Bundle result = future.getResult();
if (mNumAccounts == 0) {
final String accountName = result.getString(KEY_ACCOUNT_NAME);
final String accountType = result.getString(KEY_ACCOUNT_TYPE);
if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
setException(new AuthenticatorException("account not in result"));
return;
}
final Account account = new Account(accountName, accountType);
mNumAccounts = 1;
getAuthToken(account, mAuthTokenType, null /* options */, mActivity,
mMyCallback, mHandler);
return;
}
set(result);
} catch (OperationCanceledException e) {
cancel(true /* mayInterruptIfRUnning */);
} catch (IOException e) {