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

Commit 4f7d0bc7 authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android (Google) Code Review
Browse files

Merge "Add get_accounts app op" into mnc-dev

parents 92aeac34 ce852ddc
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -426,7 +426,7 @@ public class AccountManager {
    @RequiresPermission(GET_ACCOUNTS)
    public Account[] getAccounts() {
        try {
            return mService.getAccounts(null);
            return mService.getAccounts(null, mContext.getOpPackageName());
        } catch (RemoteException e) {
            // won't ever happen
            throw new RuntimeException(e);
@@ -451,7 +451,7 @@ public class AccountManager {
    @RequiresPermission(GET_ACCOUNTS)
    public Account[] getAccountsAsUser(int userId) {
        try {
            return mService.getAccountsAsUser(null, userId);
            return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName());
        } catch (RemoteException e) {
            // won't ever happen
            throw new RuntimeException(e);
@@ -468,7 +468,7 @@ public class AccountManager {
     */
    public Account[] getAccountsForPackage(String packageName, int uid) {
        try {
            return mService.getAccountsForPackage(packageName, uid);
            return mService.getAccountsForPackage(packageName, uid, mContext.getOpPackageName());
        } catch (RemoteException re) {
            // won't ever happen
            throw new RuntimeException(re);
@@ -485,7 +485,8 @@ public class AccountManager {
     */
    public Account[] getAccountsByTypeForPackage(String type, String packageName) {
        try {
            return mService.getAccountsByTypeForPackage(type, packageName);
            return mService.getAccountsByTypeForPackage(type, packageName,
                    mContext.getOpPackageName());
        } catch (RemoteException re) {
            // won't ever happen
            throw new RuntimeException(re);
@@ -522,7 +523,8 @@ public class AccountManager {
    /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
    public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
        try {
            return mService.getAccountsAsUser(type, userHandle.getIdentifier());
            return mService.getAccountsAsUser(type, userHandle.getIdentifier(),
                    mContext.getOpPackageName());
        } catch (RemoteException e) {
            // won't ever happen
            throw new RuntimeException(e);
@@ -610,7 +612,7 @@ public class AccountManager {
        if (features == null) throw new IllegalArgumentException("features is null");
        return new Future2Task<Boolean>(handler, callback) {
            public void doWork() throws RemoteException {
                mService.hasFeatures(mResponse, account, features);
                mService.hasFeatures(mResponse, account, features, mContext.getOpPackageName());
            }
            public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
                if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
@@ -662,7 +664,8 @@ public class AccountManager {
        if (type == null) throw new IllegalArgumentException("type is null");
        return new Future2Task<Account[]>(handler, callback) {
            public void doWork() throws RemoteException {
                mService.getAccountsByFeatures(mResponse, type, features);
                mService.getAccountsByFeatures(mResponse, type, features,
                        mContext.getOpPackageName());
            }
            public Account[] bundleToResult(Bundle bundle) throws AuthenticatorException {
                if (!bundle.containsKey(KEY_ACCOUNTS)) {
+8 −6
Original line number Diff line number Diff line
@@ -30,12 +30,14 @@ interface IAccountManager {
    String getPassword(in Account account);
    String getUserData(in Account account, String key);
    AuthenticatorDescription[] getAuthenticatorTypes(int userId);
    Account[] getAccounts(String accountType);
    Account[] getAccountsForPackage(String packageName, int uid);
    Account[] getAccountsByTypeForPackage(String type, String packageName);
    Account[] getAccountsAsUser(String accountType, int userId);
    void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features);
    void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
    Account[] getAccounts(String accountType, String opPackageName);
    Account[] getAccountsForPackage(String packageName, int uid, String opPackageName);
    Account[] getAccountsByTypeForPackage(String type, String packageName, String opPackageName);
    Account[] getAccountsAsUser(String accountType, int userId, String opPackageName);
    void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features,
        String opPackageName);
    void getAccountsByFeatures(in IAccountManagerResponse response, String accountType,
        in String[] features, String opPackageName);
    boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
    void removeAccount(in IAccountManagerResponse response, in Account account,
        boolean expectActivityLaunch);
+14 −1
Original line number Diff line number Diff line
@@ -235,8 +235,10 @@ public class AppOpsManager {
    public static final int OP_WRITE_EXTERNAL_STORAGE = 60;
    /** @hide Turned on the screen. */
    public static final int OP_TURN_SCREEN_ON = 61;
    /** @hide Get device accounts. */
    public static final int OP_GET_ACCOUNTS = 62;
    /** @hide */
    public static final int _NUM_OP = 62;
    public static final int _NUM_OP = 63;

    /** Access to coarse location information. */
    public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -331,6 +333,9 @@ public class AppOpsManager {
    /** Required to write/modify/update system settingss. */
    public static final String OPSTR_WRITE_SETTINGS
            = "android:write_settings";
    /** @hide Get device accounts. */
    public static final String OPSTR_GET_ACCOUNTS
            = "android:get_accounts";

    /**
     * This maps each operation to the operation that serves as the
@@ -403,6 +408,7 @@ public class AppOpsManager {
            OP_READ_EXTERNAL_STORAGE,
            OP_WRITE_EXTERNAL_STORAGE,
            OP_TURN_SCREEN_ON,
            OP_GET_ACCOUNTS,
    };

    /**
@@ -472,6 +478,7 @@ public class AppOpsManager {
            OPSTR_READ_EXTERNAL_STORAGE,
            OPSTR_WRITE_EXTERNAL_STORAGE,
            null,
            OPSTR_GET_ACCOUNTS
    };

    /**
@@ -541,6 +548,7 @@ public class AppOpsManager {
            "READ_EXTERNAL_STORAGE",
            "WRITE_EXTERNAL_STORAGE",
            "TURN_ON_SCREEN",
            "GET_ACCOUNTS",
    };

    /**
@@ -610,6 +618,7 @@ public class AppOpsManager {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            null, // no permission for turning the screen on
            Manifest.permission.GET_ACCOUNTS
    };

    /**
@@ -680,6 +689,7 @@ public class AppOpsManager {
            null, // READ_EXTERNAL_STORAGE
            null, // WRITE_EXTERNAL_STORAGE
            null, // TURN_ON_SCREEN
            null, // GET_ACCOUNTS
    };

    /**
@@ -749,6 +759,7 @@ public class AppOpsManager {
            false, // READ_EXTERNAL_STORAGE
            false, // WRITE_EXTERNAL_STORAGE
            false, // TURN_ON_SCREEN
            false, // GET_ACCOUNTS
    };

    /**
@@ -817,6 +828,7 @@ public class AppOpsManager {
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,
            AppOpsManager.MODE_ALLOWED,  // OP_TURN_ON_SCREEN
            AppOpsManager.MODE_ALLOWED,
    };

    /**
@@ -889,6 +901,7 @@ public class AppOpsManager {
            false,
            false,
            false,
            false
    };

    /**
+47 −39
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.accounts.IAccountManagerResponse;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -122,6 +123,7 @@ public class AccountManagerService
    private final Context mContext;

    private final PackageManager mPackageManager;
    private final AppOpsManager mAppOpsManager;
    private UserManager mUserManager;

    private final MessageHandler mMessageHandler;
@@ -266,6 +268,7 @@ public class AccountManagerService
            IAccountAuthenticatorCache authenticatorCache) {
        mContext = context;
        mPackageManager = packageManager;
        mAppOpsManager = mContext.getSystemService(AppOpsManager.class);

        mMessageHandler = new MessageHandler(FgThread.get().getLooper());

@@ -510,7 +513,7 @@ public class AccountManagerService
        // Check if there's a shared account that needs to be created as an account
        Account[] sharedAccounts = getSharedAccountsAsUser(userId);
        if (sharedAccounts == null || sharedAccounts.length == 0) return;
        Account[] accounts = getAccountsAsUser(null, userId);
        Account[] accounts = getAccountsAsUser(null, userId, mContext.getOpPackageName());
        for (Account sa : sharedAccounts) {
            if (ArrayUtils.contains(accounts, sa)) continue;
            // Account doesn't exist. Copy it now.
@@ -868,7 +871,8 @@ public class AccountManagerService
                    // Confirm that the owner's account still exists before this step.
                    UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER);
                    synchronized (owner.cacheLock) {
                        for (Account acc : getAccounts(UserHandle.USER_OWNER)) {
                        for (Account acc : getAccounts(UserHandle.USER_OWNER,
                                mContext.getOpPackageName())) {
                            if (acc.equals(account)) {
                                mAuthenticator.addAccountFromCredentials(
                                        this, account, accountCredentials);
@@ -988,7 +992,7 @@ public class AccountManagerService

    @Override
    public void hasFeatures(IAccountManagerResponse response,
            Account account, String[] features) {
            Account account, String[] features, String opPackageName) {
        int callingUid = Binder.getCallingUid();
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "hasFeatures: " + account
@@ -1001,7 +1005,8 @@ public class AccountManagerService
        if (account == null) throw new IllegalArgumentException("account is null");
        if (features == null) throw new IllegalArgumentException("features is null");
        int userId = UserHandle.getCallingUserId();
        checkReadAccountsPermitted(callingUid, account.type, userId);
        checkReadAccountsPermitted(callingUid, account.type, userId,
                opPackageName);

        long identityToken = clearCallingIdentity();
        try {
@@ -2507,9 +2512,10 @@ public class AccountManagerService
     * Returns the accounts visible to the client within the context of a specific user
     * @hide
     */
    public Account[] getAccounts(int userId) {
    public Account[] getAccounts(int userId, String opPackageName) {
        int callingUid = Binder.getCallingUid();
        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId,
                opPackageName);
        if (visibleAccountTypes.isEmpty()) {
            return new Account[0];
        }
@@ -2571,15 +2577,16 @@ public class AccountManagerService
    }

    @Override
    public Account[] getAccountsAsUser(String type, int userId) {
        return getAccountsAsUser(type, userId, null, -1);
    public Account[] getAccountsAsUser(String type, int userId, String opPackageName) {
        return getAccountsAsUser(type, userId, null, -1, opPackageName);
    }

    private Account[] getAccountsAsUser(
            String type,
            int userId,
            String callingPackage,
            int packageUid) {
            int packageUid,
            String opPackageName) {
        int callingUid = Binder.getCallingUid();
        // Only allow the system process to read accounts of other users
        if (userId != UserHandle.getCallingUserId()
@@ -2602,7 +2609,8 @@ public class AccountManagerService
            callingUid = packageUid;
        }

        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId,
                opPackageName);
        if (visibleAccountTypes.isEmpty()
                || (type != null && !visibleAccountTypes.contains(type))) {
            return new Account[0];
@@ -2741,22 +2749,24 @@ public class AccountManagerService
    }

    @Override
    public Account[] getAccounts(String type) {
        return getAccountsAsUser(type, UserHandle.getCallingUserId());
    public Account[] getAccounts(String type, String opPackageName) {
        return getAccountsAsUser(type, UserHandle.getCallingUserId(), opPackageName);
    }

    @Override
    public Account[] getAccountsForPackage(String packageName, int uid) {
    public Account[] getAccountsForPackage(String packageName, int uid, String opPackageName) {
        int callingUid = Binder.getCallingUid();
        if (!UserHandle.isSameApp(callingUid, Process.myUid())) {
            throw new SecurityException("getAccountsForPackage() called from unauthorized uid "
                    + callingUid + " with uid=" + uid);
        }
        return getAccountsAsUser(null, UserHandle.getCallingUserId(), packageName, uid);
        return getAccountsAsUser(null, UserHandle.getCallingUserId(), packageName, uid,
                opPackageName);
    }

    @Override
    public Account[] getAccountsByTypeForPackage(String type, String packageName) {
    public Account[] getAccountsByTypeForPackage(String type, String packageName,
            String opPackageName) {
        int packageUid = -1;
        try {
            packageUid = AppGlobals.getPackageManager().getPackageUid(
@@ -2765,14 +2775,16 @@ public class AccountManagerService
            Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re);
            return new Account[0];
        }
        return getAccountsAsUser(type, UserHandle.getCallingUserId(), packageName, packageUid);
        return getAccountsAsUser(type, UserHandle.getCallingUserId(), packageName,
                packageUid, opPackageName);
    }

    @Override
    public void getAccountsByFeatures(
            IAccountManagerResponse response,
            String type,
            String[] features) {
            String[] features,
            String opPackageName) {
        int callingUid = Binder.getCallingUid();
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "getAccounts: accountType " + type
@@ -2785,7 +2797,8 @@ public class AccountManagerService
        if (type == null) throw new IllegalArgumentException("accountType is null");
        int userId = UserHandle.getCallingUserId();

        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId,
                opPackageName);
        if (!visibleAccountTypes.contains(type)) {
            Bundle result = new Bundle();
            // Need to return just the accounts that are from matching signatures.
@@ -3685,29 +3698,20 @@ public class AccountManagerService
        }
    }

    private boolean isPermitted(int callingUid, String... permissions) {
    private boolean isPermitted(String opPackageName, int callingUid, String... permissions) {
        for (String perm : permissions) {
            if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "  caller uid " + callingUid + " has " + perm);
                }
                final int opCode = AppOpsManager.permissionToOpCode(perm);
                if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOp(
                        opCode, callingUid, opPackageName) == AppOpsManager.MODE_ALLOWED) {
                    return true;
                }
            }
        return false;
    }

    /** Succeeds if any of the specified permissions are granted. */
    private void checkBinderPermission(String... permissions) {
        final int callingUid = Binder.getCallingUid();
        if (isPermitted(callingUid, permissions)) {
            String msg = String.format(
                    "caller uid %s  lacks any of %s",
                    callingUid,
                    TextUtils.join(",", permissions));
            Log.w(TAG, "  " + msg);
            throw new SecurityException(msg);
        }
        return false;
    }

    private int handleIncomingUser(int userId) {
@@ -3763,11 +3767,13 @@ public class AccountManagerService
        return fromAuthenticator || hasExplicitGrants || isPrivileged;
    }

    private boolean isAccountVisibleToCaller(String accountType, int callingUid, int userId) {
    private boolean isAccountVisibleToCaller(String accountType, int callingUid, int userId,
            String opPackageName) {
        if (accountType == null) {
            return false;
        } else {
            return getTypesVisibleToCaller(callingUid, userId).contains(accountType);
            return getTypesVisibleToCaller(callingUid, userId,
                    opPackageName).contains(accountType);
        }
    }

@@ -3779,9 +3785,10 @@ public class AccountManagerService
        }
    }

    private List<String> getTypesVisibleToCaller(int callingUid, int userId) {
    private List<String> getTypesVisibleToCaller(int callingUid, int userId,
            String opPackageName) {
        boolean isPermitted =
                isPermitted(callingUid, Manifest.permission.GET_ACCOUNTS,
                isPermitted(opPackageName, callingUid, Manifest.permission.GET_ACCOUNTS,
                        Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
        Log.i(TAG, String.format("getTypesVisibleToCaller: isPermitted? %s", isPermitted));
        return getTypesForCaller(callingUid, userId, isPermitted);
@@ -3877,8 +3884,9 @@ public class AccountManagerService
    private void checkReadAccountsPermitted(
            int callingUid,
            String accountType,
            int userId) {
        if (!isAccountVisibleToCaller(accountType, callingUid, userId)) {
            int userId,
            String opPackageName) {
        if (!isAccountVisibleToCaller(accountType, callingUid, userId, opPackageName)) {
            String msg = String.format(
                    "caller uid %s cannot access %s accounts",
                    callingUid,
+4 −2
Original line number Diff line number Diff line
@@ -340,7 +340,8 @@ public class SyncManager {
        for (UserInfo user : mUserManager.getUsers(true)) {
            // Skip any partially created/removed users
            if (user.partial) continue;
            Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(user.id);
            Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(
                    user.id, mContext.getOpPackageName());
            mSyncStorageEngine.doDatabaseCleanup(accountsForUser, user.id);
        }
    }
@@ -1232,7 +1233,8 @@ public class SyncManager {
        }

        // Schedule sync for any accounts under started user
        final Account[] accounts = AccountManagerService.getSingleton().getAccounts(userId);
        final Account[] accounts = AccountManagerService.getSingleton().getAccounts(userId,
                mContext.getOpPackageName());
        for (Account account : accounts) {
            scheduleSync(account, userId, SyncOperation.REASON_USER_START, null, null,
                    0 /* no delay */, 0 /* No flex */,
Loading