diff --git a/api/current.xml b/api/current.xml index d57198473ab18..ee8d2eb865116 100644 --- a/api/current.xml +++ b/api/current.xml @@ -13463,6 +13463,23 @@ + + + + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -14160,7 +13963,7 @@ - - - - - - - - - - + - + - + @@ -14276,13 +14071,13 @@ - + - - - - - - - - - - - - - - - - - - - - - - + + @@ -14401,7 +14176,7 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + CREATOR = new Creator() { @@ -79,6 +79,6 @@ public class Account implements Parcelable { }; public String toString() { - return "Account {name=" + mName + ", type=" + mType + "}"; + return "Account {name=" + name + ", type=" + type + "}"; } } diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 502abbb312f29..9f70534fb81ab 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -26,8 +26,6 @@ import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.Parcelable; -import android.util.Config; -import android.util.Log; import java.io.IOException; import java.util.concurrent.Callable; @@ -80,258 +78,132 @@ public class AccountManager { return (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE); } - public String blockingGetPassword(Account account) { - ensureNotOnMainThread(); + public String getPassword(final Account account) { try { return mService.getPassword(account); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // will never happen throw new RuntimeException(e); } } - public Future1 getPassword(final Future1Callback callback, - final Account account, final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public String call() throws Exception { - return blockingGetPassword(account); - } - }); - } - - public String blockingGetUserData(Account account, String key) { - ensureNotOnMainThread(); + public String getUserData(final Account account, final String key) { try { return mService.getUserData(account, key); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // will never happen throw new RuntimeException(e); } } - public Future1 getUserData(Future1Callback callback, - final Account account, final String key, Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public String call() throws Exception { - return blockingGetUserData(account, key); - } - }); - } - - public AuthenticatorDescription[] blockingGetAuthenticatorTypes() { - ensureNotOnMainThread(); + public AuthenticatorDescription[] getAuthenticatorTypes() { try { return mService.getAuthenticatorTypes(); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // will never happen throw new RuntimeException(e); } } - public Future1 getAuthenticatorTypes( - Future1Callback callback, Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public AuthenticatorDescription[] call() throws Exception { - return blockingGetAuthenticatorTypes(); - } - }); - } - - public Account[] blockingGetAccounts() { - ensureNotOnMainThread(); + public Account[] getAccounts() { try { - return mService.getAccounts(); + return mService.getAccounts(null); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // won't ever happen throw new RuntimeException(e); } } - public Account[] blockingGetAccountsByType(String accountType) { - ensureNotOnMainThread(); + public Account[] getAccountsByType(String type) { try { - return mService.getAccountsByType(accountType); + return mService.getAccounts(type); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // won't ever happen throw new RuntimeException(e); } } - public Future1 getAccounts(Future1Callback callback, Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Account[] call() throws Exception { - return blockingGetAccounts(); - } - }); - } - - public Future1 getAccountsByType(Future1Callback callback, - final String type, Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Account[] call() throws Exception { - return blockingGetAccountsByType(type); - } - }); - } - - public boolean blockingAddAccountExplicitly(Account account, String password, Bundle extras) { - ensureNotOnMainThread(); + public boolean addAccountExplicitly(Account account, String password, Bundle extras) { try { return mService.addAccount(account, password, extras); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // won't ever happen throw new RuntimeException(e); } } - public Future1 addAccountExplicitly(final Future1Callback callback, - final Account account, final String password, final Bundle extras, - final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Boolean call() throws Exception { - return blockingAddAccountExplicitly(account, password, extras); + public AccountManagerFuture removeAccount(final Account account, + AccountManagerCallback callback, Handler handler) { + return new Future2Task(handler, callback) { + public void doWork() throws RemoteException { + mService.removeAccount(mResponse, account); } - }); - } - - public void blockingRemoveAccount(Account account) { - ensureNotOnMainThread(); - try { - mService.removeAccount(account); - } catch (RemoteException e) { - // if this happens the entire runtime will restart - } - } - - public Future1 removeAccount(Future1Callback callback, final Account account, - final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Void call() throws Exception { - blockingRemoveAccount(account); - return null; + public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException { + if (!bundle.containsKey(Constants.BOOLEAN_RESULT_KEY)) { + throw new AuthenticatorException("no result in response"); + } + return bundle.getBoolean(Constants.BOOLEAN_RESULT_KEY); } - }); + }.start(); } - public void blockingInvalidateAuthToken(String accountType, String authToken) { - ensureNotOnMainThread(); + public void invalidateAuthToken(final String accountType, final String authToken) { try { mService.invalidateAuthToken(accountType, authToken); } catch (RemoteException e) { - // if this happens the entire runtime will restart - } - } - - public Future1 invalidateAuthToken(Future1Callback callback, - final String accountType, final String authToken, final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Void call() throws Exception { - blockingInvalidateAuthToken(accountType, authToken); - return null; - } - }); - } - - public String blockingPeekAuthToken(Account account, String authTokenType) { - ensureNotOnMainThread(); - try { - return mService.peekAuthToken(account, authTokenType); - } catch (RemoteException e) { - // if this happens the entire runtime will restart + // won't ever happen throw new RuntimeException(e); } } - public Future1 peekAuthToken(Future1Callback callback, - final Account account, final String authTokenType, final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public String call() throws Exception { - return blockingPeekAuthToken(account, authTokenType); - } - }); + public String peekAuthToken(final Account account, final String authTokenType) { + try { + return mService.peekAuthToken(account, authTokenType); + } catch (RemoteException e) { + // won't ever happen + throw new RuntimeException(e); + } } - public void blockingSetPassword(Account account, String password) { - ensureNotOnMainThread(); + public void setPassword(final Account account, final String password) { try { mService.setPassword(account, password); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // won't ever happen + throw new RuntimeException(e); } } - public Future1 setPassword(Future1Callback callback, - final Account account, final String password, final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Void call() throws Exception { - blockingSetPassword(account, password); - return null; - } - }); - } - - public void blockingClearPassword(Account account) { - ensureNotOnMainThread(); + public void clearPassword(final Account account) { try { mService.clearPassword(account); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // won't ever happen + throw new RuntimeException(e); } } - public Future1 clearPassword(final Future1Callback callback, final Account account, - final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Void call() throws Exception { - blockingClearPassword(account); - return null; - } - }); - } - - public void blockingSetUserData(Account account, String key, String value) { - ensureNotOnMainThread(); + public void setUserData(final Account account, final String key, final String value) { try { mService.setUserData(account, key, value); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // won't ever happen + throw new RuntimeException(e); } } - public Future1 setUserData(Future1Callback callback, - final Account account, final String key, final String value, final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Void call() throws Exception { - blockingSetUserData(account, key, value); - return null; - } - }); - } - - public void blockingSetAuthToken(Account account, String authTokenType, String authToken) { - ensureNotOnMainThread(); + public void setAuthToken(Account account, final String authTokenType, final String authToken) { try { mService.setAuthToken(account, authTokenType, authToken); } catch (RemoteException e) { - // if this happens the entire runtime will restart + // won't ever happen + throw new RuntimeException(e); } } - public Future1 setAuthToken(Future1Callback callback, - final Account account, final String authTokenType, final String authToken, - final Handler handler) { - return startAsFuture(callback, handler, new Callable() { - public Void call() throws Exception { - blockingSetAuthToken(account, authTokenType, authToken); - return null; - } - }); - } - public String blockingGetAuthToken(Account account, String authTokenType, boolean notifyAuthFailure) throws OperationCanceledException, IOException, AuthenticatorException { - ensureNotOnMainThread(); Bundle bundle = getAuthToken(account, authTokenType, notifyAuthFailure, null /* callback */, null /* handler */).getResult(); return bundle.getString(Constants.AUTHTOKEN_KEY); @@ -349,9 +221,9 @@ public class AccountManager { * @param loginOptions * @param activity the activity to launch the login intent, if necessary, and to which */ - public Future2 getAuthToken( + public AccountManagerFuture getAuthToken( final Account account, final String authTokenType, final Bundle loginOptions, - final Activity activity, Future2Callback callback, Handler handler) { + final Activity activity, AccountManagerCallback callback, Handler handler) { if (activity == null) throw new IllegalArgumentException("activity is null"); if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); return new AmsTask(activity, handler, callback) { @@ -363,9 +235,9 @@ public class AccountManager { }.start(); } - public Future2 getAuthToken( + public AccountManagerFuture getAuthToken( final Account account, final String authTokenType, final boolean notifyAuthFailure, - Future2Callback callback, Handler handler) { + AccountManagerCallback callback, Handler handler) { if (account == null) throw new IllegalArgumentException("account is null"); if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); return new AmsTask(null, handler, callback) { @@ -376,10 +248,10 @@ public class AccountManager { }.start(); } - public Future2 addAccount(final String accountType, + public AccountManagerFuture addAccount(final String accountType, final String authTokenType, final String[] requiredFeatures, final Bundle addAccountOptions, - final Activity activity, Future2Callback callback, Handler handler) { + final Activity activity, AccountManagerCallback callback, Handler handler) { return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { mService.addAcount(mResponse, accountType, authTokenType, @@ -389,44 +261,45 @@ public class AccountManager { } /** @deprecated use {@link #confirmCredentials} instead */ - public Future1 confirmPassword(final Account account, final String password, - Future1Callback callback, Handler handler) { - return new AMSTaskBoolean(handler, callback) { + public AccountManagerFuture confirmPassword(final Account account, final String password, + AccountManagerCallback callback, Handler handler) { + return new Future2Task(handler, callback) { public void doWork() throws RemoteException { - mService.confirmPassword(response, account, password); + mService.confirmPassword(mResponse, account, password); } - }; - } - - public Account[] blockingGetAccountsWithTypeAndFeatures(String type, String[] features) - throws AuthenticatorException, IOException, OperationCanceledException { - Future2 future = getAccountsWithTypeAndFeatures(type, features, - null /* callback */, null /* handler */); - Bundle result = future.getResult(); - Parcelable[] accountsTemp = result.getParcelableArray(Constants.ACCOUNTS_KEY); - if (accountsTemp == null) { - throw new AuthenticatorException("accounts should not be null"); - } - Account[] accounts = new Account[accountsTemp.length]; - for (int i = 0; i < accountsTemp.length; i++) { - accounts[i] = (Account) accountsTemp[i]; - } - return accounts; - } - - public Future2 getAccountsWithTypeAndFeatures( - final String type, final String[] features, - Future2Callback callback, Handler handler) { - if (type == null) throw new IllegalArgumentException("type is null"); - return new AmsTask(null /* activity */, handler, callback) { - public void doWork() throws RemoteException { - mService.getAccountsByTypeAndFeatures(mResponse, type, features); + public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException { + if (!bundle.containsKey(Constants.BOOLEAN_RESULT_KEY)) { + throw new AuthenticatorException("no result in response"); + } + return bundle.getBoolean(Constants.BOOLEAN_RESULT_KEY); } }.start(); } - public Future2 confirmCredentials(final Account account, final Activity activity, - final Future2Callback callback, + public AccountManagerFuture getAccountsByTypeAndFeatures( + final String type, final String[] features, + AccountManagerCallback callback, Handler handler) { + if (type == null) throw new IllegalArgumentException("type is null"); + return new Future2Task(handler, callback) { + public void doWork() throws RemoteException { + mService.getAccountsByFeatures(mResponse, type, features); + } + public Account[] bundleToResult(Bundle bundle) throws AuthenticatorException { + if (!bundle.containsKey(Constants.ACCOUNTS_KEY)) { + throw new AuthenticatorException("no result in response"); + } + final Parcelable[] parcelables = bundle.getParcelableArray(Constants.ACCOUNTS_KEY); + Account[] descs = new Account[parcelables.length]; + for (int i = 0; i < parcelables.length; i++) { + descs[i] = (Account) parcelables[i]; + } + return descs; + } + }.start(); + } + + public AccountManagerFuture confirmCredentials(final Account account, final Activity activity, + final AccountManagerCallback callback, final Handler handler) { return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { @@ -435,9 +308,9 @@ public class AccountManager { }.start(); } - public Future2 updateCredentials(final Account account, final String authTokenType, + public AccountManagerFuture updateCredentials(final Account account, final String authTokenType, final Bundle loginOptions, final Activity activity, - final Future2Callback callback, + final AccountManagerCallback callback, final Handler handler) { return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { @@ -447,8 +320,8 @@ public class AccountManager { }.start(); } - public Future2 editProperties(final String accountType, final Activity activity, - final Future2Callback callback, + public AccountManagerFuture editProperties(final String accountType, final Activity activity, + final AccountManagerCallback callback, final Handler handler) { return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { @@ -471,8 +344,8 @@ public class AccountManager { } } - private void postToHandler(Handler handler, final Future2Callback callback, - final Future2 future) { + private void postToHandler(Handler handler, final AccountManagerCallback callback, + final AccountManagerFuture future) { handler = handler == null ? mMainHandler : handler; handler.post(new Runnable() { public void run() { @@ -483,87 +356,24 @@ public class AccountManager { private void postToHandler(Handler handler, final OnAccountsUpdatedListener listener, final Account[] accounts) { - handler = handler == null ? mMainHandler : handler; + final Account[] accountsCopy = new Account[accounts.length]; + // send a copy to make sure that one doesn't + // change what another sees + System.arraycopy(accounts, 0, accountsCopy, 0, accountsCopy.length); + handler = (handler == null) ? mMainHandler : handler; handler.post(new Runnable() { public void run() { - listener.onAccountsUpdated(accounts); + listener.onAccountsUpdated(accountsCopy); } }); } - private void postToHandler(Handler handler, final Future1Callback callback, - final Future1 future) { - handler = handler == null ? mMainHandler : handler; - handler.post(new Runnable() { - public void run() { - callback.run(future); - } - }); - } - - private Future1 startAsFuture(Future1Callback callback, Handler handler, - Callable callable) { - final FutureTaskWithCallback task = - new FutureTaskWithCallback(callback, callable, handler); - new Thread(task).start(); - return task; - } - - private class FutureTaskWithCallback extends FutureTask implements Future1 { - final Future1Callback mCallback; - final Handler mHandler; - - public FutureTaskWithCallback(Future1Callback callback, Callable callable, - Handler handler) { - super(callable); - mCallback = callback; - mHandler = handler; - } - - protected void done() { - if (mCallback != null) { - postToHandler(mHandler, mCallback, this); - } - } - - public V internalGetResult(Long timeout, TimeUnit unit) throws OperationCanceledException { - try { - if (timeout == null) { - return get(); - } else { - return get(timeout, unit); - } - } catch (InterruptedException e) { - // we will cancel the task below - } catch (CancellationException e) { - // we will cancel the task below - } catch (TimeoutException e) { - // we will cancel the task below - } catch (ExecutionException e) { - // this should never happen - throw new IllegalStateException(e.getCause()); - } finally { - cancel(true /* interruptIfRunning */); - } - throw new OperationCanceledException(); - } - - public V getResult() throws OperationCanceledException { - return internalGetResult(null, null); - } - - public V getResult(long timeout, TimeUnit unit) throws OperationCanceledException { - return internalGetResult(null, null); - } - } - - private abstract class AmsTask extends FutureTask implements Future2 { + private abstract class AmsTask extends FutureTask implements AccountManagerFuture { final IAccountManagerResponse mResponse; final Handler mHandler; - final Future2Callback mCallback; + final AccountManagerCallback mCallback; final Activity mActivity; - final Thread mThread; - public AmsTask(Activity activity, Handler handler, Future2Callback callback) { + public AmsTask(Activity activity, Handler handler, AccountManagerCallback callback) { super(new Callable() { public Bundle call() throws Exception { throw new IllegalStateException("this should never be called"); @@ -574,19 +384,14 @@ public class AccountManager { mCallback = callback; mActivity = activity; mResponse = new Response(); - mThread = new Thread(new Runnable() { - public void run() { - try { - doWork(); - } catch (RemoteException e) { - // never happens - } - } - }, "AmsTask"); } - public final Future2 start() { - mThread.start(); + public final AccountManagerFuture start() { + try { + doWork(); + } catch (RemoteException e) { + setException(e); + } return this; } @@ -594,6 +399,7 @@ public class AccountManager { private Bundle internalGetResult(Long timeout, TimeUnit unit) throws OperationCanceledException, IOException, AuthenticatorException { + ensureNotOnMainThread(); try { if (timeout == null) { return get(); @@ -676,92 +482,50 @@ public class AccountManager { } - private abstract class AMSTaskBoolean extends FutureTask implements Future1 { - final IAccountManagerResponse response; + private abstract class BaseFutureTask extends FutureTask { + final public IAccountManagerResponse mResponse; final Handler mHandler; - final Future1Callback mCallback; - public AMSTaskBoolean(Handler handler, Future1Callback callback) { - super(new Callable() { - public Boolean call() throws Exception { + + public BaseFutureTask(Handler handler) { + super(new Callable() { + public T call() throws Exception { throw new IllegalStateException("this should never be called"); } }); - mHandler = handler; - mCallback = callback; - response = new Response(); - - new Thread(new Runnable() { - public void run() { - try { - doWork(); - } catch (RemoteException e) { - // never happens - } - } - }).start(); + mResponse = new Response(); } public abstract void doWork() throws RemoteException; + public abstract T bundleToResult(Bundle bundle) throws AuthenticatorException; - protected void done() { - if (mCallback != null) { - postToHandler(mHandler, mCallback, this); - } + protected void postRunnableToHandler(Runnable runnable) { + Handler handler = (mHandler == null) ? mMainHandler : mHandler; + handler.post(runnable); } - private Boolean internalGetResult(Long timeout, TimeUnit unit) { + protected void startTask() { try { - if (timeout == null) { - return get(); - } else { - return get(timeout, unit); - } - } catch (InterruptedException e) { - // fall through and cancel - } catch (TimeoutException e) { - // fall through and cancel - } catch (CancellationException e) { - return false; - } catch (ExecutionException e) { - final Throwable cause = e.getCause(); - if (cause instanceof IOException) { - return false; - } else if (cause instanceof UnsupportedOperationException) { - return false; - } else if (cause instanceof AuthenticatorException) { - return false; - } else if (cause instanceof RuntimeException) { - throw (RuntimeException) cause; - } else if (cause instanceof Error) { - throw (Error) cause; - } else { - throw new IllegalStateException(cause); - } - } finally { - cancel(true /* interrupt if running */); + doWork(); + } catch (RemoteException e) { + setException(e); } - return false; } - public Boolean getResult() throws OperationCanceledException { - return internalGetResult(null, null); - } - - public Boolean getResult(long timeout, TimeUnit unit) throws OperationCanceledException { - return internalGetResult(timeout, unit); - } - - private class Response extends IAccountManagerResponse.Stub { + protected class Response extends IAccountManagerResponse.Stub { public void onResult(Bundle bundle) { try { - if (bundle.containsKey(Constants.BOOLEAN_RESULT_KEY)) { - set(bundle.getBoolean(Constants.BOOLEAN_RESULT_KEY)); + T result = bundleToResult(bundle); + if (result == null) { return; } + set(result); + return; } catch (ClassCastException e) { // we will set the exception below + } catch (AuthenticatorException e) { + // we will set the exception below } onError(Constants.ERROR_CODE_INVALID_RESPONSE, "no result in response"); } @@ -774,6 +538,76 @@ public class AccountManager { setException(convertErrorToException(code, message)); } } + } + + private abstract class Future2Task + extends BaseFutureTask implements AccountManagerFuture { + final AccountManagerCallback mCallback; + public Future2Task(Handler handler, AccountManagerCallback callback) { + super(handler); + mCallback = callback; + } + + protected void done() { + if (mCallback != null) { + postRunnableToHandler(new Runnable() { + public void run() { + mCallback.run(Future2Task.this); + } + }); + } + } + + public Future2Task start() { + startTask(); + return this; + } + + private T internalGetResult(Long timeout, TimeUnit unit) + throws OperationCanceledException, IOException, AuthenticatorException { + ensureNotOnMainThread(); + try { + if (timeout == null) { + return get(); + } else { + return get(timeout, unit); + } + } catch (InterruptedException e) { + // fall through and cancel + } catch (TimeoutException e) { + // fall through and cancel + } catch (CancellationException e) { + // fall through and cancel + } catch (ExecutionException e) { + final Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } else if (cause instanceof UnsupportedOperationException) { + throw new AuthenticatorException(cause); + } else if (cause instanceof AuthenticatorException) { + throw (AuthenticatorException) cause; + } else if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + throw new IllegalStateException(cause); + } + } finally { + cancel(true /* interrupt if running */); + } + throw new OperationCanceledException(); + } + + public T getResult() + throws OperationCanceledException, IOException, AuthenticatorException { + return internalGetResult(null, null); + } + + public T getResult(long timeout, TimeUnit unit) + throws OperationCanceledException, IOException, AuthenticatorException { + return internalGetResult(timeout, unit); + } } @@ -797,11 +631,12 @@ public class AccountManager { return new AuthenticatorException(message); } - private class GetAuthTokenByTypeAndFeaturesTask extends AmsTask implements Future2Callback { + private class GetAuthTokenByTypeAndFeaturesTask + extends AmsTask implements AccountManagerCallback { GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType, final String[] features, Activity activityForPrompting, final Bundle addAccountOptions, final Bundle loginOptions, - Future2Callback callback, Handler handler) { + AccountManagerCallback callback, Handler handler) { super(activityForPrompting, handler, callback); if (accountType == null) throw new IllegalArgumentException("account type is null"); mAccountType = accountType; @@ -811,101 +646,100 @@ public class AccountManager { mLoginOptions = loginOptions; mMyCallback = this; } - volatile Future2 mFuture = null; + volatile AccountManagerFuture mFuture = null; final String mAccountType; final String mAuthTokenType; final String[] mFeatures; final Bundle mAddAccountOptions; final Bundle mLoginOptions; - final Future2Callback mMyCallback; + final AccountManagerCallback mMyCallback; public void doWork() throws RemoteException { - getAccountsWithTypeAndFeatures(mAccountType, mFeatures, new Future2Callback() { - public void run(Future2 future) { - Bundle getAccountsResult; - try { - getAccountsResult = future.getResult(); - } catch (OperationCanceledException e) { - setException(e); - return; - } catch (IOException e) { - setException(e); - return; - } catch (AuthenticatorException e) { - setException(e); - return; - } - - Parcelable[] accounts = - getAccountsResult.getParcelableArray(Constants.ACCOUNTS_KEY); - if (accounts.length == 0) { - if (mActivity != null) { - // no accounts, add one now. pretend that the user directly - // made this request - mFuture = addAccount(mAccountType, mAuthTokenType, mFeatures, - mAddAccountOptions, mActivity, mMyCallback, mHandler); - } else { - // send result since we can't prompt to add an account - Bundle result = new Bundle(); - result.putString(Constants.ACCOUNT_NAME_KEY, null); - result.putString(Constants.ACCOUNT_TYPE_KEY, null); - result.putString(Constants.AUTHTOKEN_KEY, null); + getAccountsByTypeAndFeatures(mAccountType, mFeatures, + new AccountManagerCallback() { + public void run(AccountManagerFuture future) { + Account[] accounts; try { - mResponse.onResult(result); - } catch (RemoteException e) { - // this will never happen + accounts = future.getResult(); + } catch (OperationCanceledException e) { + setException(e); + return; + } catch (IOException e) { + setException(e); + return; + } catch (AuthenticatorException e) { + setException(e); + return; } - // we are done - } - } else if (accounts.length == 1) { - // have a single account, return an authtoken for it - if (mActivity == null) { - mFuture = getAuthToken((Account) accounts[0], mAuthTokenType, - false /* notifyAuthFailure */, mMyCallback, mHandler); - } else { - mFuture = getAuthToken((Account) accounts[0], - mAuthTokenType, mLoginOptions, - mActivity, mMyCallback, mHandler); - } - } else { - if (mActivity != null) { - IAccountManagerResponse chooseResponse = - new IAccountManagerResponse.Stub() { - public void onResult(Bundle value) throws RemoteException { - Account account = new Account( - value.getString(Constants.ACCOUNT_NAME_KEY), - value.getString(Constants.ACCOUNT_TYPE_KEY)); - mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions, + + if (accounts.length == 0) { + if (mActivity != null) { + // no accounts, add one now. pretend that the user directly + // made this request + mFuture = addAccount(mAccountType, mAuthTokenType, mFeatures, + mAddAccountOptions, mActivity, mMyCallback, mHandler); + } else { + // send result since we can't prompt to add an account + Bundle result = new Bundle(); + result.putString(Constants.ACCOUNT_NAME_KEY, null); + result.putString(Constants.ACCOUNT_TYPE_KEY, null); + result.putString(Constants.AUTHTOKEN_KEY, null); + try { + mResponse.onResult(result); + } catch (RemoteException e) { + // this will never happen + } + // we are done + } + } else if (accounts.length == 1) { + // have a single account, return an authtoken for it + if (mActivity == null) { + mFuture = getAuthToken(accounts[0], mAuthTokenType, + false /* notifyAuthFailure */, mMyCallback, mHandler); + } else { + mFuture = getAuthToken(accounts[0], + mAuthTokenType, mLoginOptions, mActivity, mMyCallback, mHandler); } + } else { + if (mActivity != null) { + IAccountManagerResponse chooseResponse = + new IAccountManagerResponse.Stub() { + public void onResult(Bundle value) throws RemoteException { + Account account = new Account( + value.getString(Constants.ACCOUNT_NAME_KEY), + value.getString(Constants.ACCOUNT_TYPE_KEY)); + mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions, + mActivity, mMyCallback, mHandler); + } - public void onError(int errorCode, String errorMessage) - throws RemoteException { - mResponse.onError(errorCode, errorMessage); + public void onError(int errorCode, String errorMessage) + throws RemoteException { + mResponse.onError(errorCode, errorMessage); + } + }; + // have many accounts, launch the chooser + Intent intent = new Intent(); + intent.setClassName("android", + "android.accounts.ChooseAccountActivity"); + intent.putExtra(Constants.ACCOUNTS_KEY, accounts); + intent.putExtra(Constants.ACCOUNT_MANAGER_RESPONSE_KEY, + 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(Constants.ACCOUNTS_KEY, null); + try { + mResponse.onResult(result); + } catch (RemoteException e) { + // this will never happen + } + // we are done } - }; - // have many accounts, launch the chooser - Intent intent = new Intent(); - intent.setClassName("android", - "android.accounts.ChooseAccountActivity"); - intent.putExtra(Constants.ACCOUNTS_KEY, accounts); - intent.putExtra(Constants.ACCOUNT_MANAGER_RESPONSE_KEY, - 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(Constants.ACCOUNTS_KEY, null); - try { - mResponse.onResult(result); - } catch (RemoteException e) { - // this will never happen } - // we are done - } - } - }}, mHandler); + }}, mHandler); } @@ -915,7 +749,7 @@ public class AccountManager { // or to cause this to be canceled if mFuture isn't set. // Once this is done then getAuthTokenByFeatures can be changed to return a Future2. - public void run(Future2 future) { + public void run(AccountManagerFuture future) { try { set(future.get()); } catch (InterruptedException e) { @@ -932,7 +766,7 @@ public class AccountManager { final String accountType, final String authTokenType, final String[] features, final Activity activityForPrompting, final Bundle addAccountOptions, final Bundle loginOptions, - final Future2Callback callback, final Handler handler) { + final AccountManagerCallback callback, final Handler handler) { if (accountType == null) throw new IllegalArgumentException("account type is null"); if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); new GetAuthTokenByTypeAndFeaturesTask(accountType, authTokenType, features, @@ -942,13 +776,6 @@ public class AccountManager { private final HashMap mAccountsUpdatedListeners = Maps.newHashMap(); - // These variable are only used from the LOGIN_ACCOUNTS_CHANGED_ACTION BroadcastReceiver - // and its getAccounts() callback which are both invoked only on the main thread. As a - // result we don't need to protect against concurrent accesses and any changes are guaranteed - // to be visible when used. Basically, these two variables are thread-confined. - private Future1 mAccountsLookupFuture = null; - private boolean mAccountLookupPending = false; - /** * 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 @@ -956,58 +783,14 @@ public class AccountManager { */ private final BroadcastReceiver mAccountsChangedBroadcastReceiver = new BroadcastReceiver() { public void onReceive(final Context context, final Intent intent) { - if (mAccountsLookupFuture != null) { - // an accounts lookup is already in progress, - // don't bother starting another request - mAccountLookupPending = true; - return; - } - // initiate a read of the accounts - mAccountsLookupFuture = getAccounts(new Future1Callback() { - public void run(Future1 future) { - // clear the future so that future receives will try the lookup again - mAccountsLookupFuture = null; - - // get the accounts array - Account[] accounts; - try { - accounts = future.getResult(); - } catch (OperationCanceledException e) { - // this should never happen, but if it does pretend we got another - // accounts changed broadcast - if (Config.LOGD) { - Log.d(TAG, "the accounts lookup for listener notifications was " - + "canceled, try again by simulating the receipt of " - + "a LOGIN_ACCOUNTS_CHANGED_ACTION broadcast"); - } - onReceive(context, intent); - return; - } - - // send the result to the listeners - synchronized (mAccountsUpdatedListeners) { - for (Map.Entry entry : - mAccountsUpdatedListeners.entrySet()) { - Account[] accountsCopy = new Account[accounts.length]; - // send the listeners a copy to make sure that one doesn't - // change what another sees - System.arraycopy(accounts, 0, accountsCopy, 0, accountsCopy.length); - postToHandler(entry.getValue(), entry.getKey(), accountsCopy); - } - } - - // If mAccountLookupPending was set when the account lookup finished it - // means that we had previously ignored a LOGIN_ACCOUNTS_CHANGED_ACTION - // intent because a lookup was already in progress. Now that we are done - // with this lookup and notification pretend that another intent - // was received by calling onReceive() directly. - if (mAccountLookupPending) { - mAccountLookupPending = false; - onReceive(context, intent); - return; - } + final Account[] accounts = getAccounts(); + // send the result to the listeners + synchronized (mAccountsUpdatedListeners) { + for (Map.Entry entry : + mAccountsUpdatedListeners.entrySet()) { + postToHandler(entry.getValue(), entry.getKey(), accounts); } - }, mMainHandler); + } } }; @@ -1045,15 +828,7 @@ public class AccountManager { } if (updateImmediately) { - getAccounts(new Future1Callback() { - public void run(Future1 future) { - try { - listener.onAccountsUpdated(future.getResult()); - } catch (OperationCanceledException e) { - // ignore - } - } - }, handler); + postToHandler(handler, listener, getAccounts()); } } diff --git a/core/java/android/accounts/Future1Callback.java b/core/java/android/accounts/AccountManagerCallback.java similarity index 87% rename from core/java/android/accounts/Future1Callback.java rename to core/java/android/accounts/AccountManagerCallback.java index 886671ba6b36b..4aa7169088c53 100644 --- a/core/java/android/accounts/Future1Callback.java +++ b/core/java/android/accounts/AccountManagerCallback.java @@ -15,6 +15,6 @@ */ package android.accounts; -public interface Future1Callback { - void run(Future1 future); -} +public interface AccountManagerCallback { + void run(AccountManagerFuture future); +} \ No newline at end of file diff --git a/core/java/android/accounts/AccountManagerFuture.java b/core/java/android/accounts/AccountManagerFuture.java new file mode 100644 index 0000000000000..99393987462ea --- /dev/null +++ b/core/java/android/accounts/AccountManagerFuture.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.accounts; + +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.io.IOException; + +/** + * An extension of {@link java.util.concurrent.Future} that provides wrappers for {@link #get()} + * that handle the various + * exceptions that {@link #get()} may return and rethrows them as exceptions specific to + * {@link android.accounts.AccountManager}. + */ +public interface AccountManagerFuture extends Future { + /** + * Wrapper for {@link java.util.concurrent.Future#get()}. If the get() throws + * {@link InterruptedException} then the + * {@link AccountManagerFuture} is canceled and + * {@link android.accounts.OperationCanceledException} is thrown. + * @return the {@link android.os.Bundle} that is returned by get() + * @throws android.accounts.OperationCanceledException if get() throws the unchecked + * CancellationException + * or if the Future was interrupted. + */ + V getResult() throws OperationCanceledException, IOException, AuthenticatorException; + + /** + * Wrapper for {@link java.util.concurrent.Future#get()}. If the get() throws + * {@link InterruptedException} then the + * {@link AccountManagerFuture} is canceled and + * {@link android.accounts.OperationCanceledException} is thrown. + * @param timeout the maximum time to wait + * @param unit the time unit of the timeout argument + * @return the {@link android.os.Bundle} that is returned by + * {@link java.util.concurrent.Future#get()} + * @throws android.accounts.OperationCanceledException if get() throws the unchecked + * {@link java.util.concurrent.CancellationException} or if the {@link AccountManagerFuture} + * was interrupted. + */ + V getResult(long timeout, TimeUnit unit) + throws OperationCanceledException, IOException, AuthenticatorException; + + @Deprecated + V get() throws InterruptedException, ExecutionException; + + @Deprecated + V get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException; +} \ No newline at end of file diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 0c941bea3837d..140c814394f61 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -214,10 +214,48 @@ public class AccountManagerService extends IAccountManager.Stub { long identityToken = clearCallingIdentity(); try { - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD}, - ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", - new String[]{account.mName, account.mType}, null, null, null); + return readPasswordFromDatabase(account); + } finally { + restoreCallingIdentity(identityToken); + } + } + + private String readPasswordFromDatabase(Account account) { + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD}, + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", + new String[]{account.name, account.type}, null, null, null); + try { + if (cursor.moveToNext()) { + return cursor.getString(0); + } + return null; + } finally { + cursor.close(); + } + } + + public String getUserData(Account account, String key) { + checkAuthenticateAccountsPermission(account); + long identityToken = clearCallingIdentity(); + try { + return readUserDataFromDatabase(account, key); + } finally { + restoreCallingIdentity(identityToken); + } + } + + private String readUserDataFromDatabase(Account account, String key) { + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + db.beginTransaction(); + try { + long accountId = getAccountId(db, account); + if (accountId < 0) { + return null; + } + Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE}, + EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?", + new String[]{key}, null, null, null); try { if (cursor.moveToNext()) { return cursor.getString(0); @@ -227,37 +265,7 @@ public class AccountManagerService extends IAccountManager.Stub { cursor.close(); } } finally { - restoreCallingIdentity(identityToken); - } - } - - public String getUserData(Account account, String key) { - checkAuthenticateAccountsPermission(account); - long identityToken = clearCallingIdentity(); - try { - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - db.beginTransaction(); - try { - long accountId = getAccountId(db, account); - if (accountId < 0) { - return null; - } - Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE}, - EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?", - new String[]{key}, null, null, null); - try { - if (cursor.moveToNext()) { - return cursor.getString(0); - } - return null; - } finally { - cursor.close(); - } - } finally { - db.endTransaction(); - } - } finally { - restoreCallingIdentity(identityToken); + db.endTransaction(); } } @@ -280,39 +288,23 @@ public class AccountManagerService extends IAccountManager.Stub { } } - public Account[] getAccounts() { - checkReadAccountsPermission(); - long identityToken = clearCallingIdentity(); - try { - return getAccountsByType(null); - } finally { - restoreCallingIdentity(identityToken); - } - } - public Account[] getAccountsByType(String accountType) { - checkReadAccountsPermission(); - long identityToken = clearCallingIdentity(); - try { - SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); - final String selection = accountType == null ? null : (ACCOUNTS_TYPE + "=?"); - final String[] selectionArgs = accountType == null ? null : new String[]{accountType}; - Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_NAME_TYPE_PROJECTION, - selection, selectionArgs, null, null, null); - try { - int i = 0; - Account[] accounts = new Account[cursor.getCount()]; - while (cursor.moveToNext()) { - accounts[i] = new Account(cursor.getString(1), cursor.getString(2)); - i++; - } - return accounts; - } finally { - cursor.close(); + final String selection = accountType == null ? null : (ACCOUNTS_TYPE + "=?"); + final String[] selectionArgs = accountType == null ? null : new String[]{accountType}; + Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_NAME_TYPE_PROJECTION, + selection, selectionArgs, null, null, null); + try { + int i = 0; + Account[] accounts = new Account[cursor.getCount()]; + while (cursor.moveToNext()) { + accounts[i] = new Account(cursor.getString(1), cursor.getString(2)); + i++; } + return accounts; } finally { - restoreCallingIdentity(identityToken); + cursor.close(); } } @@ -322,43 +314,47 @@ public class AccountManagerService extends IAccountManager.Stub { // fails if the account already exists long identityToken = clearCallingIdentity(); try { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - long numMatches = DatabaseUtils.longForQuery(db, - "select count(*) from " + TABLE_ACCOUNTS - + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", - new String[]{account.mName, account.mType}); - if (numMatches > 0) { - return false; - } - ContentValues values = new ContentValues(); - values.put(ACCOUNTS_NAME, account.mName); - values.put(ACCOUNTS_TYPE, account.mType); - values.put(ACCOUNTS_PASSWORD, password); - long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values); - if (accountId < 0) { - return false; - } - if (extras != null) { - for (String key : extras.keySet()) { - final String value = extras.getString(key); - if (insertExtra(db, accountId, key, value) < 0) { - return false; - } - } - } - db.setTransactionSuccessful(); - sendAccountsChangedBroadcast(); - return true; - } finally { - db.endTransaction(); - } + return insertAccountIntoDatabase(account, password, extras); } finally { restoreCallingIdentity(identityToken); } } + private boolean insertAccountIntoDatabase(Account account, String password, Bundle extras) { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + db.beginTransaction(); + try { + long numMatches = DatabaseUtils.longForQuery(db, + "select count(*) from " + TABLE_ACCOUNTS + + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", + new String[]{account.name, account.type}); + if (numMatches > 0) { + return false; + } + ContentValues values = new ContentValues(); + values.put(ACCOUNTS_NAME, account.name); + values.put(ACCOUNTS_TYPE, account.type); + values.put(ACCOUNTS_PASSWORD, password); + long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values); + if (accountId < 0) { + return false; + } + if (extras != null) { + for (String key : extras.keySet()) { + final String value = extras.getString(key); + if (insertExtra(db, accountId, key, value) < 0) { + return false; + } + } + } + db.setTransactionSuccessful(); + sendAccountsChangedBroadcast(); + return true; + } finally { + db.endTransaction(); + } + } + private long insertExtra(SQLiteDatabase db, long accountId, String key, String value) { ContentValues values = new ContentValues(); values.put(EXTRAS_KEY, key); @@ -367,19 +363,61 @@ public class AccountManagerService extends IAccountManager.Stub { return db.insert(TABLE_EXTRAS, EXTRAS_KEY, values); } - public void removeAccount(Account account) { + public void removeAccount(IAccountManagerResponse response, Account account) { checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { - final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", - new String[]{account.mName, account.mType}); - sendAccountsChangedBroadcast(); + new RemoveAccountSession(response, account).bind(); } finally { restoreCallingIdentity(identityToken); } } + private class RemoveAccountSession extends Session { + final Account mAccount; + public RemoveAccountSession(IAccountManagerResponse response, Account account) { + super(response, account.type, false /* expectActivityLaunch */); + mAccount = account; + } + + protected String toDebugString(long now) { + return super.toDebugString(now) + ", removeAccount" + + ", account " + mAccount; + } + + public void run() throws RemoteException { + mAuthenticator.getAccountRemovalAllowed(this, mAccount); + } + + public void onResult(Bundle result) { + if (result != null && result.containsKey(Constants.BOOLEAN_RESULT_KEY) + && !result.containsKey(Constants.INTENT_KEY)) { + final boolean removalAllowed = result.getBoolean(Constants.BOOLEAN_RESULT_KEY); + if (removalAllowed) { + removeAccount(mAccount); + } + IAccountManagerResponse response = getResponseAndClose(); + if (response != null) { + Bundle result2 = new Bundle(); + result2.putBoolean(Constants.BOOLEAN_RESULT_KEY, removalAllowed); + try { + response.onResult(result2); + } catch (RemoteException e) { + // ignore + } + } + } + super.onResult(result); + } + } + + private void removeAccount(Account account) { + final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", + new String[]{account.name, account.type}); + sendAccountsChangedBroadcast(); + } + public void invalidateAuthToken(String accountType, String authToken) { checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); @@ -398,6 +436,9 @@ public class AccountManagerService extends IAccountManager.Stub { } private void invalidateAuthToken(SQLiteDatabase db, String accountType, String authToken) { + if (authToken == null || accountType == null) { + return; + } Cursor cursor = db.rawQuery( "SELECT " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_ID + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_NAME @@ -488,7 +529,7 @@ public class AccountManagerService extends IAccountManager.Stub { values.put(ACCOUNTS_PASSWORD, password); mOpenHelper.getWritableDatabase().update(TABLE_ACCOUNTS, values, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", - new String[]{account.mName, account.mType}); + new String[]{account.name, account.type}); sendAccountsChangedBroadcast(); } finally { restoreCallingIdentity(identityToken); @@ -509,40 +550,58 @@ public class AccountManagerService extends IAccountManager.Stub { } } + private void sendResult(IAccountManagerResponse response, Bundle bundle) { + if (response != null) { + try { + response.onResult(bundle); + } catch (RemoteException e) { + // if the caller is dead then there is no one to care about remote + // exceptions + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "failure while notifying response", e); + } + } + } + } + public void setUserData(Account account, String key, String value) { checkAuthenticateAccountsPermission(account); long identityToken = clearCallingIdentity(); try { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - long accountId = getAccountId(db, account); - if (accountId < 0) { - return; - } - long extrasId = getExtrasId(db, accountId, key); - if (extrasId < 0 ) { - extrasId = insertExtra(db, accountId, key, value); - if (extrasId < 0) { - return; - } - } else { - ContentValues values = new ContentValues(); - values.put(EXTRAS_VALUE, value); - if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) { - return; - } - - } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } + writeUserdataIntoDatabase(account, key, value); } finally { restoreCallingIdentity(identityToken); } } + private void writeUserdataIntoDatabase(Account account, String key, String value) { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + db.beginTransaction(); + try { + long accountId = getAccountId(db, account); + if (accountId < 0) { + return; + } + long extrasId = getExtrasId(db, accountId, key); + if (extrasId < 0 ) { + extrasId = insertExtra(db, accountId, key, value); + if (extrasId < 0) { + return; + } + } else { + ContentValues values = new ContentValues(); + values.put(EXTRAS_VALUE, value); + if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) { + return; + } + + } + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + private void onResult(IAccountManagerResponse response, Bundle result) { try { response.onResult(result); @@ -571,14 +630,14 @@ public class AccountManagerService extends IAccountManager.Stub { if (authToken != null) { Bundle result = new Bundle(); result.putString(Constants.AUTHTOKEN_KEY, authToken); - result.putString(Constants.ACCOUNT_NAME_KEY, account.mName); - result.putString(Constants.ACCOUNT_TYPE_KEY, account.mType); + result.putString(Constants.ACCOUNT_NAME_KEY, account.name); + result.putString(Constants.ACCOUNT_TYPE_KEY, account.type); onResult(response, result); return; } } - new Session(response, account.mType, expectActivityLaunch) { + new Session(response, account.type, expectActivityLaunch) { protected String toDebugString(long now) { if (loginOptions != null) loginOptions.keySet(); return super.toDebugString(now) + ", getAuthToken" @@ -651,7 +710,7 @@ public class AccountManagerService extends IAccountManager.Stub { mContext.getText(R.string.permission_request_notification_subtitle); n.setLatestEventInfo(mContext, mContext.getText(R.string.permission_request_notification_title), - String.format(subtitleFormatString.toString(), account.mName), + String.format(subtitleFormatString.toString(), account.name), PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)); ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE)) .notify(getCredentialPermissionNotificationId(account, authTokenType, uid), n); @@ -661,9 +720,9 @@ public class AccountManagerService extends IAccountManager.Stub { AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) { RegisteredServicesCache.ServiceInfo serviceInfo = mAuthenticatorCache.getServiceInfo( - AuthenticatorDescription.newKey(account.mType)); + AuthenticatorDescription.newKey(account.type)); if (serviceInfo == null) { - throw new IllegalArgumentException("unknown account type: " + account.mType); + throw new IllegalArgumentException("unknown account type: " + account.type); } final Context authContext; @@ -671,7 +730,7 @@ public class AccountManagerService extends IAccountManager.Stub { authContext = mContext.createPackageContext( serviceInfo.type.packageName, 0); } catch (PackageManager.NameNotFoundException e) { - throw new IllegalArgumentException("unknown account type: " + account.mType); + throw new IllegalArgumentException("unknown account type: " + account.type); } Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class); @@ -750,7 +809,7 @@ public class AccountManagerService extends IAccountManager.Stub { checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { - new Session(response, account.mType, expectActivityLaunch) { + new Session(response, account.type, expectActivityLaunch) { public void run() throws RemoteException { mAuthenticator.confirmCredentials(this, account); } @@ -769,7 +828,7 @@ public class AccountManagerService extends IAccountManager.Stub { checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { - new Session(response, account.mType, false /* expectActivityLaunch */) { + new Session(response, account.type, false /* expectActivityLaunch */) { public void run() throws RemoteException { mAuthenticator.confirmPassword(this, account, password); } @@ -789,7 +848,7 @@ public class AccountManagerService extends IAccountManager.Stub { checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { - new Session(response, account.mType, expectActivityLaunch) { + new Session(response, account.type, expectActivityLaunch) { public void run() throws RemoteException { mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions); } @@ -898,10 +957,21 @@ public class AccountManagerService extends IAccountManager.Stub { + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null); } } - public void getAccountsByTypeAndFeatures(IAccountManagerResponse response, + + public Account[] getAccounts(String type) { + checkReadAccountsPermission(); + long identityToken = clearCallingIdentity(); + try { + return getAccountsByType(type); + } finally { + restoreCallingIdentity(identityToken); + } + } + + public void getAccountsByFeatures(IAccountManagerResponse response, String type, String[] features) { checkReadAccountsPermission(); - if (type == null) { + if (features != null && type == null) { if (response != null) { try { response.onError(Constants.ERROR_CODE_BAD_ARGUMENTS, "type is null"); @@ -913,6 +983,10 @@ public class AccountManagerService extends IAccountManager.Stub { } long identityToken = clearCallingIdentity(); try { + if (features == null || features.length == 0) { + getAccountsByType(type); + return; + } new GetAccountsByTypeAndFeatureSession(response, type, features).bind(); } finally { restoreCallingIdentity(identityToken); @@ -925,7 +999,7 @@ public class AccountManagerService extends IAccountManager.Stub { private long getAccountId(SQLiteDatabase db, Account account) { Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID}, - "name=? AND type=?", new String[]{account.mName, account.mType}, null, null, null); + "name=? AND type=?", new String[]{account.name, account.type}, null, null, null); try { if (cursor.moveToNext()) { return cursor.getLong(0); @@ -1401,7 +1475,7 @@ public class AccountManagerService extends IAccountManager.Stub { } private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) { - final boolean fromAuthenticator = hasAuthenticatorUid(account.mType, callerUid); + final boolean fromAuthenticator = hasAuthenticatorUid(account.type, callerUid); final boolean hasExplicitGrants = hasExplicitlyGrantedPermission(account, authTokenType); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid " @@ -1416,7 +1490,9 @@ public class AccountManagerService extends IAccountManager.Stub { for (RegisteredServicesCache.ServiceInfo serviceInfo : mAuthenticatorCache.getAllServices()) { if (serviceInfo.type.type.equals(accountType)) { - return serviceInfo.uid == callingUid; + return (serviceInfo.uid == callingUid) || + (mContext.getPackageManager().checkSignatures(serviceInfo.uid, callingUid) + == PackageManager.SIGNATURE_MATCH); } } return false; @@ -1428,7 +1504,7 @@ public class AccountManagerService extends IAccountManager.Stub { } SQLiteDatabase db = mOpenHelper.getReadableDatabase(); String[] args = {String.valueOf(Binder.getCallingUid()), authTokenType, - account.mName, account.mType}; + account.name, account.type}; final boolean permissionGranted = DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0; if (!permissionGranted && isDebuggableMonkeyBuild) { @@ -1444,7 +1520,7 @@ public class AccountManagerService extends IAccountManager.Stub { private void checkCallingUidAgainstAuthenticator(Account account) { final int uid = Binder.getCallingUid(); - if (!hasAuthenticatorUid(account.mType, uid)) { + if (!hasAuthenticatorUid(account.type, uid)) { String msg = "caller uid " + uid + " is different than the authenticator's uid"; Log.w(TAG, msg); throw new SecurityException(msg); diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java index 83377f352f0b1..bd6f2054e668d 100644 --- a/core/java/android/accounts/ChooseAccountActivity.java +++ b/core/java/android/accounts/ChooseAccountActivity.java @@ -45,7 +45,7 @@ public class ChooseAccountActivity extends ListActivity { String[] mAccountNames = new String[mAccounts.length]; for (int i = 0; i < mAccounts.length; i++) { - mAccountNames[i] = ((Account) mAccounts[i]).mName; + mAccountNames[i] = ((Account) mAccounts[i]).name; } // Use an existing ListAdapter that will map an array @@ -59,8 +59,8 @@ public class ChooseAccountActivity extends ListActivity { Account account = (Account) mAccounts[position]; Log.d(TAG, "selected account " + account); Bundle bundle = new Bundle(); - bundle.putString(Constants.ACCOUNT_NAME_KEY, account.mName); - bundle.putString(Constants.ACCOUNT_TYPE_KEY, account.mType); + bundle.putString(Constants.ACCOUNT_NAME_KEY, account.name); + bundle.putString(Constants.ACCOUNT_TYPE_KEY, account.type); mResult = bundle; finish(); } diff --git a/core/java/android/accounts/Constants.java b/core/java/android/accounts/Constants.java index da8173f5f47b7..8736f41216e8a 100644 --- a/core/java/android/accounts/Constants.java +++ b/core/java/android/accounts/Constants.java @@ -31,6 +31,7 @@ public class Constants { public static final String AUTHENTICATOR_TYPES_KEY = "authenticator_types"; public static final String USERDATA_KEY = "userdata"; public static final String AUTHTOKEN_KEY = "authtoken"; + public static final String PASSWORD_KEY = "password"; public static final String ACCOUNT_NAME_KEY = "authAccount"; public static final String ACCOUNT_TYPE_KEY = "accountType"; public static final String ERROR_CODE_KEY = "errorCode"; diff --git a/core/java/android/accounts/Future1.java b/core/java/android/accounts/Future1.java deleted file mode 100644 index 386cb6ec2ad06..0000000000000 --- a/core/java/android/accounts/Future1.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.accounts; - -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -/** - * An extension of {@link Future} that provides wrappers for {@link #get()} that handle the various - * exceptions that {@link #get()} may return and rethrows them as exceptions specific to - * {@link AccountManager}. - */ -public interface Future1 extends Future { - /** - * Wrapper for {@link Future#get()}. If the get() throws {@link InterruptedException} then the - * {@link Future1} is canceled and {@link OperationCanceledException} is thrown. - * @return the {@link android.os.Bundle} that is returned by get() - * @throws OperationCanceledException if get() throws the unchecked CancellationException - * or if the Future was interrupted. - */ - V getResult() throws OperationCanceledException; - - /** - * Wrapper for {@link Future#get()}. If the get() throws {@link InterruptedException} then the - * {@link Future1} is canceled and {@link OperationCanceledException} is thrown. - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return the {@link android.os.Bundle} that is returned by {@link Future#get()} - * @throws OperationCanceledException if get() throws the unchecked - * {@link java.util.concurrent.CancellationException} or if the {@link Future1} was interrupted. - */ - V getResult(long timeout, TimeUnit unit) throws OperationCanceledException; -} \ No newline at end of file diff --git a/core/java/android/accounts/Future2.java b/core/java/android/accounts/Future2.java deleted file mode 100644 index b2ea84f493060..0000000000000 --- a/core/java/android/accounts/Future2.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.accounts; - -import android.os.Bundle; - -import java.io.IOException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -/** - * An extension of {@link Future} that provides wrappers for {@link #get()} that handle the various - * exceptions that {@link #get()} may return and rethrows them as exceptions specific to - * {@link AccountManager}. - */ -public interface Future2 extends Future { - /** - * Wrapper for {@link Future#get()}. If the get() throws {@link InterruptedException} then the - * {@link Future2} is canceled and {@link OperationCanceledException} is thrown. - * @return the {@link android.os.Bundle} that is returned by {@link Future#get()} - * @throws OperationCanceledException if get() throws the unchecked - * {@link java.util.concurrent.CancellationException} or if the {@link Future2} was interrupted. - * @throws IOException if the request was unable to complete due to a network error - * @throws AuthenticatorException if there was an error communicating with the - * {@link AbstractAccountAuthenticator}. - */ - Bundle getResult() - throws OperationCanceledException, IOException, AuthenticatorException; - - /** - * Wrapper for {@link Future#get()}. If the get() throws {@link InterruptedException} then the - * {@link Future2} is canceled and {@link OperationCanceledException} is thrown. - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @return the {@link android.os.Bundle} that is returned by {@link Future#get()} - * @throws OperationCanceledException if get() throws the unchecked - * {@link java.util.concurrent.CancellationException} or if the {@link Future2} was interrupted. - * @throws IOException if the request was unable to complete due to a network error - * @throws AuthenticatorException if there was an error communicating with the - * {@link AbstractAccountAuthenticator}. - */ - Bundle getResult(long timeout, TimeUnit unit) - throws OperationCanceledException, IOException, AuthenticatorException; -} diff --git a/core/java/android/accounts/Future2Callback.java b/core/java/android/accounts/Future2Callback.java deleted file mode 100644 index 7ef0c94741d09..0000000000000 --- a/core/java/android/accounts/Future2Callback.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.accounts; - -public interface Future2Callback { - void run(Future2 future); -} \ No newline at end of file diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java index f92d43f68e9bc..e06afb4d5948d 100644 --- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java +++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java @@ -63,12 +63,12 @@ public class GrantCredentialsPermissionActivity extends Activity implements View CharSequence grantCredentialsPermissionFormat = getResources().getText( R.string.grant_credentials_permission_message_desc); messageView.setText(String.format(grantCredentialsPermissionFormat.toString(), - mAccount.mName, accountTypeLabel)); + mAccount.name, accountTypeLabel)); } else { CharSequence grantCredentialsPermissionFormat = getResources().getText( R.string.grant_credentials_permission_message_with_authtokenlabel_desc); messageView.setText(String.format(grantCredentialsPermissionFormat.toString(), - authTokenLabel, mAccount.mName, accountTypeLabel)); + authTokenLabel, mAccount.name, accountTypeLabel)); } String[] packageLabels = new String[packages.length]; diff --git a/core/java/android/accounts/IAccountAuthenticator.aidl b/core/java/android/accounts/IAccountAuthenticator.aidl index 7d4de392b6ef6..48f053c2ef649 100644 --- a/core/java/android/accounts/IAccountAuthenticator.aidl +++ b/core/java/android/accounts/IAccountAuthenticator.aidl @@ -70,4 +70,9 @@ oneway interface IAccountAuthenticator { */ void hasFeatures(in IAccountAuthenticatorResponse response, in Account account, in String[] features); + + /** + * Gets whether or not the account is allowed to be removed. + */ + void getAccountRemovalAllowed(in IAccountAuthenticatorResponse response, in Account account); } diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index 15ab4e822c505..411952b2664a4 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -21,6 +21,7 @@ import android.accounts.Account; import android.accounts.AuthenticatorDescription; import android.os.Bundle; + /** * Central application service that provides account management. * @hide @@ -29,10 +30,10 @@ interface IAccountManager { String getPassword(in Account account); String getUserData(in Account account, String key); AuthenticatorDescription[] getAuthenticatorTypes(); - Account[] getAccounts(); - Account[] getAccountsByType(String accountType); + Account[] getAccounts(String accountType); + void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features); boolean addAccount(in Account account, String password, in Bundle extras); - void removeAccount(in Account account); + void removeAccount(in IAccountManagerResponse response, 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); @@ -52,8 +53,6 @@ interface IAccountManager { boolean expectActivityLaunch); void confirmCredentials(in IAccountManagerResponse response, in Account account, boolean expectActivityLaunch); - void getAccountsByTypeAndFeatures(in IAccountManagerResponse response, String accountType, - in String[] features); /* * @deprecated diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java index 218f501ae92d2..808f30ce9bb1c 100644 --- a/core/java/android/content/AbstractSyncableContentProvider.java +++ b/core/java/android/content/AbstractSyncableContentProvider.java @@ -170,7 +170,7 @@ public abstract class AbstractSyncableContentProvider extends SyncableContentPro // AbstractGDataSyncAdapter, which will put acore into a crash loop ArrayList gaiaAccounts = new ArrayList(); for (Account acct: accounts) { - if (acct.mType.equals("com.google.GAIA")) { + if (acct.type.equals("com.google.GAIA")) { gaiaAccounts.add(acct); } } @@ -693,7 +693,7 @@ public abstract class AbstractSyncableContentProvider extends SyncableContentPro if (!accounts.containsKey(account)) { int numDeleted; numDeleted = db.delete(table, "_sync_account=? AND _sync_account_type=?", - new String[]{account.mName, account.mType}); + new String[]{account.name, account.type}); if (Config.LOGV) { Log.v(TAG, "deleted " + numDeleted + " records from table " + table @@ -726,7 +726,7 @@ public abstract class AbstractSyncableContentProvider extends SyncableContentPro // remove the data in the synced tables for (String table : tables) { db.delete(table, SYNC_ACCOUNT_WHERE_CLAUSE, - new String[]{account.mName, account.mType}); + new String[]{account.name, account.type}); } db.setTransactionSuccessful(); } finally { diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java index a3daa01e8317f..9545fd7f1a74b 100644 --- a/core/java/android/content/AbstractTableMerger.java +++ b/core/java/android/content/AbstractTableMerger.java @@ -174,7 +174,7 @@ public abstract class AbstractTableMerger Cursor diffsCursor = null; try { // load the local database entries, so we can merge them with the server - final String[] accountSelectionArgs = new String[]{account.mName, account.mType}; + final String[] accountSelectionArgs = new String[]{account.name, account.type}; localCursor = mDb.query(mTable, syncDirtyProjection, SELECT_MARKED, accountSelectionArgs, null, null, mTable + "." + _SYNC_ID); @@ -487,7 +487,7 @@ public abstract class AbstractTableMerger try { if (deleteBySyncId) { selectionArgs = new String[]{diffsCursor.getString(serverSyncIdColumn), - account.mName, account.mType}; + account.name, account.type}; c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_SYNC_ID_AND_ACCOUNT, selectionArgs, null, null, null); } else { @@ -534,7 +534,7 @@ public abstract class AbstractTableMerger SyncableContentProvider clientDiffs = mergeResult.tempContentProvider; if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client updates"); - final String[] accountSelectionArgs = new String[]{account.mName, account.mType}; + final String[] accountSelectionArgs = new String[]{account.name, account.type}; // Generate the client updates and insertions // Create a cursor for dirty records diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index d54e26091d24b..f25639496186f 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -596,7 +596,7 @@ class SyncManager implements OnAccountsUpdatedListener { for (String authority : syncableAuthorities) { for (Account account : accounts) { - if (mSyncAdapters.getServiceInfo(new SyncAdapterType(authority, account.mType)) + if (mSyncAdapters.getServiceInfo(new SyncAdapterType(authority, account.type)) != null) { scheduleSyncOperation( new SyncOperation(account, source, authority, extras, delay)); @@ -1094,8 +1094,8 @@ class SyncManager implements OnAccountsUpdatedListener { for (int i=0; i syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType); if (syncAdapterInfo == null) { diff --git a/core/java/android/content/SyncStateContentProviderHelper.java b/core/java/android/content/SyncStateContentProviderHelper.java index dc728eccf3d43..64bbe25cefb0e 100644 --- a/core/java/android/content/SyncStateContentProviderHelper.java +++ b/core/java/android/content/SyncStateContentProviderHelper.java @@ -172,7 +172,7 @@ public class SyncStateContentProviderHelper { */ public void copySyncState(SQLiteDatabase dbSrc, SQLiteDatabase dbDest, Account account) { - final String[] whereArgs = new String[]{account.mName, account.mType}; + final String[] whereArgs = new String[]{account.name, account.type}; Cursor c = dbSrc.query(SYNC_STATE_TABLE, new String[]{"_sync_account", "_sync_account_type", "data"}, ACCOUNT_WHERE, whereArgs, null, null, null); @@ -209,7 +209,7 @@ public class SyncStateContentProviderHelper { public void discardSyncData(SQLiteDatabase db, Account account) { if (account != null) { - db.delete(SYNC_STATE_TABLE, ACCOUNT_WHERE, new String[]{account.mName, account.mType}); + db.delete(SYNC_STATE_TABLE, ACCOUNT_WHERE, new String[]{account.name, account.type}); } else { db.delete(SYNC_STATE_TABLE, null, null); } @@ -220,7 +220,7 @@ public class SyncStateContentProviderHelper { */ public byte[] readSyncDataBytes(SQLiteDatabase db, Account account) { Cursor c = db.query(SYNC_STATE_TABLE, null, ACCOUNT_WHERE, - new String[]{account.mName, account.mType}, null, null, null); + new String[]{account.name, account.type}, null, null, null); try { if (c.moveToFirst()) { return c.getBlob(c.getColumnIndexOrThrow("data")); @@ -238,6 +238,6 @@ public class SyncStateContentProviderHelper { ContentValues values = new ContentValues(); values.put("data", data); db.update(SYNC_STATE_TABLE, values, ACCOUNT_WHERE, - new String[]{account.mName, account.mType}); + new String[]{account.name, account.type}); } } diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index 8cc06426c5997..b3f9bbbb520f9 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -1127,8 +1127,8 @@ public class SyncStorageEngine extends Handler { AuthorityInfo authority = mAuthorities.get(i); out.startTag(null, "authority"); out.attribute(null, "id", Integer.toString(authority.ident)); - out.attribute(null, "account", authority.account.mName); - out.attribute(null, "type", authority.account.mType); + out.attribute(null, "account", authority.account.name); + out.attribute(null, "type", authority.account.type); out.attribute(null, "authority", authority.authority); if (!authority.enabled) { out.attribute(null, "enabled", "false"); diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java index 489d936dab86c..fab3f3d034f7f 100644 --- a/core/java/android/provider/Calendar.java +++ b/core/java/android/provider/Calendar.java @@ -174,7 +174,7 @@ public final class Calendar { return Calendar.Calendars.delete(cr, Calendar.Calendars._SYNC_ACCOUNT + "=? AND " + Calendar.Calendars._SYNC_ACCOUNT_TYPE + "=?", - new String[] {account.mName, account.mType}); + new String[] {account.name, account.type}); } /** diff --git a/core/java/android/provider/SubscribedFeeds.java b/core/java/android/provider/SubscribedFeeds.java index f94b4427bd283..8e9f4021c934f 100644 --- a/core/java/android/provider/SubscribedFeeds.java +++ b/core/java/android/provider/SubscribedFeeds.java @@ -119,8 +119,8 @@ public class SubscribedFeeds { String authority, String service) { ContentValues values = new ContentValues(); values.put(SubscribedFeeds.Feeds.FEED, feed); - values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT, account.mName); - values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE, account.mType); + values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT, account.name); + values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE, account.type); values.put(SubscribedFeeds.Feeds.AUTHORITY, authority); values.put(SubscribedFeeds.Feeds.SERVICE, service); return resolver.insert(SubscribedFeeds.Feeds.CONTENT_URI, values); @@ -134,7 +134,7 @@ public class SubscribedFeeds { where.append(" AND " + SubscribedFeeds.Feeds.FEED + "=?"); where.append(" AND " + SubscribedFeeds.Feeds.AUTHORITY + "=?"); return resolver.delete(SubscribedFeeds.Feeds.CONTENT_URI, - where.toString(), new String[] {account.mName, account.mType, feed, authority}); + where.toString(), new String[] {account.name, account.type, feed, authority}); } public static int deleteFeeds(ContentResolver resolver, @@ -144,7 +144,7 @@ public class SubscribedFeeds { where.append(" AND " + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "=?"); where.append(" AND " + SubscribedFeeds.Feeds.AUTHORITY + "=?"); return resolver.delete(SubscribedFeeds.Feeds.CONTENT_URI, - where.toString(), new String[] {account.mName, account.mType, authority}); + where.toString(), new String[] {account.name, account.type, authority}); } /** diff --git a/core/java/android/provider/SyncStateContract.java b/core/java/android/provider/SyncStateContract.java index 7927e286ebca2..5c93af046321c 100644 --- a/core/java/android/provider/SyncStateContract.java +++ b/core/java/android/provider/SyncStateContract.java @@ -71,7 +71,7 @@ public class SyncStateContract { public static byte[] get(ContentProviderClient provider, Uri uri, Account account) throws RemoteException { Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT, - new String[]{account.mName, account.mType}, null); + new String[]{account.name, account.type}, null); try { if (c.moveToNext()) { return c.getBlob(c.getColumnIndexOrThrow(Columns.DATA)); @@ -96,8 +96,8 @@ public class SyncStateContract { Account account, byte[] data) throws RemoteException { ContentValues values = new ContentValues(); values.put(Columns.DATA, data); - values.put(Columns.ACCOUNT_NAME, account.mName); - values.put(Columns.ACCOUNT_TYPE, account.mType); + values.put(Columns.ACCOUNT_NAME, account.name); + values.put(Columns.ACCOUNT_TYPE, account.type); provider.insert(uri, values); } @@ -116,8 +116,8 @@ public class SyncStateContract { values.put(Columns.DATA, data); return ContentProviderOperation .newInsert(uri) - .withValue(Columns.ACCOUNT_NAME, account.mName) - .withValue(Columns.ACCOUNT_TYPE, account.mType) + .withValue(Columns.ACCOUNT_NAME, account.name) + .withValue(Columns.ACCOUNT_TYPE, account.type) .withValues(values) .build(); } diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java index 3cd2cc4a00cc4..b854f869aba53 100644 --- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java +++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java @@ -113,7 +113,7 @@ public class SubscribedFeedsIntentService extends IntentService { // TODO(fredq) fix the hardcoded type final Account account = new Account(accountName, "com.google.GAIA"); c = context.getContentResolver().query(SubscribedFeeds.Feeds.CONTENT_URI, - null, where, new String[]{account.mName, account.mType, feed}, null); + null, where, new String[]{account.name, account.type, feed}, null); if (c.getCount() == 0) { Log.w(TAG, "received tickle for non-existent feed: " + "account " + accountName + ", feed " + feed); @@ -171,12 +171,12 @@ public class SubscribedFeedsIntentService extends IntentService { try { ContentValues values = new ContentValues(); for (Account account : accounts) { - values.put(SyncConstValue._SYNC_ACCOUNT, account.mName); - values.put(SyncConstValue._SYNC_ACCOUNT_TYPE, account.mType); + values.put(SyncConstValue._SYNC_ACCOUNT, account.name); + values.put(SyncConstValue._SYNC_ACCOUNT_TYPE, account.type); contentResolver.update(SubscribedFeeds.Feeds.CONTENT_URI, values, SubscribedFeeds.Feeds._SYNC_ACCOUNT + "=? AND " + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "=?", - new String[] {account.mName, account.mType}); + new String[] {account.name, account.type}); } } catch (SQLiteFullException e) { Log.w(TAG, "disk full while trying to mark the feeds as dirty, skipping"); diff --git a/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java b/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java index 6b8e1f0bc7bc4..1e4f161d9f60c 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java @@ -28,7 +28,6 @@ import android.os.Bundle; import java.util.Arrays; import java.util.Comparator; -import java.util.Map; public class AccountManagerServiceTest extends AndroidTestCase { @Override @@ -48,9 +47,9 @@ public class AccountManagerServiceTest extends AndroidTestCase { if (object1 == object2) return 0; if (object1 == null) return 1; if (object2 == null) return -1; - int result = object1.mType.compareTo(object2.mType); + int result = object1.type.compareTo(object2.type); if (result != 0) return result; - return object1.mName.compareTo(object2.mName); + return object1.name.compareTo(object2.name); } } @@ -62,16 +61,14 @@ public class AccountManagerServiceTest extends AndroidTestCase { Account a12 = new Account("account1", "type2"); Account a22 = new Account("account2", "type2"); Account a32 = new Account("account3", "type2"); - assertTrue(ams.addAccount(a11, "p11", null)); - assertTrue(ams.addAccount(a12, "p12", null)); - assertTrue(ams.addAccount(a21, "p21", null)); - assertTrue(ams.addAccount(a22, "p22", null)); - assertTrue(ams.addAccount(a31, "p31", null)); - assertTrue(ams.addAccount(a32, "p32", null)); + ams.addAccount(a11, "p11", null); + ams.addAccount(a12, "p12", null); + ams.addAccount(a21, "p21", null); + ams.addAccount(a22, "p22", null); + ams.addAccount(a31, "p31", null); + ams.addAccount(a32, "p32", null); - assertFalse("duplicate account insertion should fail", ams.addAccount(a32, "p", null)); - - Account[] accounts = ams.getAccounts(); + Account[] accounts = ams.getAccounts(null); Arrays.sort(accounts, new AccountSorter()); assertEquals(6, accounts.length); assertEquals(a11, accounts[0]); @@ -88,7 +85,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { assertEquals(a21, accounts[1]); assertEquals(a31, accounts[2]); - ams.removeAccount(a21); + ams.removeAccount(null, a21); accounts = ams.getAccountsByType("type1" ); Arrays.sort(accounts, new AccountSorter()); @@ -101,8 +98,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { AccountManagerService ams = new AccountManagerService(getContext()); Account a11 = new Account("account1", "type1"); Account a12 = new Account("account1", "type2"); - assertTrue(ams.addAccount(a11, "p11", null)); - assertTrue(ams.addAccount(a12, "p12", null)); + ams.addAccount(a11, "p11", null); + ams.addAccount(a12, "p12", null); assertEquals("p11", ams.getPassword(a11)); assertEquals("p12", ams.getPassword(a12)); @@ -125,8 +122,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { u12.putString("a", "a_a12"); u12.putString("b", "b_a12"); u12.putString("c", "c_a12"); - assertTrue(ams.addAccount(a11, "p11", u11)); - assertTrue(ams.addAccount(a12, "p12", u12)); + ams.addAccount(a11, "p11", u11); + ams.addAccount(a12, "p12", u12); assertEquals("a_a11", ams.getUserData(a11, "a")); assertEquals("b_a11", ams.getUserData(a11, "b")); @@ -149,8 +146,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { AccountManagerService ams = new AccountManagerService(getContext()); Account a11 = new Account("account1", "type1"); Account a12 = new Account("account1", "type2"); - assertTrue(ams.addAccount(a11, "p11", null)); - assertTrue(ams.addAccount(a12, "p12", null)); + ams.addAccount(a11, "p11", null); + ams.addAccount(a12, "p12", null); ams.setAuthToken(a11, "att1", "a11_att1"); ams.setAuthToken(a11, "att2", "a11_att2"); @@ -167,7 +164,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { assertEquals("a12_att3", ams.peekAuthToken(a12, "att3")); ams.setAuthToken(a11, "att3", "a11_att3b"); - ams.invalidateAuthToken(a12.mType, "a12_att2"); + ams.invalidateAuthToken(a12.type, "a12_att2"); assertEquals("a11_att1", ams.peekAuthToken(a11, "att1")); assertEquals("a11_att2", ams.peekAuthToken(a11, "att2")); diff --git a/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java b/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java index 42c1e789b9c31..a8af7f83a16d9 100644 --- a/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java +++ b/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java @@ -74,8 +74,8 @@ public class AbstractTableMergerTest extends AndroidTestCase { if (syncVersion != null) values.put("_sync_version", syncVersion); if (syncId != null) values.put("_sync_id", syncId); if (syncAccount != null) { - values.put("_sync_account", syncAccount.mName); - values.put("_sync_account_type", syncAccount.mType); + values.put("_sync_account", syncAccount.name); + values.put("_sync_account_type", syncAccount.type); } values.put("_sync_local_id", syncLocalId); values.put("_sync_dirty", 0); @@ -88,8 +88,8 @@ public class AbstractTableMergerTest extends AndroidTestCase { if (syncVersion != null) values.put("_sync_version", syncVersion); if (syncId != null) values.put("_sync_id", syncId); if (syncAccount != null) { - values.put("_sync_account", syncAccount.mName); - values.put("_sync_account_type", syncAccount.mType); + values.put("_sync_account", syncAccount.name); + values.put("_sync_account_type", syncAccount.type); } if (syncLocalId != null) values.put("_sync_local_id", syncLocalId); return values;