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:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user