Add methods for directly setting Contact header data.

Previously, ContactHeaderWidget only allow data binding
through helper methods, or a single static call.  In the
Contacts edit UI, we need to set individual fields directly
based on internal EntityDelta states.  Also added more
documentation and exposed more-direct query helpers.
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
index 462143f..85f7ae8 100644
--- a/core/java/com/android/internal/widget/ContactHeaderWidget.java
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.widget;
 
+import android.Manifest;
 import android.content.AsyncQueryHandler;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -51,8 +52,14 @@
 
 import com.android.internal.R;
 
-
-/* Widget that is used across system apps for displaying a header banner with contact info */
+/**
+ * Header used across system for displaying a title bar with contact info. You
+ * can bind specific values on the header, or use helper methods like
+ * {@link #bindFromContactId(long)} to populate asynchronously.
+ * <p>
+ * The parent must request the {@link Manifest.permission#READ_CONTACTS}
+ * permission to access contact data.
+ */
 public class ContactHeaderWidget extends FrameLayout implements View.OnClickListener,
         View.OnLongClickListener {
 
@@ -74,6 +81,9 @@
 
     protected ContentResolver mContentResolver;
 
+    /**
+     * Interface for callbacks invoked when the user interacts with a header.
+     */
     public interface ContactHeaderListener {
         public void onPhotoLongClick(View view);
         public void onDisplayNameLongClick(View view);
@@ -169,6 +179,9 @@
         mQueryHandler = new QueryHandler(mContentResolver);
     }
 
+    /**
+     * Set the given {@link ContactHeaderListener} to handle header events.
+     */
     public void setContactHeaderListener(ContactHeaderListener listener) {
         mListener = listener;
     }
@@ -222,24 +235,6 @@
         }
     }
 
-
-    /** {@inheritDoc} */
-    public void onQueryComplete(int token, Object cookie, Cursor cursor) {
-        try{
-            if (token == TOKEN_CONTACT_INFO) {
-                bindContactInfo(cursor);
-                invalidate();
-            } else if (token == TOKEN_SOCIAL) {
-                bindSocial(cursor);
-                invalidate();
-            }
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-    }
-
     /**
      * Turn on/off showing of the star element.
      */
@@ -248,6 +243,40 @@
     }
 
     /**
+     * Manually set the starred state of this header widget. This doesn't change
+     * the underlying {@link Contacts} value, only the UI state.
+     */
+    public void setStared(boolean starred) {
+        mStarredView.setChecked(starred);
+    }
+
+    /**
+     * Manually set the photo to display in the header. This doesn't change the
+     * underlying {@link Contacts}, only the UI state.
+     */
+    public void setPhoto(Bitmap bitmap) {
+        mPhotoView.setImageBitmap(bitmap);
+    }
+
+    /**
+     * Manually set the display name and phonetic name to show in the header.
+     * This doesn't change the underlying {@link Contacts}, only the UI state.
+     */
+    public void setDisplayName(CharSequence displayName, CharSequence phoneticName) {
+        mDisplayNameView.setText(displayName);
+        if (mPhoneticNameView != null) {
+            mPhoneticNameView.setText(phoneticName);
+        }
+    }
+
+    /**
+     * Manually set the social snippet text to display in the header.
+     */
+    public void setSocialSnippet(CharSequence snippet) {
+        mStatusView.setText(snippet);
+    }
+
+    /**
      * Convenience method for binding all available data from an existing
      * contact.
      *
@@ -256,10 +285,29 @@
     public void bindFromContactId(long contactId) {
         mContactId = contactId;
         mContactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, mContactId);
-        mContactSummaryUri = ContentUris.withAppendedId(Contacts.CONTENT_SUMMARY_URI, mContactId);
-        mStatusUri = ContentUris.withAppendedId(
-                SocialContract.Activities.CONTENT_CONTACT_STATUS_URI, mContactId);
-        redrawHeader();
+
+        bindSummaryUri(ContentUris.withAppendedId(Contacts.CONTENT_SUMMARY_URI, mContactId));
+        bindSocialUri(ContentUris.withAppendedId(Activities.CONTENT_CONTACT_STATUS_URI, mContactId));
+    }
+
+    /**
+     * Convenience method for binding {@link Contacts} header details from a
+     * {@link Contacts#CONTENT_SUMMARY_URI} reference.
+     */
+    public void bindSummaryUri(Uri contactSummary) {
+        mContactSummaryUri = contactSummary;
+        mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, mContactSummaryUri, HEADER_PROJECTION,
+                null, null, null);
+    }
+
+    /**
+     * Convenience method for binding {@link Activities} header details from a
+     * {@link Activities#CONTENT_CONTACT_STATUS_URI}.
+     */
+    public void bindSocialUri(Uri contactSocial) {
+        mStatusUri = contactSocial;
+        mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION, null, null,
+                null);
     }
 
     /**
@@ -280,7 +328,7 @@
                 long contactId = c.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX);
                 bindFromContactId(contactId);
             } else {
-                bindStatic(emailAddress, "");
+                setDisplayName(emailAddress, null);
             }
         } finally {
             if (c != null) {
@@ -306,7 +354,7 @@
                 long contactId = c.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX);
                 bindFromContactId(contactId);
             } else {
-                bindStatic(number, "");
+                setDisplayName(number, null);
             }
         } finally {
             if (c != null) {
@@ -315,6 +363,11 @@
         }
     }
 
+    /**
+     * @deprecated use {@link #setDisplayName(CharSequence, CharSequence)} and
+     *             {@link #setSocialSnippet(CharSequence)} instead.
+     */
+    @Deprecated
     public void bindStatic(String main, String secondary) {
         mDisplayNameView.setText(main);
         mStatusView.setText(secondary);
@@ -322,57 +375,39 @@
         mPhotoView.setImageBitmap(loadPlaceholderPhoto(null));
     }
 
-    protected void redrawHeader() {
-        if (mContactSummaryUri != null) {
-            mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, mContactSummaryUri, HEADER_PROJECTION,
-                    null, null, null);
-        }
-
-        if (mStatusUri != null) {
-            mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION,
-                    null, null, null);
-        }
-    }
-
+    /**
+     * Bind the contact details provided by the given {@link Cursor}.
+     */
     protected void bindContactInfo(Cursor c) {
-        if (c == null) {
-            return;
+        if (c == null || !c.moveToFirst()) return;
+
+        // TODO: Bring back phonetic name
+        final String displayName = c.getString(HEADER_DISPLAY_NAME_COLUMN_INDEX);
+        final String phoneticName = null;
+        this.setDisplayName(displayName, null);
+
+        final boolean starred = c.getInt(HEADER_STARRED_COLUMN_INDEX) != 0;
+        mStarredView.setChecked(starred);
+
+        //Set the photo
+        Bitmap photoBitmap = loadContactPhoto(c.getLong(HEADER_PHOTO_ID_COLUMN_INDEX), null);
+        if (photoBitmap == null) {
+            photoBitmap = loadPlaceholderPhoto(null);
         }
-        if (c.moveToFirst()) {
-            //Set name
-            String displayName = c.getString(HEADER_DISPLAY_NAME_COLUMN_INDEX);
-            Log.i(TAG, displayName);
-            mDisplayNameView.setText(displayName);
-            //TODO: Bring back phonetic name
-            /*if (mPhoneticNameView != null) {
-                String phoneticName = c.getString(CONTACT_PHONETIC_NAME_COLUMN);
-                mPhoneticNameView.setText(phoneticName);
-            }*/
+        mPhotoView.setImageBitmap(photoBitmap);
 
-            //Set starred
-            mStarredView.setChecked(c.getInt(HEADER_STARRED_COLUMN_INDEX) == 1);
-
-            //Set the photo
-            Bitmap photoBitmap = loadContactPhoto(c.getLong(HEADER_PHOTO_ID_COLUMN_INDEX), null);
-            if (photoBitmap == null) {
-                photoBitmap = loadPlaceholderPhoto(null);
-            }
-            mPhotoView.setImageBitmap(photoBitmap);
-
-            //Set the presence status
-            int presence = c.getInt(HEADER_PRESENCE_STATUS_COLUMN_INDEX);
-            mPresenceView.setImageResource(Presence.getPresenceIconResourceId(presence));
-        }
+        //Set the presence status
+        int presence = c.getInt(HEADER_PRESENCE_STATUS_COLUMN_INDEX);
+        mPresenceView.setImageResource(Presence.getPresenceIconResourceId(presence));
     }
 
+    /**
+     * Bind the social data provided by the given {@link Cursor}.
+     */
     protected void bindSocial(Cursor c) {
-        if (c == null) {
-            return;
-        }
-        if (c.moveToFirst()) {
-            String status = c.getString(SOCIAL_TITLE_COLUMN_INDEX);
-            mStatusView.setText(status);
-        }
+        if (c == null || !c.moveToFirst()) return;
+        final String status = c.getString(SOCIAL_TITLE_COLUMN_INDEX);
+        this.setSocialSnippet(status);
     }
 
     public void onClick(View view) {