am 22dc3b7b: New AccountManager method to copy accounts between users.

* commit '22dc3b7ba111e27bce99a7cce966598e7873508c':
  New AccountManager method to copy accounts between users.
This commit is contained in:
Esteban Talavera
2014-11-14 11:37:33 +00:00
committed by Android Git Automerger
3 changed files with 70 additions and 29 deletions

View File

@@ -1442,6 +1442,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.

View File

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

View File

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