From 858511cd2dbb3962da843fe40baba03305396159 Mon Sep 17 00:00:00 2001 From: Simranjit Kohli Date: Thu, 10 Mar 2016 18:36:11 +0000 Subject: [PATCH] Fix extra data in cache Reverting the revert. The original CL(commit a666d74d4bc7e1298314c516d1309571fb87c212) had a bug in it. It was calling accountExistsCacheLocked(), while holding accounts.cacheLock. The function accountExistsCacheLocked, was in turn calling into getUserAccounts, which acquires mUsers. And this causes trouble. mUsers is a a lock on all accounts, and hence calling it after holding accounts.cachelock is calling for trouble. Since the locks are acquired in other order, it causes a potential deadlock issue, which we discovered later on. That bug was fixed by commit 0e592733ecbde2b7e7f2aa92001656dfbcae9641. We already have useraccount object and should reuse it. This reverts commit 27d0e1fd660a7e92644ab6a2893ac1149f0c0488. This commit was unneeded as the bug had been fixed by that time. Change-Id: I5328c31fd485fd2c1c652cd0e7c2c4bded38a5fd --- .../accounts/AccountManagerService.java | 89 +++++++++++-------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index bb323031c011a..f667fb34b3701 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -782,7 +782,12 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { UserAccounts accounts = getUserAccounts(userId); - return readUserDataInternal(accounts, account, key); + synchronized (accounts.cacheLock) { + if (!accountExistsCacheLocked(accounts, account)) { + return null; + } + return readUserDataInternalLocked(accounts, account, key); + } } finally { restoreCallingIdentity(identityToken); } @@ -1869,44 +1874,57 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { UserAccounts accounts = getUserAccounts(userId); - setUserdataInternal(accounts, account, key, value); + synchronized (accounts.cacheLock) { + if (!accountExistsCacheLocked(accounts, account)) { + return; + } + setUserdataInternalLocked(accounts, account, key, value); + } } finally { restoreCallingIdentity(identityToken); } } - private void setUserdataInternal(UserAccounts accounts, Account account, String key, + private boolean accountExistsCacheLocked(UserAccounts accounts, Account account) { + if (accounts.accountCache.containsKey(account.type)) { + for (Account acc : accounts.accountCache.get(account.type)) { + if (acc.name.equals(account.name)) { + return true; + } + } + } + return false; + } + + private void setUserdataInternalLocked(UserAccounts accounts, Account account, String key, String value) { if (account == null || key == null) { return; } - synchronized (accounts.cacheLock) { - final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked(); - db.beginTransaction(); - try { - long accountId = getAccountIdLocked(db, account); - if (accountId < 0) { + final SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); + db.beginTransaction(); + try { + long accountId = getAccountIdLocked(db, account); + if (accountId < 0) { + return; + } + long extrasId = getExtrasIdLocked(db, accountId, key); + if (extrasId < 0) { + extrasId = insertExtraLocked(db, accountId, key, value); + if (extrasId < 0) { return; } - long extrasId = getExtrasIdLocked(db, accountId, key); - if (extrasId < 0 ) { - extrasId = insertExtraLocked(db, accountId, key, value); - if (extrasId < 0) { - return; - } - } else { - ContentValues values = new ContentValues(); - values.put(EXTRAS_VALUE, value); - if (1 != db.update(CE_TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) { - return; - } - + } else { + ContentValues values = new ContentValues(); + values.put(EXTRAS_VALUE, value); + if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) { + return; } - writeUserDataIntoCacheLocked(accounts, db, account, key, value); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); } + writeUserDataIntoCacheLocked(accounts, db, account, key, value); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); } } @@ -5262,17 +5280,16 @@ public class AccountManagerService } } - protected String readUserDataInternal(UserAccounts accounts, Account account, String key) { - synchronized (accounts.cacheLock) { - HashMap userDataForAccount = accounts.userDataCache.get(account); - if (userDataForAccount == null) { - // need to populate the cache for this account - final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked(); - userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account); - accounts.userDataCache.put(account, userDataForAccount); - } - return userDataForAccount.get(key); + protected String readUserDataInternalLocked( + UserAccounts accounts, Account account, String key) { + HashMap userDataForAccount = accounts.userDataCache.get(account); + if (userDataForAccount == null) { + // need to populate the cache for this account + final SQLiteDatabase db = accounts.openHelper.getReadableDatabase(); + userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account); + accounts.userDataCache.put(account, userDataForAccount); } + return userDataForAccount.get(key); } protected HashMap readUserDataForAccountFromDatabaseLocked(