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

Commit 8778f993 authored by Simranjit Singh Kohli's avatar Simranjit Singh Kohli
Browse files

[RemoveAccount API]: Adding support for intent.

Adding support for intent handling provided by authenticators.

Bug: 18292092

Change-Id: I1e94422bc28e5fd54c454ee6542ff2d30f82849f
parent 74a4a8d6
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -2703,7 +2703,9 @@ package android.accounts {
    method public void invalidateAuthToken(java.lang.String, java.lang.String);
    method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle);
    method public java.lang.String peekAuthToken(android.accounts.Account, java.lang.String);
    method public android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
    method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
    method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
    method public boolean removeAccountExplicitly(android.accounts.Account);
    method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
    method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
    method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
@@ -4403,9 +4405,9 @@ package android.app {
    method public android.content.Intent createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
    method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
    method public boolean inKeyguardRestrictedInputMode();
    method public boolean isKeyguardInTrustedState();
    method public boolean isKeyguardLocked();
    method public boolean isKeyguardSecure();
    method public boolean isKeyguardInTrustedState();
    method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
  }
+114 −13
Original line number Diff line number Diff line
@@ -17,37 +17,37 @@
package android.accounts;

import android.app.Activity;
import android.content.Intent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.res.Resources;
import android.database.SQLException;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.Parcelable;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.R;
import com.google.android.collect.Maps;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.HashMap;
import java.util.Map;

import com.android.internal.R;
import com.google.android.collect.Maps;
import java.util.concurrent.TimeoutException;

/**
 * This class provides access to a centralized registry of the user's
@@ -747,13 +747,17 @@ public class AccountManager {
     *     null for the main thread
     * @return An {@link AccountManagerFuture} which resolves to a Boolean,
     *     true if the account has been successfully removed
     * @deprecated use
     *     {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)}
     *     instead
     */
    @Deprecated
    public AccountManagerFuture<Boolean> removeAccount(final Account account,
            AccountManagerCallback<Boolean> callback, Handler handler) {
        if (account == null) throw new IllegalArgumentException("account is null");
        return new Future2Task<Boolean>(handler, callback) {
            public void doWork() throws RemoteException {
                mService.removeAccount(mResponse, account);
                mService.removeAccount(mResponse, account, false);
            }
            public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
                if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
@@ -764,10 +768,61 @@ public class AccountManager {
        }.start();
    }

    /**
     * Removes an account from the AccountManager. Does nothing if the account
     * does not exist.  Does not delete the account from the server.
     * The authenticator may have its own policies preventing account
     * deletion, in which case the account will not be deleted.
     *
     * <p>This method may be called from any thread, but the returned
     * {@link AccountManagerFuture} must not be used on the main thread.
     *
     * <p>This method requires the caller to hold the permission
     * {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
     *
     * @param account The {@link Account} to remove
     * @param activity The {@link Activity} context to use for launching a new
     *     authenticator-defined sub-Activity to prompt the user to delete an
     *     account; used only to call startActivity(); if null, the prompt
     *     will not be launched directly, but the {@link Intent} may be
     *     returned to the caller instead
     * @param callback Callback to invoke when the request completes,
     *     null for no callback
     * @param handler {@link Handler} identifying the callback thread,
     *     null for the main thread
     * @return An {@link AccountManagerFuture} which resolves to a Bundle with
     *     {@link #KEY_BOOLEAN_RESULT} if activity was specified and an account
     *     was removed or if active. If no activity was specified, the returned
     *     Bundle contains only {@link #KEY_INTENT} with the {@link Intent}
     *     needed to launch the actual account removal process, if authenticator
     *     needs the activity launch. If an error occurred,
     *     {@link AccountManagerFuture#getResult()} throws:
     * <ul>
     * <li> {@link AuthenticatorException} if no authenticator was registered for
     *      this account type or the authenticator failed to respond
     * <li> {@link OperationCanceledException} if the operation was canceled for
     *      any reason, including the user canceling the creation process or
     *      adding accounts (of this type) has been disabled by policy
     * </ul>
     */
    public AccountManagerFuture<Bundle> removeAccount(final Account account,
            final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
        if (account == null) throw new IllegalArgumentException("account is null");
        return new AmsTask(activity, handler, callback) {
            public void doWork() throws RemoteException {
                mService.removeAccount(mResponse, account, activity != null);
            }
        }.start();
    }

    /**
     * @see #removeAccount(Account, AccountManagerCallback, Handler)
     * @hide
     * @deprecated use
     *     {@link #removeAccountAsUser(Account, Activity, AccountManagerCallback, Handler)}
     *     instead
     */
    @Deprecated
    public AccountManagerFuture<Boolean> removeAccountAsUser(final Account account,
            AccountManagerCallback<Boolean> callback, Handler handler,
            final UserHandle userHandle) {
@@ -775,7 +830,7 @@ public class AccountManager {
        if (userHandle == null) throw new IllegalArgumentException("userHandle is null");
        return new Future2Task<Boolean>(handler, callback) {
            public void doWork() throws RemoteException {
                mService.removeAccountAsUser(mResponse, account, userHandle.getIdentifier());
                mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier());
            }
            public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
                if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
@@ -786,6 +841,52 @@ public class AccountManager {
        }.start();
    }

    /**
     * @see #removeAccount(Account, Activity, AccountManagerCallback, Handler)
     * @hide
     */
    public AccountManagerFuture<Bundle> removeAccountAsUser(final Account account,
            final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler,
            final UserHandle userHandle) {
        if (account == null)
            throw new IllegalArgumentException("account is null");
        if (userHandle == null)
            throw new IllegalArgumentException("userHandle is null");
        return new AmsTask(activity, handler, callback) {
            public void doWork() throws RemoteException {
                mService.removeAccountAsUser(mResponse, account, activity != null,
                        userHandle.getIdentifier());
            }
        }.start();
    }

    /**
     * Removes an account directly. Normally used by authenticators, not
     * directly by applications. Does not delete the account from the server.
     * The authenticator may have its own policies preventing account deletion,
     * in which case the account will not be deleted.
     * <p>
     * It is safe to call this method from the main thread.
     * <p>
     * This method requires the caller to hold the permission
     * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and to have the
     * same UID or signature as the account's authenticator.
     *
     * @param account The {@link Account} to delete.
     * @return True if the account was successfully deleted, false if the
     *         account did not exist, the account is null, or another error
     *         occurs.
     */
    public boolean removeAccountExplicitly(Account account) {
        if (account == null) throw new IllegalArgumentException("account is null");
        try {
            return mService.removeAccountExplicitly(account);
        } catch (RemoteException e) {
            // won't ever happen
            throw new RuntimeException(e);
        }
    }

    /**
     * Removes an auth token from the AccountManager's cache.  Does nothing if
     * the auth token is not currently in the cache.  Applications must call this
+5 −2
Original line number Diff line number Diff line
@@ -37,8 +37,11 @@ interface IAccountManager {
    void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features);
    void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
    boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
    void removeAccount(in IAccountManagerResponse response, in Account account);
    void removeAccountAsUser(in IAccountManagerResponse response, in Account account, int userId);
    void removeAccount(in IAccountManagerResponse response, in Account account,
        boolean expectActivityLaunch);
    void removeAccountAsUser(in IAccountManagerResponse response, in Account account,
        boolean expectActivityLaunch, int userId);
    boolean removeAccountExplicitly(in Account account);
    void invalidateAuthToken(String accountType, String authToken);
    String peekAuthToken(in Account account, String authTokenType);
    void setAuthToken(in Account account, String authTokenType, String authToken);
+35 −9
Original line number Diff line number Diff line
@@ -77,7 +77,6 @@ import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;

import com.google.android.collect.Lists;
import com.google.android.collect.Sets;

@@ -1043,7 +1042,8 @@ public class AccountManagerService
    }

    @Override
    public void removeAccount(IAccountManagerResponse response, Account account) {
    public void removeAccount(IAccountManagerResponse response, Account account,
            boolean expectActivityLaunch) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "removeAccount: " + account
                    + ", response " + response
@@ -1088,7 +1088,7 @@ public class AccountManagerService
        }

        try {
            new RemoveAccountSession(accounts, response, account).bind();
            new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind();
        } finally {
            restoreCallingIdentity(identityToken);
        }
@@ -1096,7 +1096,7 @@ public class AccountManagerService

    @Override
    public void removeAccountAsUser(IAccountManagerResponse response, Account account,
            int userId) {
            boolean expectActivityLaunch, int userId) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "removeAccount: " + account
                    + ", response " + response
@@ -1145,7 +1145,30 @@ public class AccountManagerService
        }

        try {
            new RemoveAccountSession(accounts, response, account).bind();
            new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind();
        } finally {
            restoreCallingIdentity(identityToken);
        }
    }

    @Override
    public boolean removeAccountExplicitly(Account account) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "removeAccountExplicitly: " + account
                    + ", caller's uid " + Binder.getCallingUid()
                    + ", pid " + Binder.getCallingPid());
        }
        if (account == null) throw new IllegalArgumentException("account is null");
        checkAuthenticateAccountsPermission(account);

        UserAccounts accounts = getUserAccountsForCaller();
        int userId = Binder.getCallingUserHandle().getIdentifier();
        if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
            return false;
        }
        long identityToken = clearCallingIdentity();
        try {
            return removeAccountInternal(accounts, account);
        } finally {
            restoreCallingIdentity(identityToken);
        }
@@ -1154,8 +1177,8 @@ public class AccountManagerService
    private class RemoveAccountSession extends Session {
        final Account mAccount;
        public RemoveAccountSession(UserAccounts accounts, IAccountManagerResponse response,
                Account account) {
            super(accounts, response, account.type, false /* expectActivityLaunch */,
                Account account, boolean expectActivityLaunch) {
            super(accounts, response, account.type, expectActivityLaunch,
                    true /* stripAuthTokenFromResult */);
            mAccount = account;
        }
@@ -1203,10 +1226,12 @@ public class AccountManagerService
        removeAccountInternal(getUserAccountsForCaller(), account);
    }

    private void removeAccountInternal(UserAccounts accounts, Account account) {
    private boolean removeAccountInternal(UserAccounts accounts, Account account) {
        int deleted;
        synchronized (accounts.cacheLock) {
            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
            db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
            deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
                    + "=?",
                    new String[]{account.name, account.type});
            removeAccountFromCacheLocked(accounts, account);
            sendAccountsChangedBroadcast(accounts.userId);
@@ -1226,6 +1251,7 @@ public class AccountManagerService
                Binder.restoreCallingIdentity(id);
            }
        }
        return (deleted > 0);
    }

    @Override