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

Commit 01985ff6 authored by Dmitry Dementyev's avatar Dmitry Dementyev
Browse files

Implement Account Discovery API.

Inludes temporary flow for notifications filtered by accountType
Bug: 33046496
Test: cts tests, manual tests.
Change-Id: I2d767030e851579a0666efd7e243a1239af740c7
parent ca003429
Loading
Loading
Loading
Loading
+36 −7
Original line number Diff line number Diff line
@@ -53,9 +53,12 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.SuppressWarnings;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
@@ -864,11 +867,17 @@ public class AccountManager {
     *
     * @param account The account for which visibility data should be returned.
     *
     * @return Map from uid to visibility for given account
     * @return Map from uid to visibility for given account.
     */
    public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) {
        // TODO implement.
        return null;
        try {
            @SuppressWarnings("unchecked")
            Map<Integer, Integer> result = (Map<Integer, Integer>) mService
                    .getUidsAndVisibilityForAccount(account);
            return result;
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
@@ -2110,8 +2119,21 @@ public class AccountManager {
                synchronized (mAccountsUpdatedListeners) {
                    try {
                        if (mAccountsUpdatedListeners.containsKey(listener)) {
                            Set<String> types = mAccountsUpdatedListenersTypes.get(listener);
                            if (types != null) {
                                // filter by account type;
                                ArrayList<Account> filtered = new ArrayList<>();
                                for (Account account : accountsCopy) {
                                    if (types.contains(account.type)) {
                                        filtered.add(account);
                                    }
                                }
                                listener.onAccountsUpdated(
                                        filtered.toArray(new Account[filtered.size()]));
                            } else {
                                listener.onAccountsUpdated(accountsCopy);
                            }
                        }
                    } catch (SQLException e) {
                        // Better luck next time. If the problem was disk-full,
                        // the STORAGE_OK intent will re-trigger the update.
@@ -2759,6 +2781,9 @@ public class AccountManager {
    private final HashMap<OnAccountsUpdateListener, Handler> mAccountsUpdatedListeners =
            Maps.newHashMap();

    private final HashMap<OnAccountsUpdateListener, Set<String> > mAccountsUpdatedListenersTypes =
            Maps.newHashMap();

    /**
     * BroadcastReceiver that listens for the LOGIN_ACCOUNTS_CHANGED_ACTION intent
     * so that it can read the updated list of accounts and send them to the listener
@@ -2784,7 +2809,7 @@ public class AccountManager {
     * accounts of any type related to the caller. This method is equivalent to
     * addOnAccountsUpdatedListener(listener, handler, updateImmediately, null)
     *
     * @see #addOnAccountsUpdatedListener(OnAccountsUpdateListener, Handler, boolean, Handler,
     * @see #addOnAccountsUpdatedListener(OnAccountsUpdateListener, Handler, boolean,
     *      String[])
     */
    public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
@@ -2828,7 +2853,10 @@ public class AccountManager {
            final boolean wasEmpty = mAccountsUpdatedListeners.isEmpty();

            mAccountsUpdatedListeners.put(listener, handler);

            if (accountTypes != null) {
                mAccountsUpdatedListenersTypes.put(listener,
                        new HashSet<String>(Arrays.asList(accountTypes)));
            }

            if (wasEmpty) {
                // Register a broadcast receiver to monitor account changes
@@ -2870,6 +2898,7 @@ public class AccountManager {
                return;
            }
            mAccountsUpdatedListeners.remove(listener);
            mAccountsUpdatedListenersTypes.remove(listener);
            if (mAccountsUpdatedListeners.isEmpty()) {
                mContext.unregisterReceiver(mAccountsChangedBroadcastReceiver);
            }
+3 −1
Original line number Diff line number Diff line
@@ -52,7 +52,9 @@ public class ChooseAccountActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // TODO This activity is only used by getAuthTokenByFeatures and can not see
        // VISIBILITY_USER_MANAGED_NOT_VISIBLE accounts. It should be moved to account managed
        // service.
        mAccounts = getIntent().getParcelableArrayExtra(AccountManager.KEY_ACCOUNTS);
        mAccountManagerResponse =
                getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE);
+70 −36
Original line number Diff line number Diff line
@@ -40,7 +40,9 @@ import com.android.internal.R;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
@@ -110,7 +112,7 @@ public class ChooseTypeAndAccountActivity extends Activity
    private static final String KEY_INSTANCE_STATE_EXISTING_ACCOUNTS = "existingAccounts";
    private static final String KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME = "selectedAccountName";
    private static final String KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT = "selectedAddAccount";
    private static final String KEY_INSTANCE_STATE_ACCOUNT_LIST = "accountList";
    private static final String KEY_INSTANCE_STATE_ACCOUNT_LIST = "accountAndVisibilityList";

    private static final int SELECTED_ITEM_NONE = -1;

@@ -120,7 +122,11 @@ public class ChooseTypeAndAccountActivity extends Activity
    private boolean mSelectedAddNewAccount = false;
    private String mDescriptionOverride;

    private ArrayList<Account> mAccounts;
    private Map<Account, Integer> mAccounts;
    // TODO Redesign flow to show NOT_VISIBLE accounts
    // and display a warning if they are selected.
    // Currently NOT_VISBILE accounts are not shown at all.
    private ArrayList<Account> mPossiblyVisibleAccounts;
    private int mPendingRequest = REQUEST_NULL;
    private Parcelable[] mExistingAccounts = null;
    private int mSelectedItemIndex;
@@ -164,12 +170,12 @@ public class ChooseTypeAndAccountActivity extends Activity
                    savedInstanceState.getParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS);

            // Makes sure that any user selection is preserved across orientation changes.
            mSelectedAccountName = savedInstanceState.getString(
                    KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME);

            mSelectedAddNewAccount = savedInstanceState.getBoolean(
                    KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false);
            mAccounts = savedInstanceState.getParcelableArrayList(KEY_INSTANCE_STATE_ACCOUNT_LIST);
            mSelectedAccountName =
                    savedInstanceState.getString(KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME);
            mSelectedAddNewAccount =
                    savedInstanceState.getBoolean(KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false);
            mAccounts = (Map<Account, Integer>) savedInstanceState
                    .getSerializable(KEY_INSTANCE_STATE_ACCOUNT_LIST);
        } else {
            mPendingRequest = REQUEST_NULL;
            mExistingAccounts = null;
@@ -220,9 +226,15 @@ public class ChooseTypeAndAccountActivity extends Activity
            }
        }

        String[] listItems = getListOfDisplayableOptions(mAccounts);
        mSelectedItemIndex = getItemIndexToSelect(
            mAccounts, mSelectedAccountName, mSelectedAddNewAccount);
        mPossiblyVisibleAccounts = new ArrayList<>(mAccounts.size());
        for (Map.Entry<Account, Integer> entry : mAccounts.entrySet()) {
            if (AccountManager.VISIBILITY_NOT_VISIBLE != entry.getValue()) {
                mPossiblyVisibleAccounts.add(entry.getKey());
            }
        }
        String[] listItems = getListOfDisplayableOptions(mPossiblyVisibleAccounts);
        mSelectedItemIndex = getItemIndexToSelect(mPossiblyVisibleAccounts, mSelectedAccountName,
                mSelectedAddNewAccount);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.choose_type_and_account);
@@ -250,15 +262,18 @@ public class ChooseTypeAndAccountActivity extends Activity
            outState.putParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS, mExistingAccounts);
        }
        if (mSelectedItemIndex != SELECTED_ITEM_NONE) {
            if (mSelectedItemIndex == mAccounts.size()) {
            if (mSelectedItemIndex == mPossiblyVisibleAccounts.size()) {
                outState.putBoolean(KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, true);
            } else {
                outState.putBoolean(KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false);
                outState.putString(KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME,
                        mAccounts.get(mSelectedItemIndex).name);
                        mPossiblyVisibleAccounts.get(mSelectedItemIndex).name);
            }
        }
        outState.putParcelableArrayList(KEY_INSTANCE_STATE_ACCOUNT_LIST, mAccounts);
        // should be HashMap by default.
        HashMap<Account, Integer> accountsHashMap = (mAccounts instanceof HashMap)
                ? (HashMap) mAccounts : new HashMap<Account, Integer>(mAccounts);
        outState.putSerializable(KEY_INSTANCE_STATE_ACCOUNT_LIST, accountsHashMap);
    }

    public void onCancelButtonClicked(View view) {
@@ -266,11 +281,11 @@ public class ChooseTypeAndAccountActivity extends Activity
    }

    public void onOkButtonClicked(View view) {
        if (mSelectedItemIndex == mAccounts.size()) {
        if (mSelectedItemIndex == mPossiblyVisibleAccounts.size()) {
            // Selected "Add New Account" option
            startChooseAccountTypeActivity();
        } else if (mSelectedItemIndex != SELECTED_ITEM_NONE) {
            onAccountSelected(mAccounts.get(mSelectedItemIndex));
            onAccountSelected(mPossiblyVisibleAccounts.get(mSelectedItemIndex));
        }
    }

@@ -321,6 +336,7 @@ public class ChooseTypeAndAccountActivity extends Activity
                }

                if (accountName == null || accountType == null) {
                    // new account was added.
                    Account[] currentAccounts = AccountManager.get(this).getAccountsForPackage(
                            mCallingPackage, mCallingUid);
                    Set<Account> preExistingAccounts = new HashSet<Account>();
@@ -328,6 +344,7 @@ public class ChooseTypeAndAccountActivity extends Activity
                        preExistingAccounts.add((Account) accountParcel);
                    }
                    for (Account account : currentAccounts) {
                        // New account is visible to the app - return it.
                        if (!preExistingAccounts.contains(account)) {
                            accountName = account.name;
                            accountType = account.type;
@@ -409,13 +426,27 @@ public class ChooseTypeAndAccountActivity extends Activity
    }

    private void setResultAndFinish(final String accountName, final String accountType) {
        // Mark account as visible since user chose it.
        Account account = new Account(accountName, accountType);
        Integer oldVisibility = mAccounts.get(account);
        // oldVisibility is null if new account was added
        if (oldVisibility == null) {
            Map<Account, Integer> accountsAndVisibility = AccountManager.get(this)
                    .getAccountsAndVisibilityForPackage(mCallingPackage, null /* type */);
            oldVisibility = accountsAndVisibility.get(account);
        }
        if (oldVisibility != null
                && oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) {
            AccountManager.get(this).setAccountVisibility(account, mCallingUid,
                    AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
        }
        Bundle bundle = new Bundle();
        bundle.putString(AccountManager.KEY_ACCOUNT_NAME, accountName);
        bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, accountType);
        setResult(Activity.RESULT_OK, new Intent().putExtras(bundle));
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "ChooseTypeAndAccountActivity.setResultAndFinish: "
                    + "selected account " + accountName + ", " + accountType);
            Log.v(TAG, "ChooseTypeAndAccountActivity.setResultAndFinish: selected account "
                    + accountName + ", " + accountType);
        }
        finish();
    }
@@ -474,23 +505,26 @@ public class ChooseTypeAndAccountActivity extends Activity
    }

    /**
     * Create a list of Account objects for each account that is acceptable. Filter out
     * accounts that don't match the allowable types, if provided, or that don't match the
     * allowable accounts, if provided.
     * Create a list of Account objects for each account that is acceptable. Filter out accounts
     * that don't match the allowable types, if provided, or that don't match the allowable
     * accounts, if provided.
     */
    private ArrayList<Account> getAcceptableAccountChoices(AccountManager accountManager) {
      final Account[] accounts = accountManager.getAccountsForPackage(mCallingPackage,
              mCallingUid);
      ArrayList<Account> accountsToPopulate = new ArrayList<Account>(accounts.length);
      for (Account account : accounts) {
          if (mSetOfAllowableAccounts != null && !mSetOfAllowableAccounts.contains(account)) {
    private Map<Account, Integer> getAcceptableAccountChoices(AccountManager accountManager) {
        Map<Account, Integer> accountsAndVisibility =
                accountManager.getAccountsAndVisibilityForPackage(mCallingPackage, null /* type */);

        Map<Account, Integer> accountsToPopulate =
                new HashMap<Account, Integer>(accountsAndVisibility.size());
        for (Map.Entry<Account, Integer> entry : accountsAndVisibility.entrySet()) {
            if (mSetOfAllowableAccounts != null
                    && !mSetOfAllowableAccounts.contains(entry.getKey())) {
                continue;
            }
            if (mSetOfRelevantAccountTypes != null
                  && !mSetOfRelevantAccountTypes.contains(account.type)) {
                    && !mSetOfRelevantAccountTypes.contains(entry.getKey().type)) {
                continue;
            }
          accountsToPopulate.add(account);
            accountsToPopulate.put(entry.getKey(), entry.getValue());
        }
        return accountsToPopulate;
    }
+3 −3
Original line number Diff line number Diff line
@@ -108,8 +108,8 @@ interface IAccountManager {
    void isCredentialsUpdateSuggested(in IAccountManagerResponse response, in Account account,
        String statusToken);

    /* Allows Authenticator to get UIDs of packages which registered to receive updates about given account type.*/
    int[] getRequestingUidsForType(String accountType);
    /* Returns Map<Integer, Integer> from UID to visibility with all values stored for given account*/
    Map getUidsAndVisibilityForAccount(in Account account);

    boolean addAccountExplicitlyWithVisibility(in Account account, String password, in Bundle extras,
            in Map visibility);
+638 −234

File changed.

Preview size limit exceeded, changes collapsed.

Loading