Update smart dial results after adding contact.

+ Add a URI for smart dial database updates, and notify this URI
with the content resolver after finishing an update.

+ Add a content observer to the SmartDialCursorLoader, to force a
reload of its contents when notified.

Bug: 19372539
Change-Id: I963d0d0fcb519e672f580ea8d33dc80d0c3f7799
diff --git a/src/com/android/dialer/database/DialerDatabaseHelper.java b/src/com/android/dialer/database/DialerDatabaseHelper.java
index 511c2a7..2177878 100644
--- a/src/com/android/dialer/database/DialerDatabaseHelper.java
+++ b/src/com/android/dialer/database/DialerDatabaseHelper.java
@@ -93,6 +93,9 @@
         static final String PROPERTIES = "properties";
     }
 
+    public static final Uri SMART_DIAL_UPDATED_URI =
+            Uri.parse("content://com.android.dialer/smart_dial_updated");
+
     public interface SmartDialDbColumns {
         static final String _ID = "id";
         static final String DATA_ID = "data_id";
@@ -893,6 +896,9 @@
             final SharedPreferences.Editor editor = databaseLastUpdateSharedPref.edit();
             editor.putLong(LAST_UPDATED_MILLIS, currentMillis);
             editor.commit();
+
+            // Notify content observers that smart dial database has been updated.
+            mContext.getContentResolver().notifyChange(SMART_DIAL_UPDATED_URI, null, false);
         }
     }
 
diff --git a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
index d01776c..372692e 100644
--- a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
+++ b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
@@ -18,8 +18,10 @@
 
 import android.content.AsyncTaskLoader;
 import android.content.Context;
+import android.content.Loader.ForceLoadContentObserver;
 import android.database.Cursor;
 import android.database.MatrixCursor;
+import android.net.Uri;
 import android.util.Log;
 
 import com.android.contacts.common.list.PhoneNumberListAdapter.PhoneQuery;
@@ -44,6 +46,8 @@
     private String mQuery;
     private SmartDialNameMatcher mNameMatcher;
 
+    private ForceLoadContentObserver mObserver;
+
     public SmartDialCursorLoader(Context context) {
         super(context);
         mContext = context;
@@ -110,6 +114,12 @@
         Cursor oldCursor = mCursor;
         mCursor = cursor;
 
+        if (mObserver == null) {
+            mObserver = new ForceLoadContentObserver();
+            mContext.getContentResolver().registerContentObserver(
+                    DialerDatabaseHelper.SMART_DIAL_UPDATED_URI, true, mObserver);
+        }
+
         if (isStarted()) {
             /** If the Loader is in a started state, deliver the results to the client. */
             super.deliverResult(cursor);
@@ -144,6 +154,11 @@
         /** Ensure the loader has been stopped. */
         onStopLoading();
 
+        if (mObserver != null) {
+            mContext.getContentResolver().unregisterContentObserver(mObserver);
+            mObserver = null;
+        }
+
         /** Release all previously saved query results. */
         if (mCursor != null) {
             releaseResources(mCursor);
@@ -155,6 +170,11 @@
     public void onCanceled(Cursor cursor) {
         super.onCanceled(cursor);
 
+        if (mObserver != null) {
+            mContext.getContentResolver().unregisterContentObserver(mObserver);
+            mObserver = null;
+        }
+
         /** The load has been canceled, so we should release the resources associated with 'data'.*/
         releaseResources(cursor);
     }