Invalidate sources cache when accounts change.
This change listens for AccountManager changes, such as
when an account is added. Fixes http://b/2115977
diff --git a/src/com/android/contacts/model/Sources.java b/src/com/android/contacts/model/Sources.java
index 04fa493..7d06cab 100644
--- a/src/com/android/contacts/model/Sources.java
+++ b/src/com/android/contacts/model/Sources.java
@@ -24,6 +24,7 @@
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
+import android.accounts.OnAccountsUpdatedListener;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -46,10 +47,11 @@
* Singleton holder for all parsed {@link ContactsSource} available on the
* system, typically filled through {@link PackageManager} queries.
*/
-public class Sources extends BroadcastReceiver {
+public class Sources extends BroadcastReceiver implements OnAccountsUpdatedListener {
private static final String TAG = "Sources";
- private Context mContext;
+ private Context mApplicationContext;
+ private AccountManager mAccountManager;
private ContactsSource mFallbackSource = null;
@@ -76,13 +78,22 @@
* Internal constructor that only performs initial parsing.
*/
private Sources(Context context) {
- mContext = context;
+ mApplicationContext = context.getApplicationContext();
+ mAccountManager = AccountManager.get(mApplicationContext);
// Create fallback contacts source for on-phone contacts
mFallbackSource = new FallbackSource();
- loadAccounts();
- registerIntentReceivers(context);
+ queryAccounts();
+
+ // Request updates when packages or accounts change
+ final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addDataScheme("package");
+
+ mApplicationContext.registerReceiver(this, filter);
+ mAccountManager.addOnAccountsUpdatedListener(this, null, false);
}
/** @hide exposed for unit tests */
@@ -97,49 +108,50 @@
mKnownPackages.add(source.resPackageName);
}
- private void registerIntentReceivers(Context context) {
- IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addDataScheme("package");
-
- // We use getApplicationContext() so that the broadcast reciever can stay registered for
- // the length of the application lifetime (instead of the calling activity's lifetime).
- // This is so that we can notified of package changes, and purge the cache accordingly,
- // but not be woken up if the application process isn't already running, since we will
- // have no cache to clear at that point.
- context.getApplicationContext().registerReceiver(this, filter);
- }
-
/** {@inheritDoc} */
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
final String packageName = intent.getData().getSchemeSpecificPart();
- final boolean matchingPackage = mKnownPackages.contains(packageName);
- final boolean validAction = Intent.ACTION_PACKAGE_REMOVED.equals(action)
+ if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
|| Intent.ACTION_PACKAGE_ADDED.equals(action)
- || Intent.ACTION_PACKAGE_CHANGED.equals(action);
-
- if (matchingPackage && validAction) {
- for (ContactsSource source : mSources.values()) {
- if (TextUtils.equals(packageName, source.resPackageName)) {
- // Invalidate any cache for the changed package
- source.invalidateCache();
- }
+ || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+ final boolean knownPackage = mKnownPackages.contains(packageName);
+ if (knownPackage) {
+ // Invalidate cache of existing source
+ invalidateCache(packageName);
+ } else {
+ // Unknown source, so reload from scratch
+ queryAccounts();
}
}
}
+ protected void invalidateCache(String packageName) {
+ for (ContactsSource source : mSources.values()) {
+ if (TextUtils.equals(packageName, source.resPackageName)) {
+ // Invalidate any cache for the changed package
+ source.invalidateCache();
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void onAccountsUpdated(Account[] accounts) {
+ // Refresh to catch any changed accounts
+ queryAccounts();
+ }
+
/**
* Blocking call to load all {@link AuthenticatorDescription} known by the
* {@link AccountManager} on the system.
*/
- protected void loadAccounts() {
+ protected synchronized void queryAccounts() {
mSources.clear();
+ mKnownPackages.clear();
- final AccountManager am = AccountManager.get(mContext);
+ final AccountManager am = mAccountManager;
final IContentService cs = ContentResolver.getContentService();
try {
@@ -200,7 +212,7 @@
* returned may require inflation before they can be used.
*/
public ArrayList<Account> getAccounts(boolean writableOnly) {
- final AccountManager am = AccountManager.get(mContext);
+ final AccountManager am = mAccountManager;
final Account[] accounts = am.getAccounts();
final ArrayList<Account> matching = Lists.newArrayList();
@@ -259,7 +271,7 @@
return source;
} else {
// Not inflated, but requested that we force-inflate
- source.ensureInflated(mContext, inflateLevel);
+ source.ensureInflated(mApplicationContext, inflateLevel);
return source;
}
}