summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Suprabh Shukla <suprabh@google.com> 2017-09-11 22:20:35 +0000
committer Suprabh Shukla <suprabh@google.com> 2017-09-12 15:06:59 -0700
commit271702fc2876ecb98615ab0590f8acd7b6128de4 (patch)
treee27fd3acf123e8c8ddb7e4d1385334483a6effa8
parente1adf2240f6218a2c4eb2c3e853db8c5b685dcab (diff)
Clearing up invalid entries when SyncStorageEngine starts
Fixing the original change which was reverted. Using the available api Context.getSystemService(String) instead of the unavailable Context.getSystemService(Class) Test: cts-tradefed run cts -p android.content.syncmanager Bug: 35028827 This reverts commit 4a9d358448ef150cae259e9c5b5ed1227a1d6d9c. Change-Id: I725430401eaec861f45bb91ee1352bb1307a6915
-rw-r--r--services/core/java/com/android/server/content/SyncStorageEngine.java65
1 files changed, 60 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 6adb37eb334e..deb505f83e7a 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -18,6 +18,7 @@ package com.android.server.content;
import android.accounts.Account;
import android.accounts.AccountAndUser;
+import android.accounts.AccountManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -26,6 +27,7 @@ import android.content.PeriodicSync;
import android.content.SyncInfo;
import android.content.SyncRequest;
import android.content.SyncStatusInfo;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
@@ -404,6 +406,49 @@ public class SyncStorageEngine extends Handler {
public void onSyncRequest(EndPoint info, int reason, Bundle extras);
}
+ /**
+ * 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 = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
+ 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, 0, userId) != null);
+ }
+ return authorityMap.get(authority);
+ }
+ }
+
// Primary list of all syncable authorities. Also our global lock.
private final SparseArray<AuthorityInfo> mAuthorities =
new SparseArray<AuthorityInfo>();
@@ -1862,12 +1907,13 @@ public class SyncStorageEngine extends Handler {
eventType = parser.next();
AuthorityInfo authority = null;
PeriodicSync periodicSync = null;
+ AccountAuthorityValidator validator = new AccountAuthorityValidator(mContext);
do {
if (eventType == XmlPullParser.START_TAG) {
tagName = parser.getName();
if (parser.getDepth() == 2) {
if ("authority".equals(tagName)) {
- authority = parseAuthority(parser, version);
+ authority = parseAuthority(parser, version, validator);
periodicSync = null;
if (authority != null) {
if (authority.ident > highestAuthorityId) {
@@ -2000,7 +2046,8 @@ public class SyncStorageEngine extends Handler {
mMasterSyncAutomatically.put(userId, listen);
}
- private AuthorityInfo parseAuthority(XmlPullParser parser, int version) {
+ private AuthorityInfo parseAuthority(XmlPullParser parser, int version,
+ AccountAuthorityValidator validator) {
AuthorityInfo authority = null;
int id = -1;
try {
@@ -2045,12 +2092,22 @@ public class SyncStorageEngine extends Handler {
info = new EndPoint(
new Account(accountName, accountType),
authorityName, userId);
+ if (validator.isAccountValid(info.account, userId)
+ && validator.isAuthorityValid(authorityName, userId)) {
+ authority = getOrCreateAuthorityLocked(info, id, false);
+ } else {
+ EventLog.writeEvent(0x534e4554, "35028827", -1,
+ "account:" + info.account + " provider:" + authorityName + " user:"
+ + userId);
+ }
} else {
info = new EndPoint(
new ComponentName(packageName, className),
userId);
+ authority = getOrCreateAuthorityLocked(info, id, false);
}
- authority = getOrCreateAuthorityLocked(info, id, false);
+ }
+ if (authority != null) {
// 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
// want the default, which is a daily periodic sync.
@@ -2059,8 +2116,6 @@ public class SyncStorageEngine extends Handler {
if (version > 0) {
authority.periodicSyncs.clear();
}
- }
- if (authority != null) {
authority.enabled = enabled == null || Boolean.parseBoolean(enabled);
if ("unknown".equals(syncable)) {
authority.syncable = -1;