summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/accounts/AccountManager.java34
-rw-r--r--core/java/android/accounts/IAccountManager.aidl2
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java63
3 files changed, 70 insertions, 29 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 64c2fd0..6957435 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -1443,6 +1443,40 @@ public class AccountManager {
}
/**
+ * Copies an account from the primary user to another user.
+ * @param account the account to copy
+ * @param user the target user
+ * @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 Boolean indicated wether it
+ * succeeded.
+ * @hide
+ */
+ public AccountManagerFuture<Boolean> copyAccountToUser(
+ final Account account, final UserHandle user,
+ AccountManagerCallback<Boolean> callback, Handler handler) {
+ if (account == null) throw new IllegalArgumentException("account is null");
+ if (user == null) throw new IllegalArgumentException("user is null");
+
+ return new Future2Task<Boolean>(handler, callback) {
+ @Override
+ public void doWork() throws RemoteException {
+ mService.copyAccountToUser(
+ mResponse, account, UserHandle.USER_OWNER, user.getIdentifier());
+ }
+ @Override
+ public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
+ if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
+ throw new AuthenticatorException("no result in response");
+ }
+ return bundle.getBoolean(KEY_BOOLEAN_RESULT);
+ }
+ }.start();
+ }
+
+ /**
* @hide
* Removes the shared account.
* @param account the account to remove
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index bc75b9b..aa41161 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -42,6 +42,8 @@ interface IAccountManager {
void removeAccountAsUser(in IAccountManagerResponse response, in Account account,
boolean expectActivityLaunch, int userId);
boolean removeAccountExplicitly(in Account account);
+ void copyAccountToUser(in IAccountManagerResponse response, in Account account,
+ int userFrom, int userTo);
void invalidateAuthToken(String accountType, String authToken);
String peekAuthToken(in Account account, String authTokenType);
void setAuthToken(in Account account, String authTokenType, String authToken);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 85eed85..a2f4d56 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -486,7 +486,7 @@ public class AccountManagerService
for (Account sa : sharedAccounts) {
if (ArrayUtils.contains(accounts, sa)) continue;
// Account doesn't exist. Copy it now.
- copyAccountToUser(sa, UserHandle.USER_OWNER, userId);
+ copyAccountToUser(null /*no response*/, sa, UserHandle.USER_OWNER, userId);
}
}
@@ -672,16 +672,31 @@ public class AccountManagerService
}
}
- private boolean copyAccountToUser(final Account account, int userFrom, int userTo) {
+ @Override
+ public void copyAccountToUser(final IAccountManagerResponse response, final Account account,
+ int userFrom, int userTo) {
+ enforceCrossUserPermission(UserHandle.USER_ALL, "Calling copyAccountToUser requires "
+ + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
final UserAccounts fromAccounts = getUserAccounts(userFrom);
final UserAccounts toAccounts = getUserAccounts(userTo);
if (fromAccounts == null || toAccounts == null) {
- return false;
+ if (response != null) {
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
+ try {
+ response.onResult(result);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to report error back to the client." + e);
+ }
+ }
+ return;
}
+ Slog.d(TAG, "Copying account " + account.name
+ + " from user " + userFrom + " to user " + userTo);
long identityToken = clearCallingIdentity();
try {
- new Session(fromAccounts, null, account.type, false,
+ new Session(fromAccounts, response, account.type, false,
false /* stripAuthTokenFromResult */) {
@Override
protected String toDebugString(long now) {
@@ -696,12 +711,10 @@ public class AccountManagerService
@Override
public void onResult(Bundle result) {
- if (result != null) {
- if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
- // Create a Session for the target user and pass in the bundle
- completeCloningAccount(result, account, toAccounts);
- }
- return;
+ if (result != null
+ && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
+ // Create a Session for the target user and pass in the bundle
+ completeCloningAccount(response, result, account, toAccounts);
} else {
super.onResult(result);
}
@@ -710,14 +723,13 @@ public class AccountManagerService
} finally {
restoreCallingIdentity(identityToken);
}
- return true;
}
- void completeCloningAccount(final Bundle result, final Account account,
- final UserAccounts targetUser) {
+ private void completeCloningAccount(IAccountManagerResponse response,
+ final Bundle accountCredentials, final Account account, final UserAccounts targetUser) {
long id = clearCallingIdentity();
try {
- new Session(targetUser, null, account.type, false,
+ new Session(targetUser, response, account.type, false,
false /* stripAuthTokenFromResult */) {
@Override
protected String toDebugString(long now) {
@@ -730,10 +742,10 @@ public class AccountManagerService
// Confirm that the owner's account still exists before this step.
UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER);
synchronized (owner.cacheLock) {
- Account[] ownerAccounts = getAccounts(UserHandle.USER_OWNER);
- for (Account acc : ownerAccounts) {
+ for (Account acc : getAccounts(UserHandle.USER_OWNER)) {
if (acc.equals(account)) {
- mAuthenticator.addAccountFromCredentials(this, account, result);
+ mAuthenticator.addAccountFromCredentials(
+ this, account, accountCredentials);
break;
}
}
@@ -742,17 +754,10 @@ public class AccountManagerService
@Override
public void onResult(Bundle result) {
- if (result != null) {
- if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
- // TODO: Anything?
- } else {
- // TODO: Show error notification
- // TODO: Should we remove the shadow account to avoid retries?
- }
- return;
- } else {
- super.onResult(result);
- }
+ // TODO: Anything to do if if succedded?
+ // TODO: If it failed: Show error notification? Should we remove the shadow
+ // account to avoid retries?
+ super.onResult(result);
}
@Override
@@ -2740,7 +2745,7 @@ public class AccountManagerService
break;
case MESSAGE_COPY_SHARED_ACCOUNT:
- copyAccountToUser((Account) msg.obj, msg.arg1, msg.arg2);
+ copyAccountToUser(/*no response*/ null, (Account) msg.obj, msg.arg1, msg.arg2);
break;
default: