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

Commit f1946baa authored by Jian Sun's avatar Jian Sun Committed by Android (Google) Code Review
Browse files

Merge "Fix visibility issue in AccountManager.getAuthTokenByFeatures." into oc-dev

parents d7427d5d f29d549c
Loading
Loading
Loading
Loading
+28 −61
Original line number Diff line number Diff line
@@ -2511,6 +2511,18 @@ public class AccountManager {
        return new AuthenticatorException(message);
    }

    private void getAccountByTypeAndFeatures(String accountType, String[] features,
        AccountManagerCallback<Bundle> callback, Handler handler) {
        (new AmsTask(null, handler, callback) {
            @Override
            public void doWork() throws RemoteException {
                mService.getAccountByTypeAndFeatures(mResponse, accountType, features,
                    mContext.getOpPackageName());
            }

        }).start();
    }

    private class GetAuthTokenByTypeAndFeaturesTask
            extends AmsTask implements AccountManagerCallback<Bundle> {
        GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType,
@@ -2537,13 +2549,16 @@ public class AccountManager {

        @Override
        public void doWork() throws RemoteException {
            getAccountsByTypeAndFeatures(mAccountType, mFeatures,
                    new AccountManagerCallback<Account[]>() {
            getAccountByTypeAndFeatures(mAccountType, mFeatures,
                    new AccountManagerCallback<Bundle>() {
                        @Override
                        public void run(AccountManagerFuture<Account[]> future) {
                            Account[] accounts;
                        public void run(AccountManagerFuture<Bundle> future) {
                            String accountName = null;
                            String accountType = null;
                            try {
                                accounts = future.getResult();
                                Bundle result = future.getResult();
                                accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
                                accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
                            } catch (OperationCanceledException e) {
                                setException(e);
                                return;
@@ -2555,9 +2570,7 @@ public class AccountManager {
                                return;
                            }

                            mNumAccounts = accounts.length;

                            if (accounts.length == 0) {
                            if (accountName == null) {
                                if (mActivity != null) {
                                    // no accounts, add one now. pretend that the user directly
                                    // made this request
@@ -2577,63 +2590,17 @@ public class AccountManager {
                                    }
                                    // we are done
                                }
                            } else if (accounts.length == 1) {
                            } else {
                                mNumAccounts = 1;
                                Account account = new Account(accountName, accountType);
                                // have a single account, return an authtoken for it
                                if (mActivity == null) {
                                    mFuture = getAuthToken(accounts[0], mAuthTokenType,
                                    mFuture = getAuthToken(account, mAuthTokenType,
                                            false /* notifyAuthFailure */, mMyCallback, mHandler);
                                } else {
                                    mFuture = getAuthToken(accounts[0],
                                            mAuthTokenType, mLoginOptions,
                                    mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions,
                                            mActivity, mMyCallback, mHandler);
                                }
                            } else {
                                if (mActivity != null) {
                                    IAccountManagerResponse chooseResponse =
                                            new IAccountManagerResponse.Stub() {
                                        @Override
                                        public void onResult(Bundle value) throws RemoteException {
                                            Account account = new Account(
                                                    value.getString(KEY_ACCOUNT_NAME),
                                                    value.getString(KEY_ACCOUNT_TYPE),
                                                    value.getString(KEY_ACCOUNT_ACCESS_ID));
                                            mFuture = getAuthToken(account, mAuthTokenType,
                                                    mLoginOptions,  mActivity, mMyCallback,
                                                    mHandler);
                                        }

                                        @Override
                                        public void onError(int errorCode, String errorMessage)
                                                throws RemoteException {
                                            mResponse.onError(errorCode, errorMessage);
                                        }
                                    };
                                    // have many accounts, launch the chooser
                                    Intent intent = new Intent();
                                    // TODO - this activity will not include
                                    // USER_MANAGED_NOT_VISIBLE
                                    // accounts. We need to move method to service
                                    ComponentName componentName = ComponentName.unflattenFromString(
                                            Resources.getSystem().getString(
                                                    R.string.config_chooseAccountActivity));
                                    intent.setClassName(componentName.getPackageName(),
                                            componentName.getClassName());
                                    intent.putExtra(KEY_ACCOUNTS, accounts);
                                    intent.putExtra(KEY_ACCOUNT_MANAGER_RESPONSE,
                                            new AccountManagerResponse(chooseResponse));
                                    mActivity.startActivity(intent);
                                    // the result will arrive via the IAccountManagerResponse
                                } else {
                                    // send result since we can't prompt to select an account
                                    Bundle result = new Bundle();
                                    result.putString(KEY_ACCOUNTS, null);
                                    try {
                                        mResponse.onResult(result);
                                    } catch (RemoteException e) {
                                        // this will never happen
                                    }
                                    // we are done
                                }
                            }
                        }}, mHandler);
        }
@@ -2723,8 +2690,8 @@ public class AccountManager {
    public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
            final String accountType, final String authTokenType, final String[] features,
            final Activity activity, final Bundle addAccountOptions,
            final Bundle getAuthTokenOptions,
            final AccountManagerCallback<Bundle> callback, final Handler handler) {
            final Bundle getAuthTokenOptions, final AccountManagerCallback<Bundle> callback,
            final Handler handler) {
        if (accountType == null) throw new IllegalArgumentException("account type is null");
        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
        final GetAuthTokenByTypeAndFeaturesTask task =
+2 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ interface IAccountManager {
    Account[] getAccountsAsUser(String accountType, int userId, String opPackageName);
    void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features,
        String opPackageName);
    void getAccountByTypeAndFeatures(in IAccountManagerResponse response, String accountType,
        in String[] features, String opPackageName);
    void getAccountsByFeatures(in IAccountManagerResponse response, String accountType,
        in String[] features, String opPackageName);
    boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
+117 −3
Original line number Diff line number Diff line
@@ -23,8 +23,10 @@ import android.accounts.AccountAndUser;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.accounts.AccountManagerInternal;
import android.accounts.AccountManagerResponse;
import android.accounts.AuthenticatorDescription;
import android.accounts.CantAddAccountActivity;
import android.accounts.ChooseAccountActivity;
import android.accounts.GrantCredentialsPermissionActivity;
import android.accounts.IAccountAuthenticator;
import android.accounts.IAccountAuthenticatorResponse;
@@ -71,6 +73,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -4042,6 +4045,7 @@ public class AccountManagerService
        private volatile int mCurrentAccount = 0;
        private final int mCallingUid;
        private final String mPackageName;
        private final boolean mIncludeManagedNotVisible;

        public GetAccountsByTypeAndFeatureSession(
                UserAccounts accounts,
@@ -4049,19 +4053,21 @@ public class AccountManagerService
                String type,
                String[] features,
                int callingUid,
                String packageName) {
                String packageName,
                boolean includeManagedNotVisible) {
            super(accounts, response, type, false /* expectActivityLaunch */,
                    true /* stripAuthTokenFromResult */, null /* accountName */,
                    false /* authDetailsRequired */);
            mCallingUid = callingUid;
            mFeatures = features;
            mPackageName = packageName;
            mIncludeManagedNotVisible = includeManagedNotVisible;
        }

        @Override
        public void run() throws RemoteException {
            mAccountsOfType = getAccountsFromCache(mAccounts, mAccountType,
                    mCallingUid, mPackageName, false /* include managed not visible*/);
                    mCallingUid, mPackageName, mIncludeManagedNotVisible);
            // check whether each account matches the requested features
            mAccountsWithFeatures = new ArrayList<>(mAccountsOfType.length);
            mCurrentAccount = 0;
@@ -4426,6 +4432,112 @@ public class AccountManagerService
                packageName, packageUid, opPackageName, true /* includeUserManagedNotVisible */);
    }

    private boolean needToStartChooseAccountActivity(Account[] accounts, String callingPackage) {
        if (accounts.length < 1) return false;
        if (accounts.length > 1) return true;
        Account account = accounts[0];
        UserAccounts userAccounts = getUserAccounts(UserHandle.getCallingUserId());
        int visibility = resolveAccountVisibility(account, callingPackage, userAccounts);
        if (visibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) return true;
        return false;
    }

    private void startChooseAccountActivityWithAccounts(
        IAccountManagerResponse response, Account[] accounts) {
        Intent intent = new Intent(mContext, ChooseAccountActivity.class);
        intent.putExtra(AccountManager.KEY_ACCOUNTS, accounts);
        intent.putExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE,
                new AccountManagerResponse(response));

        mContext.startActivityAsUser(intent, UserHandle.of(UserHandle.getCallingUserId()));
    }

    private void handleGetAccountsResult(
        IAccountManagerResponse response,
        Account[] accounts,
        String callingPackage) {

        if (needToStartChooseAccountActivity(accounts, callingPackage)) {
            startChooseAccountActivityWithAccounts(response, accounts);
            return;
        }
        if (accounts.length == 1) {
            Bundle bundle = new Bundle();
            bundle.putString(AccountManager.KEY_ACCOUNT_NAME, accounts[0].name);
            bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, accounts[0].type);
            onResult(response, bundle);
            return;
        }
        // No qualified account exists, return an empty Bundle.
        onResult(response, new Bundle());
    }

    @Override
    public void getAccountByTypeAndFeatures(
        IAccountManagerResponse response,
        String accountType,
        String[] features,
        String opPackageName) {

        int callingUid = Binder.getCallingUid();
        mAppOpsManager.checkPackage(callingUid, opPackageName);
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "getAccount: accountType " + accountType
                    + ", response " + response
                    + ", features " + Arrays.toString(features)
                    + ", caller's uid " + callingUid
                    + ", pid " + Binder.getCallingPid());
        }
        if (response == null) throw new IllegalArgumentException("response is null");
        if (accountType == null) throw new IllegalArgumentException("accountType is null");

        int userId = UserHandle.getCallingUserId();

        long identityToken = clearCallingIdentity();
        try {
            UserAccounts userAccounts = getUserAccounts(userId);
            if (ArrayUtils.isEmpty(features)) {
                Account[] accountsWithManagedNotVisible = getAccountsFromCache(
                    userAccounts, accountType, callingUid, opPackageName,
                    true /* include managed not visible */);
                handleGetAccountsResult(
                    response, accountsWithManagedNotVisible, opPackageName);
                return;
            }

            IAccountManagerResponse retrieveAccountsResponse =
                new IAccountManagerResponse.Stub() {
                @Override
                public void onResult(Bundle value) throws RemoteException {
                    Parcelable[] parcelables = value.getParcelableArray(
                        AccountManager.KEY_ACCOUNTS);
                    Account[] accounts = new Account[parcelables.length];
                    for (int i = 0; i < parcelables.length; i++) {
                        accounts[i] = (Account) parcelables[i];
                    }
                    handleGetAccountsResult(
                        response, accounts, opPackageName);
                }

                @Override
                public void onError(int errorCode, String errorMessage)
                        throws RemoteException {
                    // Will not be called in this case.
                }
            };
            new GetAccountsByTypeAndFeatureSession(
                    userAccounts,
                    retrieveAccountsResponse,
                    accountType,
                    features,
                    callingUid,
                    opPackageName,
                    true /* include managed not visible */).bind();
        } finally {
            restoreCallingIdentity(identityToken);
        }
    }

    @Override
    public void getAccountsByFeatures(
            IAccountManagerResponse response,
@@ -4458,6 +4570,7 @@ public class AccountManagerService
            }
            return;
        }

        long identityToken = clearCallingIdentity();
        try {
            UserAccounts userAccounts = getUserAccounts(userId);
@@ -4475,7 +4588,8 @@ public class AccountManagerService
                    type,
                    features,
                    callingUid,
                    opPackageName).bind();
                    opPackageName,
                    false /* include managed not visible */).bind();
        } finally {
            restoreCallingIdentity(identityToken);
        }
+218 −0

File changed.

Preview size limit exceeded, changes collapsed.

+3 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ public final class AccountManagerServiceTestFixtures {
    public static final String KEY_OPTIONS_BUNDLE =
            "account_manager_service_test:option_bundle_key";
    public static final String ACCOUNT_NAME_SUCCESS = "success_on_return@fixture.com";
    public static final String ACCOUNT_NAME_SUCCESS_2 = "success_on_return_2@fixture.com";
    public static final String ACCOUNT_NAME_INTERVENE = "intervene@fixture.com";
    public static final String ACCOUNT_NAME_ERROR = "error@fixture.com";

@@ -69,6 +70,8 @@ public final class AccountManagerServiceTestFixtures {

    public static final Account ACCOUNT_SUCCESS =
            new Account(ACCOUNT_NAME_SUCCESS, ACCOUNT_TYPE_1);
    public static final Account ACCOUNT_SUCCESS_2 =
            new Account(ACCOUNT_NAME_SUCCESS_2, ACCOUNT_TYPE_1);
    public static final Account ACCOUNT_INTERVENE =
            new Account(ACCOUNT_NAME_INTERVENE, ACCOUNT_TYPE_1);
    public static final Account ACCOUNT_ERROR =
Loading