Merge "[RemoveAccount API]: Adding support for intent." into lmp-mr1-dev

This commit is contained in:
Simranjit Singh Kohli
2014-11-13 19:18:28 +00:00
committed by Android (Google) Code Review
4 changed files with 157 additions and 25 deletions

View File

@@ -2708,7 +2708,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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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