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

Commit 47c5338b authored by Carlos Valdivia's avatar Carlos Valdivia Committed by Android Git Automerger
Browse files

am 968fc3ab: Merge "Fix deadlock." into mnc-dev

* commit '968fc3ab':
  Fix deadlock.
parents c787d8bc 968fc3ab
Loading
Loading
Loading
Loading
+59 −54
Original line number Original line Diff line number Diff line
@@ -283,8 +283,23 @@ public class AccountManagerService
                // Don't delete accounts when updating a authenticator's
                // Don't delete accounts when updating a authenticator's
                // package.
                // package.
                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                    /* Purging data requires file io, don't block the main thread. This is probably
                     * less than ideal because we are introducing a race condition where old grants
                     * could be exercised until they are purged. But that race condition existed
                     * anyway with the broadcast receiver.
                     *
                     * Ideally, we would completely clear the cache, purge data from the database,
                     * and then rebuild the cache. All under the cache lock. But that change is too
                     * large at this point.
                     */
                    Runnable r = new Runnable() {
                        @Override
                        public void run() {
                            purgeOldGrantsAll();
                            purgeOldGrantsAll();
                        }
                        }
                    };
                    new Thread(r).start();
                }
            }
            }
        }, intentFilter);
        }, intentFilter);


@@ -329,52 +344,6 @@ public class AccountManagerService
        return mUserManager;
        return mUserManager;
    }
    }


    /* Caller should lock mUsers */
    private UserAccounts initUserLocked(int userId) {
        UserAccounts accounts = mUsers.get(userId);
        if (accounts == null) {
            accounts = new UserAccounts(mContext, userId);
            initializeDebugDbSizeAndCompileSqlStatementForLogging(
                    accounts.openHelper.getWritableDatabase(), accounts);
            mUsers.append(userId, accounts);
            purgeOldGrants(accounts);
            validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
        }
        return accounts;
    }

    private void purgeOldGrantsAll() {
        synchronized (mUsers) {
            for (int i = 0; i < mUsers.size(); i++) {
                purgeOldGrants(mUsers.valueAt(i));
            }
        }
    }

    private void purgeOldGrants(UserAccounts accounts) {
        synchronized (accounts.cacheLock) {
            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
            final Cursor cursor = db.query(TABLE_GRANTS,
                    new String[]{GRANTS_GRANTEE_UID},
                    null, null, GRANTS_GRANTEE_UID, null, null);
            try {
                while (cursor.moveToNext()) {
                    final int uid = cursor.getInt(0);
                    final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
                    if (packageExists) {
                        continue;
                    }
                    Log.d(TAG, "deleting grants for UID " + uid
                            + " because its package is no longer installed");
                    db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
                            new String[]{Integer.toString(uid)});
                }
            } finally {
                cursor.close();
            }
        }
    }

    /**
    /**
     * Validate internal set of accounts against installed authenticators for
     * Validate internal set of accounts against installed authenticators for
     * given user. Clears cached authenticators before validating.
     * given user. Clears cached authenticators before validating.
@@ -469,13 +438,49 @@ public class AccountManagerService
        synchronized (mUsers) {
        synchronized (mUsers) {
            UserAccounts accounts = mUsers.get(userId);
            UserAccounts accounts = mUsers.get(userId);
            if (accounts == null) {
            if (accounts == null) {
                accounts = initUserLocked(userId);
                accounts = new UserAccounts(mContext, userId);
                initializeDebugDbSizeAndCompileSqlStatementForLogging(
                        accounts.openHelper.getWritableDatabase(), accounts);
                mUsers.append(userId, accounts);
                mUsers.append(userId, accounts);
                purgeOldGrants(accounts);
                validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
            }
            }
            return accounts;
            return accounts;
        }
        }
    }
    }


    private void purgeOldGrantsAll() {
        synchronized (mUsers) {
            for (int i = 0; i < mUsers.size(); i++) {
                purgeOldGrants(mUsers.valueAt(i));
            }
        }
    }

    private void purgeOldGrants(UserAccounts accounts) {
        synchronized (accounts.cacheLock) {
            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
            final Cursor cursor = db.query(TABLE_GRANTS,
                    new String[]{GRANTS_GRANTEE_UID},
                    null, null, GRANTS_GRANTEE_UID, null, null);
            try {
                while (cursor.moveToNext()) {
                    final int uid = cursor.getInt(0);
                    final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
                    if (packageExists) {
                        continue;
                    }
                    Log.d(TAG, "deleting grants for UID " + uid
                            + " because its package is no longer installed");
                    db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
                            new String[]{Integer.toString(uid)});
                }
            } finally {
                cursor.close();
            }
        }
    }

    private void onUserRemoved(Intent intent) {
    private void onUserRemoved(Intent intent) {
        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
        if (userId < 1) return;
        if (userId < 1) return;
@@ -2510,8 +2515,9 @@ public class AccountManagerService
        }
        }
        long identityToken = clearCallingIdentity();
        long identityToken = clearCallingIdentity();
        try {
        try {
            UserAccounts accounts = getUserAccounts(userId);
            return getAccountsInternal(
            return getAccountsInternal(
                    userId,
                    accounts,
                    callingUid,
                    callingUid,
                    null,  // packageName
                    null,  // packageName
                    visibleAccountTypes);
                    visibleAccountTypes);
@@ -2609,8 +2615,9 @@ public class AccountManagerService


        long identityToken = clearCallingIdentity();
        long identityToken = clearCallingIdentity();
        try {
        try {
            UserAccounts accounts = getUserAccounts(userId);
            return getAccountsInternal(
            return getAccountsInternal(
                    userId,
                    accounts,
                    callingUid,
                    callingUid,
                    callingPackage,
                    callingPackage,
                    visibleAccountTypes);
                    visibleAccountTypes);
@@ -2620,13 +2627,11 @@ public class AccountManagerService
    }
    }


    private Account[] getAccountsInternal(
    private Account[] getAccountsInternal(
            int userId,
            UserAccounts userAccounts,
            int callingUid,
            int callingUid,
            String callingPackage,
            String callingPackage,
            List<String> visibleAccountTypes) {
            List<String> visibleAccountTypes) {
        UserAccounts accounts = getUserAccounts(userId);
        synchronized (userAccounts.cacheLock) {
        synchronized (accounts.cacheLock) {
            UserAccounts userAccounts = getUserAccounts(userId);
            ArrayList<Account> visibleAccounts = new ArrayList<>();
            ArrayList<Account> visibleAccounts = new ArrayList<>();
            for (String visibleType : visibleAccountTypes) {
            for (String visibleType : visibleAccountTypes) {
                Account[] accountsForType = getAccountsFromCacheLocked(
                Account[] accountsForType = getAccountsFromCacheLocked(