Merge "Clearing up invalid entries when SyncStorageEngine starts" into nyc-dev am: fc9e382229 am: 7d9e844124

am: 25ec24740b

Change-Id: I858f75717157bd9269bcd43d4198935302132d5a
This commit is contained in:
Suprabh Shukla
2017-09-10 20:01:33 +00:00
committed by android-build-merger

View File

@@ -18,6 +18,7 @@ package com.android.server.content;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountAndUser; import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
import android.app.backup.BackupManager; import android.app.backup.BackupManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -27,6 +28,7 @@ import android.content.PeriodicSync;
import android.content.SyncInfo; import android.content.SyncInfo;
import android.content.SyncRequest; import android.content.SyncRequest;
import android.content.SyncStatusInfo; import android.content.SyncStatusInfo;
import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteException;
@@ -350,6 +352,50 @@ public class SyncStorageEngine extends Handler {
void onAuthorityRemoved(EndPoint removedAuthority); void onAuthorityRemoved(EndPoint removedAuthority);
} }
/**
* Validator that maintains a lazy cache of accounts and providers to tell if an authority or
* account is valid.
*/
private static class AccountAuthorityValidator {
final private AccountManager mAccountManager;
final private PackageManager mPackageManager;
final private SparseArray<Account[]> mAccountsCache;
final private SparseArray<ArrayMap<String, Boolean>> mProvidersPerUserCache;
AccountAuthorityValidator(Context context) {
mAccountManager = context.getSystemService(AccountManager.class);
mPackageManager = context.getPackageManager();
mAccountsCache = new SparseArray<>();
mProvidersPerUserCache = new SparseArray<>();
}
// An account is valid if an installed authenticator has previously created that account
// on the device
boolean isAccountValid(Account account, int userId) {
Account[] accountsForUser = mAccountsCache.get(userId);
if (accountsForUser == null) {
accountsForUser = mAccountManager.getAccountsAsUser(userId);
mAccountsCache.put(userId, accountsForUser);
}
return ArrayUtils.contains(accountsForUser, account);
}
// An authority is only valid if it has a content provider installed on the system
boolean isAuthorityValid(String authority, int userId) {
ArrayMap<String, Boolean> authorityMap = mProvidersPerUserCache.get(userId);
if (authorityMap == null) {
authorityMap = new ArrayMap<>();
mProvidersPerUserCache.put(userId, authorityMap);
}
if (!authorityMap.containsKey(authority)) {
authorityMap.put(authority, mPackageManager.resolveContentProviderAsUser(authority,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId) != null);
}
return authorityMap.get(authority);
}
}
// Primary list of all syncable authorities. Also our global lock. // Primary list of all syncable authorities. Also our global lock.
private final SparseArray<AuthorityInfo> mAuthorities = private final SparseArray<AuthorityInfo> mAuthorities =
new SparseArray<AuthorityInfo>(); new SparseArray<AuthorityInfo>();
@@ -1502,12 +1548,13 @@ public class SyncStorageEngine extends Handler {
eventType = parser.next(); eventType = parser.next();
AuthorityInfo authority = null; AuthorityInfo authority = null;
PeriodicSync periodicSync = null; PeriodicSync periodicSync = null;
AccountAuthorityValidator validator = new AccountAuthorityValidator(mContext);
do { do {
if (eventType == XmlPullParser.START_TAG) { if (eventType == XmlPullParser.START_TAG) {
tagName = parser.getName(); tagName = parser.getName();
if (parser.getDepth() == 2) { if (parser.getDepth() == 2) {
if ("authority".equals(tagName)) { if ("authority".equals(tagName)) {
authority = parseAuthority(parser, version); authority = parseAuthority(parser, version, validator);
periodicSync = null; periodicSync = null;
if (authority != null) { if (authority != null) {
if (authority.ident > highestAuthorityId) { if (authority.ident > highestAuthorityId) {
@@ -1636,7 +1683,8 @@ public class SyncStorageEngine extends Handler {
mMasterSyncAutomatically.put(userId, listen); mMasterSyncAutomatically.put(userId, listen);
} }
private AuthorityInfo parseAuthority(XmlPullParser parser, int version) { private AuthorityInfo parseAuthority(XmlPullParser parser, int version,
AccountAuthorityValidator validator) {
AuthorityInfo authority = null; AuthorityInfo authority = null;
int id = -1; int id = -1;
try { try {
@@ -1676,21 +1724,26 @@ public class SyncStorageEngine extends Handler {
if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) { if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
Slog.v(TAG_FILE, "Creating authority entry"); Slog.v(TAG_FILE, "Creating authority entry");
} }
EndPoint info = null;
if (accountName != null && authorityName != null) { if (accountName != null && authorityName != null) {
info = new EndPoint( EndPoint info = new EndPoint(
new Account(accountName, accountType), new Account(accountName, accountType),
authorityName, userId); authorityName, userId);
} if (validator.isAccountValid(info.account, userId)
if (info != null) { && validator.isAuthorityValid(authorityName, userId)) {
authority = getOrCreateAuthorityLocked(info, id, false); authority = getOrCreateAuthorityLocked(info, id, false);
// If the version is 0 then we are upgrading from a file format that did not // If the version is 0 then we are upgrading from a file format that did not
// know about periodic syncs. In that case don't clear the list since we // know about periodic syncs. In that case don't clear the list since we
// want the default, which is a daily periodic sync. // want the default, which is a daily periodic sync.
// Otherwise clear out this default list since we will populate it later with // Otherwise clear out this default list since we will populate it later
// the periodic sync descriptions that are read from the configuration file. // with
if (version > 0) { // the periodic sync descriptions that are read from the configuration file.
authority.periodicSyncs.clear(); if (version > 0) {
authority.periodicSyncs.clear();
}
} else {
EventLog.writeEvent(0x534e4554, "35028827", -1,
"account:" + info.account + " provider:" + authorityName + " user:"
+ userId);
} }
} }
} }