Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0fd8436 authored by Fred Quintana's avatar Fred Quintana
Browse files

- add verbose logging to the authenticator

- fix a bug in AccountManager.getAuthTokenByFeatures() where getAuthToken()
  isn't called after adding the account when necessary
parent a9fb0a24
Loading
Loading
Loading
Loading
+83 −3
Original line number Diff line number Diff line
@@ -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));
                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");
            }
+14 −0
Original line number Diff line number Diff line
@@ -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) {
+32 −1
Original line number Diff line number Diff line
@@ -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) {