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

Commit 3c144c3e authored by Fred Quintana's avatar Fred Quintana Committed by Android (Google) Code Review
Browse files

Merge "Add an updateAppPermission() API call to the AccountManagerService AIDL...

Merge "Add an updateAppPermission() API call to the AccountManagerService AIDL and have the GrantCredentialsPermissionActivity call that instead of a static so that it can be made to run in a different process than the AccountManagerService. Protect this call by checking that the caller has the same UID as the system process." into jb-dev
parents f46bd06c d9640ec7
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -404,6 +404,55 @@ public class AccountManager {
        }
    }

    /**
     * Change whether or not an app (identified by its uid) is allowed to retrieve an authToken
     * for an account.
     * <p>
     * This is only meant to be used by system activities and is not in the SDK.
     * @param account The account whose permissions are being modified
     * @param authTokenType The type of token whose permissions are being modified
     * @param uid The uid that identifies the app which is being granted or revoked permission.
     * @param value true is permission is being granted, false for revoked
     * @hide
     */
    public void updateAppPermission(Account account, String authTokenType, int uid, boolean value) {
        try {
            mService.updateAppPermission(account, authTokenType, uid, value);
        } catch (RemoteException e) {
            // won't ever happen
            throw new RuntimeException(e);
        }
    }

    /**
     * Get the user-friendly label associated with an authenticator's auth token.
     * @param accountType the type of the authenticator. must not be null.
     * @param authTokenType the token type. must not be null.
     * @param callback callback to invoke when the result is available. may be null.
     * @param handler the handler on which to invoke the callback, or null for the main thread
     * @return a future containing the label string
     * @hide
     */
    public AccountManagerFuture<String> getAuthTokenLabel(
            final String accountType, final String authTokenType,
            AccountManagerCallback<String> callback, Handler handler) {
        if (accountType == null) throw new IllegalArgumentException("accountType is null");
        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
        return new Future2Task<String>(handler, callback) {
            public void doWork() throws RemoteException {
                mService.getAuthTokenLabel(mResponse, accountType, authTokenType);
            }

            @Override
            public String bundleToResult(Bundle bundle) throws AuthenticatorException {
                if (!bundle.containsKey(KEY_AUTH_TOKEN_LABEL)) {
                    throw new AuthenticatorException("no result in response");
                }
                return bundle.getString(KEY_AUTH_TOKEN_LABEL);
            }
        }.start();
    }

    /**
     * Finds out whether a particular account has all the specified features.
     * Account features are authenticator-specific string tokens identifying
+29 −10
Original line number Diff line number Diff line
@@ -985,21 +985,25 @@ public class AccountManagerService
        }
    }

    void getAuthTokenLabel(final IAccountManagerResponse response,
            final Account account,
            final String authTokenType, int uid) {
        if (account == null) throw new IllegalArgumentException("account is null");
    public void getAuthTokenLabel(IAccountManagerResponse response, final String accountType,
                                  final String authTokenType)
            throws RemoteException {
        if (accountType == null) throw new IllegalArgumentException("accountType is null");
        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");

        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
        UserAccounts accounts = getUserAccounts(UserId.getUserId(uid));
        final int callingUid = getCallingUid();
        clearCallingIdentity();
        if (callingUid != android.os.Process.SYSTEM_UID) {
            throw new SecurityException("can only call from system");
        }
        UserAccounts accounts = getUserAccounts(UserId.getUserId(callingUid));
        long identityToken = clearCallingIdentity();
        try {
            new Session(accounts, response, account.type, false,
            new Session(accounts, response, accountType, false,
                    false /* stripAuthTokenFromResult */) {
                protected String toDebugString(long now) {
                    return super.toDebugString(now) + ", getAuthTokenLabel"
                            + ", " + account
                            + ", " + accountType
                            + ", authTokenType " + authTokenType;
                }

@@ -2230,6 +2234,21 @@ public class AccountManagerService
                Manifest.permission.USE_CREDENTIALS);
    }

    public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
            throws RemoteException {
        final int callingUid = getCallingUid();

        if (callingUid != android.os.Process.SYSTEM_UID) {
            throw new SecurityException();
        }

        if (value) {
            grantAppPermission(account, authTokenType, uid);
        } else {
            revokeAppPermission(account, authTokenType, uid);
        }
    }

    /**
     * Allow callers with the given uid permission to get credentials for account/authTokenType.
     * <p>
@@ -2237,7 +2256,7 @@ public class AccountManagerService
     * which is in the system. This means we don't need to protect it with permissions.
     * @hide
     */
    public void grantAppPermission(Account account, String authTokenType, int uid) {
    private void grantAppPermission(Account account, String authTokenType, int uid) {
        if (account == null || authTokenType == null) {
            Log.e(TAG, "grantAppPermission: called with invalid arguments", new Exception());
            return;
@@ -2271,7 +2290,7 @@ public class AccountManagerService
     * which is in the system. This means we don't need to protect it with permissions.
     * @hide
     */
    public void revokeAppPermission(Account account, String authTokenType, int uid) {
    private void revokeAppPermission(Account account, String authTokenType, int uid) {
        if (account == null || authTokenType == null) {
            Log.e(TAG, "revokeAppPermission: called with invalid arguments", new Exception());
            return;
+43 −27
Original line number Diff line number Diff line
@@ -16,22 +16,22 @@
package android.accounts;

import android.app.Activity;
import android.content.pm.RegisteredServicesCache;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.RemoteException;
import android.widget.TextView;
import android.widget.LinearLayout;
import android.widget.ImageView;
import android.view.View;
import android.view.LayoutInflater;
import android.view.Window;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.RegisteredServicesCache;
import android.text.TextUtils;
import android.graphics.drawable.Drawable;
import com.android.internal.R;

import java.io.IOException;
import java.net.Authenticator;

/**
 * @hide
 */
@@ -48,7 +48,6 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
    private int mUid;
    private Bundle mResultBundle = null;
    protected LayoutInflater mInflater;
    private final AccountManagerService accountManagerService = AccountManagerService.getSingleton();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
@@ -81,7 +80,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View

        String accountTypeLabel;
        try {
            accountTypeLabel = accountManagerService.getAccountLabel(mAccount.type);
            accountTypeLabel = getAccountLabel(mAccount);
        } catch (IllegalArgumentException e) {
            // label or resource was missing. abort the activity.
            setResult(Activity.RESULT_CANCELED);
@@ -92,11 +91,10 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
        final TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
        authTokenTypeView.setVisibility(View.GONE);

        /** Handles the responses from the AccountManager */
        IAccountManagerResponse response = new IAccountManagerResponse.Stub() {
            public void onResult(Bundle bundle) {
                final String authTokenLabel =
                    bundle.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
        final AccountManagerCallback<String> callback = new AccountManagerCallback<String>() {
            public void run(AccountManagerFuture<String> future) {
                try {
                    final String authTokenLabel = future.getResult();
                    if (!TextUtils.isEmpty(authTokenLabel)) {
                        runOnUiThread(new Runnable() {
                            public void run() {
@@ -107,13 +105,13 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
                            }
                        });
                    }
                } catch (OperationCanceledException e) {
                } catch (IOException e) {
                } catch (AuthenticatorException e) {
                }

            public void onError(int code, String message) {
            }
        };

        accountManagerService.getAuthTokenLabel(response, mAccount, mAuthTokenType, mUid);
        AccountManager.get(this).getAuthTokenLabel(mAccount.type, mAuthTokenType, callback, null);

        findViewById(R.id.allow_button).setOnClickListener(this);
        findViewById(R.id.deny_button).setOnClickListener(this);
@@ -134,6 +132,24 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
        ((TextView) findViewById(R.id.account_type)).setText(accountTypeLabel);
    }

    private String getAccountLabel(Account account) {
        final AuthenticatorDescription[] authenticatorTypes =
                AccountManager.get(this).getAuthenticatorTypes();
        for (int i = 0, N = authenticatorTypes.length; i < N; i++) {
            final AuthenticatorDescription desc = authenticatorTypes[i];
            if (desc.type.equals(account.type)) {
                try {
                    return createPackageContext(desc.packageName, 0).getString(desc.labelId);
                } catch (PackageManager.NameNotFoundException e) {
                    return account.type;
                } catch (Resources.NotFoundException e) {
                    return account.type;
                }
            }
        }
        return account.type;
    }

    private View newPackageView(String packageLabel) {
        View view = mInflater.inflate(R.layout.permissions_package_list_item, null);
        ((TextView) view.findViewById(R.id.package_label)).setText(packageLabel);
@@ -143,7 +159,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.allow_button:
                accountManagerService.grantAppPermission(mAccount, mAuthTokenType, mUid);
                AccountManager.get(this).updateAppPermission(mAccount, mAuthTokenType, mUid, true);
                Intent result = new Intent();
                result.putExtra("retry", true);
                setResult(RESULT_OK, result);
@@ -151,7 +167,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
                break;

            case R.id.deny_button:
                accountManagerService.revokeAppPermission(mAccount, mAuthTokenType, mUid);
                AccountManager.get(this).updateAppPermission(mAccount, mAuthTokenType, mUid, false);
                setResult(RESULT_CANCELED);
                break;
        }
+3 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ interface IAccountManager {
    void setPassword(in Account account, String password);
    void clearPassword(in Account account);
    void setUserData(in Account account, String key, String value);
    void updateAppPermission(in Account account, String authTokenType, int uid, boolean value);

    void getAuthToken(in IAccountManagerResponse response, in Account account,
        String authTokenType, boolean notifyOnAuthFailure, boolean expectActivityLaunch,
@@ -54,4 +55,6 @@ interface IAccountManager {
        boolean expectActivityLaunch);
    void confirmCredentials(in IAccountManagerResponse response, in Account account,
        in Bundle options, boolean expectActivityLaunch);
    void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
        String authTokenType);
}