Merge "Fix deadlock." into mnc-dev

This commit is contained in:
Carlos Valdivia
2015-08-12 01:42:19 +00:00
committed by Android (Google) Code Review

View File

@@ -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(