Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95162ad2 authored by Esteban Talavera's avatar Esteban Talavera Committed by Android Git Automerger
Browse files

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

* commit '22dc3b7b':
  New AccountManager method to copy accounts between users.
parents 7bec28c5 22dc3b7b
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -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.
+2 −0
Original line number Diff line number Diff line
@@ -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);
+34 −29
Original line number Diff line number Diff line
@@ -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)) {
                    if (result != null
                            && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
                        // Create a Session for the target user and pass in the bundle
                            completeCloningAccount(result, account, toAccounts);
                        }
                        return;
                        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,18 +754,11 @@ 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 {
                    // 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
                public void onError(int errorCode, String errorMessage) {
@@ -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: