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

Commit a049cf4a authored by Joe Castro's avatar Joe Castro
Browse files

Revert^2 "More judicious permission-change handling"

This reverts commit 2b70fd8d.

Reason for revert: Fixing forward original bug. Original change exposed race condition that is exposed on Mokey devices where the database isn't initialized by the time SyncAdapter starts querying account data.

Change-Id: I734155b47e0407e8db8e31868a5eb3ee08203956
parent 04ccd1b4
Loading
Loading
Loading
Loading
+42 −62
Original line number Diff line number Diff line
@@ -186,6 +186,12 @@ public class AccountManagerService

    final Context mContext;

    private static final int[] INTERESTING_APP_OPS = new int[] {
        AppOpsManager.OP_GET_ACCOUNTS,
        AppOpsManager.OP_READ_CONTACTS,
        AppOpsManager.OP_WRITE_CONTACTS,
    };

    private final PackageManager mPackageManager;
    private final AppOpsManager mAppOpsManager;
    private UserManager mUserManager;
@@ -389,75 +395,49 @@ public class AccountManagerService
        }.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);

        // Cancel account request notification if an app op was preventing the account access
        mAppOpsManager.startWatchingMode(AppOpsManager.OP_GET_ACCOUNTS, null,
                new AppOpsManager.OnOpChangedInternalListener() {
        for (int i = 0; i < INTERESTING_APP_OPS.length; ++i) {
            mAppOpsManager.startWatchingMode(INTERESTING_APP_OPS[i], null,
                    new OnInterestingAppOpChangedListener());
        }

        // Clear the accounts cache on permission changes.
        // The specific permissions we care about are backed by AppOps, so just
        // let the change events on those handle clearing any notifications.
        mPackageManager.addOnPermissionsChangeListener((int uid) -> {
            AccountManager.invalidateLocalAccountsDataCaches();
        });
    }

    private class OnInterestingAppOpChangedListener
            extends AppOpsManager.OnOpChangedInternalListener {
        @Override
        public void onOpChanged(int op, String packageName) {
                try {
            final int userId = ActivityManager.getCurrentUser();
                    final int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
                    final int mode = mAppOpsManager.checkOpNoThrow(
                            AppOpsManager.OP_GET_ACCOUNTS, uid, packageName);
                    if (mode == AppOpsManager.MODE_ALLOWED) {
                        final long identity = Binder.clearCallingIdentity();
            final int packageUid;
            try {
                            UserAccounts accounts = getUserAccounts(userId);
                            cancelAccountAccessRequestNotificationIfNeeded(
                                    packageName, uid, true, accounts);
                        } finally {
                            Binder.restoreCallingIdentity(identity);
                        }
                    }
                packageUid = mPackageManager.getPackageUidAsUser(packageName, userId);
            } catch (NameNotFoundException e) {
                /* ignore */
                } catch (SQLiteCantOpenDatabaseException e) {
                    Log.w(TAG, "Can't read accounts database", e);
                return;
            }
            }
        });

        // Cancel account request notification if a permission was preventing the account access
        mPackageManager.addOnPermissionsChangeListener(
                (int uid) -> {
            // Permission changes cause requires updating accounts cache.
            AccountManager.invalidateLocalAccountsDataCaches();
            final int mode = mAppOpsManager.checkOpNoThrow(op, packageUid, packageName);
            if (mode != AppOpsManager.MODE_ALLOWED) {
                return;
            }

            Account[] accounts = null;
            String[] packageNames = mPackageManager.getPackagesForUid(uid);
            if (packageNames != null) {
                final int userId = UserHandle.getUserId(uid);
            final long identity = Binder.clearCallingIdentity();
            try {
                    for (String packageName : packageNames) {
                                // if app asked for permission we need to cancel notification even
                                // for O+ applications.
                                if (mPackageManager.checkPermission(
                                        Manifest.permission.GET_ACCOUNTS,
                                        packageName) != PackageManager.PERMISSION_GRANTED) {
                                    continue;
                                }

                        if (accounts == null) {
                            accounts = getAccountsOrEmptyArray(null, userId, "android");
                            if (ArrayUtils.isEmpty(accounts)) {
                                return;
                            }
                        }
                        UserAccounts userAccounts = getUserAccounts(UserHandle.getUserId(uid));
                        for (Account account : accounts) {
                cancelAccountAccessRequestNotificationIfNeeded(
                                    account, uid, packageName, true, userAccounts);
                        }
                    }
                        packageName, packageUid, true, getUserAccounts(userId));
            } catch (SQLiteCantOpenDatabaseException e) {
                Log.w(TAG, "Can't read accounts database", e);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
        });
    }


    boolean getBindInstantServiceAllowed(int userId) {
        return  mAuthenticatorCache.getBindInstantServiceAllowed(userId);
    }