* commit '95162ad2eaa45cf2643b564c7fd03bfe0e4844de': 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
|
* @hide
|
||||||
* Removes the shared account.
|
* Removes the shared account.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ interface IAccountManager {
|
|||||||
void removeAccountAsUser(in IAccountManagerResponse response, in Account account,
|
void removeAccountAsUser(in IAccountManagerResponse response, in Account account,
|
||||||
boolean expectActivityLaunch, int userId);
|
boolean expectActivityLaunch, int userId);
|
||||||
boolean removeAccountExplicitly(in Account account);
|
boolean removeAccountExplicitly(in Account account);
|
||||||
|
void copyAccountToUser(in IAccountManagerResponse response, in Account account,
|
||||||
|
int userFrom, int userTo);
|
||||||
void invalidateAuthToken(String accountType, String authToken);
|
void invalidateAuthToken(String accountType, String authToken);
|
||||||
String peekAuthToken(in Account account, String authTokenType);
|
String peekAuthToken(in Account account, String authTokenType);
|
||||||
void setAuthToken(in Account account, String authTokenType, String authToken);
|
void setAuthToken(in Account account, String authTokenType, String authToken);
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ public class AccountManagerService
|
|||||||
for (Account sa : sharedAccounts) {
|
for (Account sa : sharedAccounts) {
|
||||||
if (ArrayUtils.contains(accounts, sa)) continue;
|
if (ArrayUtils.contains(accounts, sa)) continue;
|
||||||
// Account doesn't exist. Copy it now.
|
// 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 fromAccounts = getUserAccounts(userFrom);
|
||||||
final UserAccounts toAccounts = getUserAccounts(userTo);
|
final UserAccounts toAccounts = getUserAccounts(userTo);
|
||||||
if (fromAccounts == null || toAccounts == null) {
|
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();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
new Session(fromAccounts, null, account.type, false,
|
new Session(fromAccounts, response, account.type, false,
|
||||||
false /* stripAuthTokenFromResult */) {
|
false /* stripAuthTokenFromResult */) {
|
||||||
@Override
|
@Override
|
||||||
protected String toDebugString(long now) {
|
protected String toDebugString(long now) {
|
||||||
@@ -696,12 +711,10 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResult(Bundle result) {
|
public void onResult(Bundle result) {
|
||||||
if (result != null) {
|
if (result != null
|
||||||
if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
|
&& result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
|
||||||
// Create a Session for the target user and pass in the bundle
|
// Create a Session for the target user and pass in the bundle
|
||||||
completeCloningAccount(result, account, toAccounts);
|
completeCloningAccount(response, result, account, toAccounts);
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
super.onResult(result);
|
super.onResult(result);
|
||||||
}
|
}
|
||||||
@@ -710,14 +723,13 @@ public class AccountManagerService
|
|||||||
} finally {
|
} finally {
|
||||||
restoreCallingIdentity(identityToken);
|
restoreCallingIdentity(identityToken);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void completeCloningAccount(final Bundle result, final Account account,
|
private void completeCloningAccount(IAccountManagerResponse response,
|
||||||
final UserAccounts targetUser) {
|
final Bundle accountCredentials, final Account account, final UserAccounts targetUser) {
|
||||||
long id = clearCallingIdentity();
|
long id = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
new Session(targetUser, null, account.type, false,
|
new Session(targetUser, response, account.type, false,
|
||||||
false /* stripAuthTokenFromResult */) {
|
false /* stripAuthTokenFromResult */) {
|
||||||
@Override
|
@Override
|
||||||
protected String toDebugString(long now) {
|
protected String toDebugString(long now) {
|
||||||
@@ -730,10 +742,10 @@ public class AccountManagerService
|
|||||||
// Confirm that the owner's account still exists before this step.
|
// Confirm that the owner's account still exists before this step.
|
||||||
UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER);
|
UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER);
|
||||||
synchronized (owner.cacheLock) {
|
synchronized (owner.cacheLock) {
|
||||||
Account[] ownerAccounts = getAccounts(UserHandle.USER_OWNER);
|
for (Account acc : getAccounts(UserHandle.USER_OWNER)) {
|
||||||
for (Account acc : ownerAccounts) {
|
|
||||||
if (acc.equals(account)) {
|
if (acc.equals(account)) {
|
||||||
mAuthenticator.addAccountFromCredentials(this, account, result);
|
mAuthenticator.addAccountFromCredentials(
|
||||||
|
this, account, accountCredentials);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -742,17 +754,10 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResult(Bundle result) {
|
public void onResult(Bundle result) {
|
||||||
if (result != null) {
|
// TODO: Anything to do if if succedded?
|
||||||
if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
|
// TODO: If it failed: Show error notification? Should we remove the shadow
|
||||||
// TODO: Anything?
|
// account to avoid retries?
|
||||||
} else {
|
super.onResult(result);
|
||||||
// TODO: Show error notification
|
|
||||||
// TODO: Should we remove the shadow account to avoid retries?
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
super.onResult(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2740,7 +2745,7 @@ public class AccountManagerService
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MESSAGE_COPY_SHARED_ACCOUNT:
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user