Merge "Fix deadlock." into mnc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
968fc3ab75
@@ -283,7 +283,22 @@ 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)) {
|
||||||
purgeOldGrantsAll();
|
/* 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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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(
|
||||||
|
|||||||
Reference in New Issue
Block a user