[Fix extra data in cache]

It seems that some account authenticators call getData before account
is added, which initializes the cache for that account.
1. We now don't initialize the cache if the account is not on the device.
2. We now use locking.

Bug: 23018710
Bug: 20071745
Change-Id: Ie59ca6b4e575f524a9d3bf286c3bd95abce4a596
This commit is contained in:
Simranjit Singh Kohli
2015-08-07 13:34:09 -07:00
parent f0c5b7af6f
commit a666d74d4b

View File

@@ -660,7 +660,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);
}
@@ -1716,44 +1721,58 @@ 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 : getUserAccountsForCaller().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.getWritableDatabase();
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(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();
}
}
@@ -4788,17 +4807,16 @@ public class AccountManagerService
}
}
protected String readUserDataInternal(UserAccounts accounts, Account account, String key) {
synchronized (accounts.cacheLock) {
HashMap<String, String> 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 String readUserDataInternalLocked(
UserAccounts accounts, Account account, String key) {
HashMap<String, String> 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<String, String> readUserDataForAccountFromDatabaseLocked(