Merge change Idc34a3f7 into eclair

* changes:
  Fix 2209086: add drawables for SlidingTab states in PhoneApp. Update string file for new SlidingTab sound states. Tweak "animation" to be 250ms based on conversation with ui guys. Some minor performance tweaks to SlidingTab.
diff --git a/api/current.xml b/api/current.xml
index 32d0f1e..13e4c94 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -35279,6 +35279,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_LOCALE_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.LOCALE_CHANGED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_MAIN"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b785dbf..c676a5b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1344,6 +1344,12 @@
      * can not be restarted will need to watch for this action and handle it
      * appropriately.
      * 
+     * <p class="note">
+     * You can <em>not</em> receive this through components declared
+     * in manifests, only by explicitly registering for it with
+     * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
+     * Context.registerReceiver()}.
+     * 
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
      *
@@ -1352,6 +1358,14 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";
     /**
+     * Broadcast Action: The current device's locale has changed.
+     * 
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
+    /**
      * Broadcast Action:  This is a <em>sticky broadcast</em> containing the
      * charging state, level, and other information about the battery.
      * See {@link android.os.BatteryManager} for documentation on the
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 87da55f..b94bb51 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -309,15 +309,22 @@
 
     public void dump(Printer pw, String prefix) {
         super.dumpFront(pw, prefix);
-        pw.println(prefix + "permission=" + permission);
+        if (permission != null) {
+            pw.println(prefix + "permission=" + permission);
+        }
         pw.println(prefix + "taskAffinity=" + taskAffinity
                 + " targetActivity=" + targetActivity);
-        pw.println(prefix + "launchMode=" + launchMode
-                + " flags=0x" + Integer.toHexString(flags)
-                + " theme=0x" + Integer.toHexString(theme));
-        pw.println(prefix + "screenOrientation=" + screenOrientation
-                + " configChanges=0x" + Integer.toHexString(configChanges)
-                + " softInputMode=0x" + Integer.toHexString(softInputMode));
+        if (launchMode != 0 || flags != 0 || theme != 0) {
+            pw.println(prefix + "launchMode=" + launchMode
+                    + " flags=0x" + Integer.toHexString(flags)
+                    + " theme=0x" + Integer.toHexString(theme));
+        }
+        if (screenOrientation != SCREEN_ORIENTATION_UNSPECIFIED
+                || configChanges != 0 || softInputMode != 0) {
+            pw.println(prefix + "screenOrientation=" + screenOrientation
+                    + " configChanges=0x" + Integer.toHexString(configChanges)
+                    + " softInputMode=0x" + Integer.toHexString(softInputMode));
+        }
         super.dumpBack(pw, prefix);
     }
     
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 7a65af8..1800c30 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -270,21 +270,31 @@
 
     public void dump(Printer pw, String prefix) {
         super.dumpFront(pw, prefix);
-        pw.println(prefix + "className=" + className);
-        pw.println(prefix + "permission=" + permission
-                + " uid=" + uid);
-        pw.println(prefix + "taskAffinity=" + taskAffinity);
-        pw.println(prefix + "theme=0x" + Integer.toHexString(theme));
+        if (className != null) {
+            pw.println(prefix + "className=" + className);
+        }
+        if (permission != null) {
+            pw.println(prefix + "permission=" + permission);
+        }
+        pw.println(prefix + "uid=" + uid + " taskAffinity=" + taskAffinity);
+        if (theme != 0) {
+            pw.println(prefix + "theme=0x" + Integer.toHexString(theme));
+        }
         pw.println(prefix + "flags=0x" + Integer.toHexString(flags)
                 + " processName=" + processName);
         pw.println(prefix + "sourceDir=" + sourceDir);
         pw.println(prefix + "publicSourceDir=" + publicSourceDir);
-        pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
         pw.println(prefix + "dataDir=" + dataDir);
-        pw.println(prefix + "targetSdkVersion=" + targetSdkVersion);
-        pw.println(prefix + "enabled=" + enabled);
-        pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
-        pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
+        if (sharedLibraryFiles != null) {
+            pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
+        }
+        pw.println(prefix + "enabled=" + enabled + " targetSdkVersion=" + targetSdkVersion);
+        if (manageSpaceActivityName != null) {
+            pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
+        }
+        if (descriptionRes != 0) {
+            pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
+        }
         super.dumpBack(pw, prefix);
     }
     
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 46e7ca43..8043dae 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -141,11 +141,15 @@
     }
     
     protected void dumpFront(Printer pw, String prefix) {
-        pw.println(prefix + "name=" + name);
+        if (name != null) {
+            pw.println(prefix + "name=" + name);
+        }
         pw.println(prefix + "packageName=" + packageName);
-        pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
-                + " nonLocalizedLabel=" + nonLocalizedLabel
-                + " icon=0x" + Integer.toHexString(icon));
+        if (labelRes != 0 || nonLocalizedLabel != null || icon != 0) {
+            pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
+                    + " nonLocalizedLabel=" + nonLocalizedLabel
+                    + " icon=0x" + Integer.toHexString(icon));
+        }
     }
     
     protected void dumpBack(Printer pw, String prefix) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 7904401..c3b0f1c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -29,6 +29,7 @@
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.RemoteException;
+import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.view.View;
@@ -37,8 +38,59 @@
 import java.io.InputStream;
 
 /**
- * The contract between the contacts provider and applications. Contains definitions
- * for the supported URIs and columns. These APIs supersede {@link Contacts}.
+ * <p>
+ * The contract between the contacts provider and applications. Contains
+ * definitions for the supported URIs and columns. These APIs supersede
+ * {@link Contacts}.
+ * </p>
+ * <h3>Overview</h3>
+ * <p>
+ * ContactsContract defines an extensible database of contact-related
+ * information. Contact information is stored in a three-tier data model:
+ * </p>
+ * <blockquote>
+ * <p>
+ * The {@link Data} table contains all kinds of personal data: phone numbers,
+ * email addresses etc. The list of data kinds that can be stored in this table
+ * is open-ended. There is a predefined set of common kinds, but any application
+ * can add its own data kinds.
+ * </p>
+ * <p>
+ * A row in the {@link RawContacts} table represents a set of Data describing a
+ * person and associated with a single account.
+ * </p>
+ * <p>
+ * A row in the {@link Contacts} table represents an aggregate of one or more
+ * RawContacts presumably describing the same person.
+ * </p>
+ * </blockquote>
+ * <p>
+ * Other tables include:
+ * </p>
+ * <blockquote>
+ * <p>
+ * {@link Groups}, which contains information about raw contact groups - the
+ * current API does not support the notion of groups spanning multiple accounts.
+ * </p>
+ * <p>
+ * {@link StatusUpdates}, which contains social status updates including IM
+ * availability.
+ * </p>
+ * <p>
+ * {@link AggregationExceptions}, which is used for manual aggregation and
+ * disaggregation of raw contacts
+ * </p>
+ * <p>
+ * {@link Settings}, which contains visibility and sync settings for accounts
+ * and groups.
+ * </p>
+ * <p>
+ * {@link SyncState}, which contains free-form data maintained on behalf of sync
+ * adapters
+ * </p>
+ * <p>
+ * {@link PhoneLookup}, which is used for quick caller-ID lookup</id>
+ * </blockquote>
  */
 @SuppressWarnings("unused")
 public final class ContactsContract {
@@ -128,6 +180,9 @@
      * Generic columns for use by sync adapters. The specific functions of
      * these columns are private to the sync adapter. Other clients of the API
      * should not attempt to either read or write this column.
+     *
+     * @see RawContacts
+     * @see Groups
      */
     protected interface BaseSyncColumns {
 
@@ -144,6 +199,9 @@
     /**
      * Columns that appear when each row of a table belongs to a specific
      * account, including sync information that an account may need.
+     *
+     * @see RawContacts
+     * @see Groups
      */
     protected interface SyncColumns extends BaseSyncColumns {
         /**
@@ -181,6 +239,13 @@
         public static final String DIRTY = "dirty";
     }
 
+    /**
+     * @see Contacts
+     * @see RawContacts
+     * @see ContactsContract.Data
+     * @see PhoneLookup
+     * @see ContactsContract.Contacts.AggregationSuggestions
+     */
     protected interface ContactOptionsColumns {
         /**
          * The number of times a contact has been contacted
@@ -214,6 +279,12 @@
         public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
     }
 
+    /**
+     * @see Contacts
+     * @see ContactsContract.Data
+     * @see PhoneLookup
+     * @see ContactsContract.Contacts.AggregationSuggestions
+     */
     protected interface ContactsColumns {
         /**
          * The display name for the contact.
@@ -247,6 +318,9 @@
         public static final String LOOKUP_KEY = "lookup";
     }
 
+    /**
+     * @see Contacts
+     */
     protected interface ContactStatusColumns {
         /**
          * Contact presence status. See {@link StatusUpdates} for individual status
@@ -270,7 +344,7 @@
 
         /**
          * The package containing resources for this status: label and icon.
-         * <p>Type: NUMBER</p>
+         * <p>Type: TEXT</p>
          */
         public static final String CONTACT_STATUS_RES_PACKAGE = "contact_status_res_package";
 
@@ -291,8 +365,194 @@
     }
 
     /**
-     * Constants for the contacts table, which contains a record per group
+     * Constants for the contacts table, which contains a record per aggregate
      * of raw contacts representing the same person.
+     * <h3>Operations</h3>
+     * <dl>
+     * <dt><b>Insert</b></dt>
+     * <dd>A Contact cannot be created explicitly. When a raw contact is
+     * inserted, the provider will first try to find a Contact representing the
+     * same person. If one is found, the raw contact's
+     * {@link RawContacts#CONTACT_ID} column gets the _ID of the aggregate
+     * Contact. If no match is found, the provider automatically inserts a new
+     * Contact and puts its _ID into the {@link RawContacts#CONTACT_ID} column
+     * of the newly inserted raw contact.</dd>
+     * <dt><b>Update</b></dt>
+     * <dd>Only certain columns of Contact are modifiable:
+     * {@link #TIMES_CONTACTED}, {@link #LAST_TIME_CONTACTED}, {@link #STARRED},
+     * {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of
+     * these columns on the Contact also changes them on all constituent raw
+     * contacts.</dd>
+     * <dt><b>Delete</b></dt>
+     * <dd>Be careful with deleting Contacts! Deleting an aggregate contact
+     * deletes all constituent raw contacts. The corresponding sync adapters
+     * will notice the deletions of their respective raw contacts and remove
+     * them from their back end storage.</dd>
+     * <dt><b>Query</b></dt>
+     * <dd>
+     * <ul>
+     * <li>If you need to read an individual contact, consider using
+     * {@link #CONTENT_LOOKUP_URI} instead of {@link #CONTENT_URI}.</li>
+     * <li>If you need to look up a contact by the phone number, use
+     * {@link PhoneLookup#CONTENT_FILTER_URI PhoneLookup.CONTENT_FILTER_URI},
+     * which is optimized for this purpose.</li>
+     * <li>If you need to look up a contact by partial name, e.g. to produce
+     * filter-as-you-type suggestions, use the {@link #CONTENT_FILTER_URI} URI.
+     * <li>If you need to look up a contact by some data element like email
+     * address, nickname, etc, use a query against the {@link ContactsContract.Data} table.
+     * The result will contain contact ID, name etc.
+     * </ul>
+     * </dd>
+     * </dl>
+     * <h2>Columns</h2>
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Contacts</th>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #_ID}</td>
+     * <td>read-only</td>
+     * <td>Row ID. Consider using {@link #LOOKUP_KEY} instead.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #LOOKUP_KEY}</td>
+     * <td>read-only</td>
+     * <td>An opaque value that contains hints on how to find the contact if its
+     * row id changed as a result of a sync or aggregation.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #DISPLAY_NAME}</td>
+     * <td>read-only</td>
+     * <td>The display name for the contact. During aggregation display name is
+     * computed from display names of constituent raw contacts using a
+     * heuristic: a longer name or a name with more diacritic marks or more
+     * upper case characters is chosen.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #PHOTO_ID}</td>
+     * <td>read-only</td>
+     * <td>Reference to the row in the {@link ContactsContract.Data} table holding the photo.
+     * That row has the mime type
+     * {@link CommonDataKinds.Photo#CONTENT_ITEM_TYPE}. The value of this field
+     * is computed automatically based on the
+     * {@link CommonDataKinds.Photo#IS_SUPER_PRIMARY} field of the data rows of
+     * that mime type.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #IN_VISIBLE_GROUP}</td>
+     * <td>read-only</td>
+     * <td>An indicator of whether this contact is supposed to be visible in the
+     * UI. "1" if the contact has at least one raw contact that belongs to a
+     * visible group; "0" otherwise.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #HAS_PHONE_NUMBER}</td>
+     * <td>read-only</td>
+     * <td>An indicator of whether this contact has at least one phone number.
+     * "1" if there is at least one phone number, "0" otherwise.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #TIMES_CONTACTED}</td>
+     * <td>read/write</td>
+     * <td>The number of times the contact has been contacted. See
+     * {@link #markAsContacted}. When raw contacts are aggregated, this field is
+     * computed automatically as the maximum number of times contacted among all
+     * constituent raw contacts. Setting this field automatically changes the
+     * corresponding field on all constituent raw contacts.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #LAST_TIME_CONTACTED}</td>
+     * <td>read/write</td>
+     * <td>The timestamp of the last time the contact was contacted. See
+     * {@link #markAsContacted}. Setting this field also automatically
+     * increments {@link #TIMES_CONTACTED}. When raw contacts are aggregated,
+     * this field is computed automatically as the latest time contacted of all
+     * constituent raw contacts. Setting this field automatically changes the
+     * corresponding field on all constituent raw contacts.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #STARRED}</td>
+     * <td>read/write</td>
+     * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise.
+     * When raw contacts are aggregated, this field is automatically computed:
+     * if any constituent raw contacts are starred, then this field is set to
+     * '1'. Setting this field automatically changes the corresponding field on
+     * all constituent raw contacts.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CUSTOM_RINGTONE}</td>
+     * <td>read/write</td>
+     * <td>A custom ringtone associated with a contact. Typically this is the
+     * URI returned by an activity launched with the
+     * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #SEND_TO_VOICEMAIL}</td>
+     * <td>read/write</td>
+     * <td>An indicator of whether calls from this contact should be forwarded
+     * directly to voice mail ('1') or not ('0'). When raw contacts are
+     * aggregated, this field is automatically computed: if <i>all</i>
+     * constituent raw contacts have SEND_TO_VOICEMAIL=1, then this field is set
+     * to '1'. Setting this field automatically changes the corresponding field
+     * on all constituent raw contacts.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #CONTACT_PRESENCE}</td>
+     * <td>read-only</td>
+     * <td>Contact IM presence status. See {@link StatusUpdates} for individual
+     * status definitions. Automatically computed as the highest presence of all
+     * constituent raw contacts. The provider may choose not to store this value
+     * in persistent storage. The expectation is that presence status will be
+     * updated on a regular basic.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CONTACT_STATUS}</td>
+     * <td>read-only</td>
+     * <td>Contact's latest status update. Automatically computed as the latest
+     * of all constituent raw contacts' status updates.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td>
+     * <td>read-only</td>
+     * <td>The absolute time in milliseconds when the latest status was
+     * inserted/updated.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td>
+     * <td>read-only</td>
+     * <td> The package containing resources for this status: label and icon.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_STATUS_LABEL}</td>
+     * <td>read-only</td>
+     * <td>The resource ID of the label describing the source of contact status,
+     * e.g. "Google Talk". This resource is scoped by the
+     * {@link #CONTACT_STATUS_RES_PACKAGE}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_STATUS_ICON}</td>
+     * <td>read-only</td>
+     * <td>The resource ID of the icon for the source of contact status. This
+     * resource is scoped by the {@link #CONTACT_STATUS_RES_PACKAGE}.</td>
+     * </tr>
+     * </table>
      */
     public static class Contacts implements BaseColumns, ContactsColumns,
             ContactOptionsColumns, ContactStatusColumns {
@@ -365,7 +625,7 @@
 
         /**
          * Build a {@link #CONTENT_LOOKUP_URI} lookup {@link Uri} using the
-         * given {@link android.provider.ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}.
+         * given {@link ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}.
          */
         public static Uri getLookupUri(long contactId, String lookupKey) {
             return ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI,
@@ -423,7 +683,7 @@
 
         /**
          * The content:// style URI for this table joined with useful data from
-         * {@link Data}, filtered to include only starred contacts
+         * {@link ContactsContract.Data}, filtered to include only starred contacts
          * and the most frequently contacted contacts.
          */
         public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath(
@@ -461,7 +721,7 @@
 
         /**
          * A sub-directory of a single contact that contains all of the constituent raw contact
-         * {@link Data} rows.
+         * {@link ContactsContract.Data} rows.
          */
         public static final class Data implements BaseColumns, DataColumns {
             /**
@@ -476,10 +736,33 @@
         }
 
         /**
-         * A sub-directory of a single contact aggregate that contains all aggregation suggestions
-         * (other contacts).  The aggregation suggestions are computed based on approximate
-         * data matches with this contact.
+         * <p>
+         * A <i>read-only</i> sub-directory of a single contact aggregate that
+         * contains all aggregation suggestions (other contacts). The
+         * aggregation suggestions are computed based on approximate data
+         * matches with this contact.
+         * </p>
+         * <p>
+         * <i>Note: this query may be expensive! If you need to use it in bulk,
+         * make sure the user experience is acceptable when the query runs for a
+         * long time.</i>
+         * <p>
+         * Usage example:
+         *
+         * <pre>
+         * Uri uri = Contacts.CONTENT_URI.buildUpon()
+         *          .appendEncodedPath(String.valueOf(contactId))
+         *          .appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY)
+         *          .appendQueryParameter(&quot;limit&quot;, &quot;3&quot;)
+         *          .build()
+         * Cursor cursor = getContentResolver().query(suggestionsUri,
+         *          new String[] {Contacts.DISPLAY_NAME, Contacts._ID, Contacts.LOOKUP_KEY},
+         *          null, null, null);
+         * </pre>
+         *
+         * </p>
          */
+        // TODO: add ContactOptionsColumns, ContactStatusColumns
         public static final class AggregationSuggestions implements BaseColumns, ContactsColumns {
             /**
              * No public constructor since this is a utility class
@@ -495,8 +778,40 @@
         }
 
         /**
-         * A sub-directory of a single contact that contains the contact's primary photo.
+         * A <i>read-only</i> sub-directory of a single contact that contains
+         * the contact's primary photo.
+         * <p>
+         * Usage example:
+         *
+         * <pre>
+         * public InputStream openPhoto(long contactId) {
+         *     Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
+         *     Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
+         *     Cursor cursor = getContentResolver().query(photoUri,
+         *          new String[] {Contacts.Photo.PHOTO}, null, null, null);
+         *     if (cursor == null) {
+         *         return null;
+         *     }
+         *     try {
+         *         if (cursor.moveToFirst()) {
+         *             byte[] data = cursor.getBlob(0);
+         *             if (data != null) {
+         *                 return new ByteArrayInputStream(data);
+         *             }
+         *         }
+         *     } finally {
+         *         cursor.close();
+         *     }
+         *     return null;
+         * }
+         * </pre>
+         *
+         * </p>
+         * <p>You should also consider using the convenience method
+         * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri)}
+         * </p>
          */
+        // TODO: change DataColumns to DataColumnsWithJoins
         public static final class Photo implements BaseColumns, DataColumns {
             /**
              * no public constructor since this is a utility class
@@ -507,6 +822,15 @@
              * The directory twig for this sub-table
              */
             public static final String CONTENT_DIRECTORY = "photo";
+
+            /**
+             * Thumbnail photo of the raw contact. This is the raw bytes of an image
+             * that could be inflated using {@link android.graphics.BitmapFactory}.
+             * <p>
+             * Type: BLOB
+             * @hide TODO: Unhide in a separate CL
+             */
+            public static final String PHOTO = DATA15;
         }
 
         /**
@@ -542,7 +866,7 @@
 
     protected interface RawContactsColumns {
         /**
-         * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} that this
+         * A reference to the {@link ContactsContract.Contacts#_ID} that this
          * data belongs to.
          * <P>Type: INTEGER</P>
          */
@@ -580,6 +904,315 @@
      * Constants for the raw contacts table, which contains the base contact
      * information per sync source. Sync adapters and contact management apps
      * are the primary consumers of this API.
+     * <h3>Operations</h3>
+     * <dl>
+     * <dt><b>Insert</b></dt>
+     * <dd>There are two mechanisms that can be used to insert a raw contact: incremental and
+     * batch. The incremental method is more traditional but less efficient.  It should be used
+     * only if the constituent data rows are unavailable at the time the raw contact is created:
+     * <pre>
+     * ContentValues values = new ContentValues();
+     * values.put(RawContacts.ACCOUNT_TYPE, accountType);
+     * values.put(RawContacts.ACCOUNT_NAME, accountName);
+     * Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values);
+     * long rawContactId = ContentUris.parseId(rawContactUri);
+     * </pre>
+     * <p>
+     * Once data rows are available, insert those.  For example, here's how you would insert
+     * a name:
+     *
+     * <pre>
+     * values.clear();
+     * values.put(Data.RAW_CONTACT_ID, rawContactId);
+     * values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+     * values.put(StructuredName.DISPLAY_NAME, &quot;Mike Sullivan&quot;);
+     * getContentResolver().insert(Data.CONTENT_URI, values);
+     * </pre>
+     * </p>
+     * <p>
+     * The batch method is by far preferred.  It inserts the raw contact and its
+     * constituent data rows in a single database transaction
+     * and causes at most one aggregation pass.
+     * <pre>
+     * ArrayList&lt;ContentProviderOperation&gt; ops = Lists.newArrayList();
+     * int rawContactInsertIndex = ops.size();
+     * ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
+     *          .withValue(RawContacts.ACCOUNT_TYPE, accountType)
+     *          .withValue(RawContacts.ACCOUNT_NAME, accountName)
+     *          .build());
+     *
+     * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
+     *          .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex)
+     *          .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
+     *          .withValue(StructuredName.DISPLAY_NAME, &quot;Mike Sullivan&quot;)
+     *          .build());
+     *
+     * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+     * </pre>
+     * </p>
+     * <p>
+     * Please note the use of back reference in the construction of the
+     * {@link ContentProviderOperation}. It allows an operation to use the result of
+     * a previous operation by referring to it by its index in the batch.
+     * </p>
+     * <dt><b>Update</b></dt>
+     * <dd><p>Just as with insert, the update can be done incrementally or as a batch, the
+     * batch mode being the preferred method.</p></dd>
+     * <dt><b>Delete</b></dt>
+     * <dd><p>When a raw contact is deleted, all of its Data rows as well as StatusUpdates,
+     * AggregationExceptions, PhoneLookup rows are deleted automatically. When all raw
+     * contacts in a Contact are deleted, the Contact itself is also deleted automatically.
+     * </p>
+     * <p>
+     * The invocation of {@code resolver.delete(...)}, does not physically delete
+     * a raw contacts row. It sets the {@link #DELETED} flag on the raw contact and
+     * removes the raw contact from its aggregate contact.
+     * The sync adapter then deletes the raw contact from the server and
+     * finalizes phone-side deletion by calling {@code resolver.delete(...)}
+     * again and passing the {@link #CALLER_IS_SYNCADAPTER} query parameter.<p>
+     * <p>Some sync adapters are read-only, meaning that they only sync server-side
+     * changes to the phone, but not the reverse.  If one of those raw contacts
+     * is marked for deletion, it will remain on the phone.  However it will be
+     * effectively invisible, because it will not be part of any aggregate contact.
+     * </dd>
+     * <dt><b>Query</b></dt>
+     * <dd>
+     * <p>
+     * Finding all raw contacts in a Contact is easy:
+     * <pre>
+     * Cursor c = getContentResolver().query(RawContacts.CONTENT_URI,
+     *          new String[]{RawContacts._ID},
+     *          RawContacts.CONTACT_ID + "=?",
+     *          new String[]{String.valueOf(contactId)}, null);
+     * </pre>
+     * </p>
+     * <p>
+     * There are two ways to find raw contacts within a specific account,
+     * you can either put the account name and type in the selection or pass them as query
+     * parameters.  The latter approach is preferable, especially when you can reuse the
+     * URI:
+     * <pre>
+     * Uri rawContactUri = RawContacts.URI.buildUpon()
+     *          .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName)
+     *          .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType)
+     *          .build();
+     * Cursor c1 = getContentResolver().query(rawContactUri,
+     *          RawContacts.STARRED + "&lt;&gt;0", null, null, null);
+     * ...
+     * Cursor c2 = getContentResolver().query(rawContactUri,
+     *          RawContacts.DELETED + "&lt;&gt;0", null, null, null);
+     * </pre>
+     * </p>
+     * <p>The best way to read a raw contact along with all the data associated with it is
+     * by using the {@link Entity} directory. If the raw contact has data rows,
+     * the Entity cursor will contain a row for each data row.  If the raw contact has no
+     * data rows, the cursor will still contain one row with the raw contact-level information.
+     * <pre>
+     * Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
+     * Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);
+     * Cursor c = getContentResolver().query(entityUri,
+     *          new String[]{RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1},
+     *          null, null, null);
+     * try {
+     *     while (c.moveToNext()) {
+     *         String sourceId = c.getString(0);
+     *         if (!c.isNull(1)) {
+     *             String mimeType = c.getString(2);
+     *             String data = c.getString(3);
+     *             ...
+     *         }
+     *     }
+     * } finally {
+     *     c.close();
+     * }
+     * </pre>
+     * </p>
+     * </dd>
+     * </dl>
+     * <h3>Aggregation</h3>
+     * <p>
+     * As soon as a raw contact is inserted or whenever its constituent data
+     * changes, the provider will check if the raw contact matches other
+     * existing raw contacts and if so will aggregate it with those. From the
+     * data standpoint, aggregation is reflected in the change of the
+     * {@link #CONTACT_ID} field, which is the reference to the aggregate contact.
+     * </p>
+     * <p>
+     * See also {@link AggregationExceptions} for a mechanism to control
+     * aggregation programmatically.
+     * </p>
+     * <h2>Columns</h2>
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>RawContacts</th>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #_ID}</td>
+     * <td>read-only</td>
+     * <td>Row ID. Sync adapter should try to preserve row IDs during updates. In other words,
+     * it would be a really bad idea to delete and reinsert a raw contact. A sync adapter should
+     * always do an update instead.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_ID}</td>
+     * <td>read-only</td>
+     * <td>A reference to the {@link ContactsContract.Contacts#_ID} that this raw contact belongs
+     * to. Raw contacts are linked to contacts by the aggregation process, which can be controlled
+     * by the {@link #AGGREGATION_MODE} field and {@link AggregationExceptions}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #AGGREGATION_MODE}</td>
+     * <td>read/write</td>
+     * <td>A mechanism that allows programmatic control of the aggregation process. The allowed
+     * values are {@link #AGGREGATION_MODE_DEFAULT}, {@link #AGGREGATION_MODE_DISABLED}
+     * and {@link #AGGREGATION_MODE_SUSPENDED}. See also {@link AggregationExceptions}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #DELETED}</td>
+     * <td>read/write</td>
+     * <td>The "deleted" flag: "0" by default, "1" if the row has been marked
+     * for deletion. When {@link android.content.ContentResolver#delete} is
+     * called on a raw contact, it is marked for deletion and removed from its
+     * aggregate contact. The sync adaptor deletes the raw contact on the server and
+     * then calls ContactResolver.delete once more, this time passing the
+     * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
+     * the data removal.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #TIMES_CONTACTED}</td>
+     * <td>read/write</td>
+     * <td>The number of times the contact has been contacted. To have an effect
+     * on the corresponding value of the aggregate contact, this field
+     * should be set at the time the raw contact is inserted.
+     * See {@link ContactsContract.Contacts#markAsContacted}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #LAST_TIME_CONTACTED}</td>
+     * <td>read/write</td>
+     * <td>The timestamp of the last time the contact was contacted. To have an effect
+     * on the corresponding value of the aggregate contact, this field
+     * should be set at the time the raw contact is inserted.
+     * See {@link ContactsContract.Contacts#markAsContacted}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #STARRED}</td>
+     * <td>read/write</td>
+     * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise.
+     * Changing this field immediately effects the corresponding aggregate contact:
+     * if any raw contacts in that aggregate contact are starred, then the contact
+     * itself is marked as starred.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CUSTOM_RINGTONE}</td>
+     * <td>read/write</td>
+     * <td>A custom ringtone associated with a raw contact. Typically this is the
+     * URI returned by an activity launched with the
+     * {@link android.media.RingtoneManager#ACTION_RINGTONE_PICKER} intent.
+     * To have an effect on the corresponding value of the aggregate contact, this field
+     * should be set at the time the raw contact is inserted. To set a custom
+     * ringtone on a contact, use the field {@link ContactsContract.Contacts#CUSTOM_RINGTONE}
+     * instead.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #SEND_TO_VOICEMAIL}</td>
+     * <td>read/write</td>
+     * <td>An indicator of whether calls from this raw contact should be forwarded
+     * directly to voice mail ('1') or not ('0'). To have an effect
+     * on the corresponding value of the aggregate contact, this field
+     * should be set at the time the raw contact is inserted.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #ACCOUNT_NAME}</td>
+     * <td>read/write-once</td>
+     * <td>The name of the account instance to which this row belongs, which when paired with
+     * {@link #ACCOUNT_TYPE} identifies a specific account. It should be set at the time
+     * the raw contact is inserted and never changed afterwards.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #ACCOUNT_TYPE}</td>
+     * <td>read/write-once</td>
+     * <td>The type of account to which this row belongs, which when paired with
+     * {@link #ACCOUNT_NAME} identifies a specific account. It should be set at the time
+     * the raw contact is inserted and never changed afterwards.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #SOURCE_ID}</td>
+     * <td>read/write</td>
+     * <td>String that uniquely identifies this row to its source account.
+     * Typically it is set at the time the raw contact is inserted and never
+     * changed afterwards. The one notable exception is a new raw contact: it
+     * will have an account name and type, but no source id. This should
+     * indicated to the sync adapter that a new contact needs to be created
+     * server-side and its ID stored in the corresponding SOURCE_ID field on
+     * the phone.
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #VERSION}</td>
+     * <td>read-only</td>
+     * <td>Version number that is updated whenever this row or its related data
+     * changes. This field can be used for optimistic locking of a raw contact.
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #DIRTY}</td>
+     * <td>read/write</td>
+     * <td>Flag indicating that {@link #VERSION} has changed, and this row needs
+     * to be synchronized by its owning account.  The value is set to "1" automatically
+     * whenever the raw contact changes, unless the URI has the
+     * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter specified.
+     * The sync adapter should always supply this query parameter to prevent
+     * unnecessary synchronization: user changes some data on the server,
+     * the sync adapter updates the contact on the phone (without the
+     * CALLER_IS_SYNCADAPTER flag) flag, which sets the DIRTY flag,
+     * which triggers a sync to bring the changes to the server.
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #SYNC1}</td>
+     * <td>read/write</td>
+     * <td>Generic column for use by sync adapters. Content provider
+     * stores this information on behalf of the sync adapter but does not
+     * interpret it in any way.
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #SYNC2}</td>
+     * <td>read/write</td>
+     * <td>Generic column for use by sync adapters.
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #SYNC3}</td>
+     * <td>read/write</td>
+     * <td>Generic column for use by sync adapters.
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #SYNC4}</td>
+     * <td>read/write</td>
+     * <td>Generic column for use by sync adapters.
+     * </td>
+     * </tr>
+     * </table>
      */
     public static final class RawContacts implements BaseColumns, RawContactsColumns,
             ContactOptionsColumns, SyncColumns  {
@@ -613,6 +1246,7 @@
 
         /**
          * Aggregation mode: aggregate at the time the raw contact is inserted/updated.
+         * TODO: deprecate. Aggregation is now synchronous, this value is a no-op
          */
         public static final int AGGREGATION_MODE_IMMEDIATE = 1;
 
@@ -658,8 +1292,9 @@
         }
 
         /**
-         * A sub-directory of a single raw contact that contains all of their {@link Data} rows.
-         * To access this directory append {@link Data#CONTENT_DIRECTORY} to the contact URI.
+         * A sub-directory of a single raw contact that contains all of their
+         * {@link ContactsContract.Data} rows. To access this directory
+         * append {@link Data#CONTENT_DIRECTORY} to the contact URI.
          */
         public static final class Data implements BaseColumns, DataColumns {
             /**
@@ -675,8 +1310,27 @@
         }
 
         /**
-         * A sub-directory of a single raw contact that contains all of their {@link Data} rows.
-         * To access this directory append {@link Entity#CONTENT_DIRECTORY} to the contact URI.
+         * <p>
+         * A sub-directory of a single raw contact that contains all of their
+         * {@link ContactsContract.Data} rows. To access this directory append
+         * {@link Entity#CONTENT_DIRECTORY} to the contact URI. See
+         * {@link RawContactsEntity} for a stand-alone table containing the same
+         * data.
+         * </p>
+         * <p>
+         * The Entity directory is similar to the {@link RawContacts.Data}
+         * directory but with two important differences:
+         * <ul>
+         * <li>Entity has different ID fields: {@link #_ID} for the raw contact
+         * and {@link #DATA_ID} for the data rows.</li>
+         * <li>Entity always contains at least one row, even if there are no
+         * actual data rows. In this case the {@link #DATA_ID} field will be
+         * null.</li>
+         * </ul>
+         * Using Entity should preferred to using two separate queries:
+         * RawContacts followed by Data. The reason is that Entity reads all
+         * data for a raw contact in one transaction, so there is no possibility
+         * of the data changing between the two queries.
          */
         public static final class Entity implements BaseColumns, DataColumns {
             /**
@@ -699,6 +1353,12 @@
         }
     }
 
+    /**
+     * Social status update columns.
+     *
+     * @see StatusUpdates
+     * @see ContactsContract.Data
+     */
     protected interface StatusColumns extends Im.CommonPresenceColumns {
         /**
          * Contact's latest presence level.
@@ -739,6 +1399,11 @@
         public static final String STATUS_ICON = "status_icon";
     }
 
+    /**
+     * Columns in the Data table.
+     *
+     * @see ContactsContract.Data
+     */
     protected interface DataColumns {
         /**
          * The package name to use when creating {@link Resources} objects for
@@ -824,7 +1489,9 @@
     }
 
     /**
-     * Combines all columns returned by {@link Data} table queries.
+     * Combines all columns returned by {@link ContactsContract.Data} table queries.
+     *
+     * @see ContactsContract.Data
      */
     protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns,
         RawContactsColumns, ContactsColumns, ContactOptionsColumns, ContactStatusColumns {
@@ -832,10 +1499,468 @@
     }
 
     /**
-     * Constants for the data table, which contains data points tied to a raw contact.
-     * For example, a phone number or email address. Each row in this table contains a type
-     * definition and some generic columns. Each data type can define the meaning for each of
-     * the generic columns.
+     * <p>
+     * Constants for the data table, which contains data points tied to a raw
+     * contact. For example, a phone number or email address.
+     * </p>
+     * <h3>Data kinds</h3>
+     * <p>
+     * Data is a generic table that can hold all kinds of data. Sync adapters
+     * and applications can introduce their own data kinds. The kind of data
+     * stored in a particular row is determined by the mime type in the row.
+     * Fields from {@link #DATA1} through {@link #DATA15} are generic columns
+     * whose specific use is determined by the kind of data stored in the row.
+     * For example, if the data kind is
+     * {@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}, then DATA1 stores the
+     * phone number, but if the data kind is
+     * {@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}, then DATA1 stores the
+     * email address.
+     * </p>
+     * <p>
+     * ContactsContract defines a small number of common data kinds, e.g.
+     * {@link CommonDataKinds.Phone}, {@link CommonDataKinds.Email} etc. As a
+     * convenience, these classes define data kind specific aliases for DATA1 etc.
+     * For example, {@link CommonDataKinds.Phone Phone.NUMBER} is the same as
+     * {@link ContactsContract.Data Data.DATA1}.
+     * </p>
+     * <p>
+     * {@link #DATA1} is an indexed column and should be used for the data element that is
+     * expected to be most frequently used in query selections. For example, in the
+     * case of a row representing email addresses {@link #DATA1} should probably
+     * be used for the email address itself, while {@link #DATA2} etc can be
+     * used for auxiliary information like type of email address.
+     * <p>
+     * <p>
+     * By convention, {@link #DATA15} is used for storing BLOBs (binary data).
+     * </p>
+     * <p>
+     * Typically you should refrain from introducing new kinds of data for 3rd
+     * party account types. For example, if you add a data row for
+     * "favorite song" to a raw contact owned by a Google account, it will not
+     * get synced to the server, because the Google sync adapter does not know
+     * how to handle this data kind. Thus new data kinds are typically
+     * introduced along with new account types, i.e. new sync adapters.
+     * </p>
+     * <h3>Batch operations</h3>
+     * <p>
+     * Data rows can be inserted/updated/deleted using the traditional
+     * {@link ContentResolver#insert}, {@link ContentResolver#update} and
+     * {@link ContentResolver#delete} methods, however the newer mechanism based
+     * on a batch of {@link ContentProviderOperation} will prove to be a better
+     * choice in almost all cases. All operations in a batch are executed in a
+     * single transaction, which ensures that the phone-side and server-side
+     * state of a raw contact are always consistent. Also, the batch-based
+     * approach is far more efficient: not only are the database operations
+     * faster when executed in a single transaction, but also sending a batch of
+     * commands to the content provider saves a lot of time on context switching
+     * between your process and the process in which the content provider runs.
+     * </p>
+     * <p>
+     * The flip side of using batched operations is that a large batch may lock
+     * up the database for a long time preventing other applications from
+     * accessing data and potentially causing ANRs ("Application Not Responding"
+     * dialogs.)
+     * </p>
+     * <p>
+     * To avoid such lockups of the database, make sure to insert "yield points"
+     * in the batch. A yield point indicates to the content provider that before
+     * executing the next operation it can commit the changes that have already
+     * been made, yield to other requests, open another transaction and continue
+     * processing operations. A yield point will not automatically commit the
+     * transaction, but only if there is another request waiting on the
+     * database. Normally a sync adapter should insert a yield point at the
+     * beginning of each raw contact operation sequence in the batch. See
+     * {@link ContentProviderOperation.Builder#withYieldAllowed(boolean)}.
+     * </p>
+     * <h3>Operations</h3>
+     * <dl>
+     * <dt><b>Insert</b></dt>
+     * <dd>
+     * <p>
+     * An individual data row can be inserted using the traditional
+     * {@link ContentResolver#insert(Uri, ContentValues)} method. Multiple rows
+     * should always be inserted as a batch.
+     * </p>
+     * <p>
+     * An example of a traditional insert:
+     * <pre>
+     * ContentValues values = new ContentValues();
+     * values.put(Data.RAW_CONTACT_ID, rawContactId);
+     * values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+     * values.put(Phone.NUMBER, "1-800-GOOG-411");
+     * values.put(Phone.TYPE, Phone.TYPE_CUSTOM);
+     * values.put(Phone.LABEL, "free directory assistance");
+     * Uri dataUri = getContentResolver().insert(Data.CONTENT_URI, values);
+     * </pre>
+     * <p>
+     * The same done using ContentProviderOperations:
+     * <pre>
+     * ArrayList&lt;ContentProviderOperation&gt; ops = Lists.newArrayList();
+     * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
+     *          .withValue(Data.RAW_CONTACT_ID, rawContactId)
+     *          .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
+     *          .withValue(Phone.NUMBER, "1-800-GOOG-411")
+     *          .withValue(Phone.TYPE, Phone.TYPE_CUSTOM)
+     *          .withValue(Phone.LABEL, "free directory assistance")
+     *          .build());
+     * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+     * </pre>
+     * </p>
+     * <dt><b>Update</b></dt>
+     * <dd>
+     * <p>
+     * Just as with insert, update can be done incrementally or as a batch,
+     * the batch mode being the preferred method:
+     * <pre>
+     * ArrayList&lt;ContentProviderOperation&gt; ops = Lists.newArrayList();
+     * ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
+     *          .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
+     *          .withValue(Email.DATA, "somebody@android.com")
+     *          .build());
+     * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+     * </pre>
+     * </p>
+     * </dd>
+     * <dt><b>Delete</b></dt>
+     * <dd>
+     * <p>
+     * Just as with insert and update, deletion can be done either using the
+     * {@link ContentResolver#delete} method or using a ContentProviderOperation:
+     * <pre>
+     * ArrayList&lt;ContentProviderOperation&gt; ops = Lists.newArrayList();
+     * ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI)
+     *          .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
+     *          .build());
+     * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+     * </pre>
+     * </p>
+     * </dd>
+     * <dt><b>Query</b></dt>
+     * <dd>
+     * <p>
+     * <dl>
+     * <dt>Finding all Data of a given type for a given contact</dt>
+     * <dd>
+     * <pre>
+     * Cursor c = getContentResolver().query(Data.CONTENT_URI,
+     *          new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL},
+     *          Data.CONTACT_ID + &quot;=?&quot; + " AND "
+     *                  + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'",
+     *          new String[] {String.valueOf(contactId)}, null);
+     * </pre>
+     * </p>
+     * <p>
+     * </dd>
+     * <dt>Finding all Data of a given type for a given raw contact</dt>
+     * <dd>
+     * <pre>
+     * Cursor c = getContentResolver().query(Data.CONTENT_URI,
+     *          new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL},
+     *          Data.RAW_CONTACT_ID + &quot;=?&quot; + " AND "
+     *                  + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'",
+     *          new String[] {String.valueOf(rawContactId)}, null);
+     * </pre>
+     * </dd>
+     * <dt>Finding all Data for a given raw contact</dt>
+     * <dd>
+     * Most sync adapters will want to read all data rows for a raw contact
+     * along with the raw contact itself.  For that you should use the
+     * {@link RawContactsEntity}. See also {@link RawContacts}.
+     * </dd>
+     * </dl>
+     * </p>
+     * </dd>
+     * </dl>
+     * <h2>Columns</h2>
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Data</th>
+     * </tr>
+     * <tr>
+     * <td style="width: 7em;">long</td>
+     * <td style="width: 20em;">{@link #_ID}</td>
+     * <td style="width: 5em;">read-only</td>
+     * <td>Row ID. Sync adapter should try to preserve row IDs during updates. In other words,
+     * it would be a bad idea to delete and reinsert a data rows. A sync adapter should
+     * always do an update instead.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #MIMETYPE}</td>
+     * <td>read/write-once</td>
+     * <td>
+     * <p>The MIME type of the item represented by this row. Examples of common
+     * MIME types are:
+     * <ul>
+     * <li>{@link CommonDataKinds.StructuredName StructuredName.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Photo Photo.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Organization Organization.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Im Im.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Nickname Nickname.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Note Note.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.StructuredPostal StructuredPostal.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.GroupMembership GroupMembership.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Website Website.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Event Event.CONTENT_ITEM_TYPE}</li>
+     * <li>{@link CommonDataKinds.Relation Relation.CONTENT_ITEM_TYPE}</li>
+     * </ul>
+     * </p>
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #RAW_CONTACT_ID}</td>
+     * <td>read/write-once</td>
+     * <td>A reference to the {@link RawContacts#_ID} that this data belongs to.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_ID}</td>
+     * <td>read-only</td>
+     * <td>A reference to the {@link ContactsContract.Contacts#_ID} that this data row belongs
+     * to. It is obtained through a join with RawContacts.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #IS_PRIMARY}</td>
+     * <td>read/write</td>
+     * <td>Whether this is the primary entry of its kind for the raw contact it belongs to.
+     * "1" if true, "0" if false.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #IS_SUPER_PRIMARY}</td>
+     * <td>read/write</td>
+     * <td>Whether this is the primary entry of its kind for the aggregate
+     * contact it belongs to. Any data record that is "super primary" must
+     * also be "primary".</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #DATA_VERSION}</td>
+     * <td>read-only</td>
+     * <td>The version of this data record. Whenever the data row changes
+     * the version goes up. This value is monotonically increasing.</td>
+     * </tr>
+     * <tr>
+     * <td>Any type</td>
+     * <td>
+     * {@link #DATA1}<br>
+     * {@link #DATA2}<br>
+     * {@link #DATA3}<br>
+     * {@link #DATA4}<br>
+     * {@link #DATA5}<br>
+     * {@link #DATA6}<br>
+     * {@link #DATA7}<br>
+     * {@link #DATA8}<br>
+     * {@link #DATA9}<br>
+     * {@link #DATA10}<br>
+     * {@link #DATA11}<br>
+     * {@link #DATA12}<br>
+     * {@link #DATA13}<br>
+     * {@link #DATA14}<br>
+     * {@link #DATA15}
+     * </td>
+     * <td>read/write</td>
+     * <td>Generic data columns, the meaning is {@link #MIMETYPE} specific.</td>
+     * </tr>
+     * <tr>
+     * <td>Any type</td>
+     * <td>
+     * {@link #SYNC1}<br>
+     * {@link #SYNC2}<br>
+     * {@link #SYNC3}<br>
+     * {@link #SYNC4}
+     * </td>
+     * <td>read/write</td>
+     * <td>Generic columns for use by sync adapters. For example, a Photo row
+     * may store the image URL in SYNC1, a status (not loaded, loading, loaded, error)
+     * in SYNC2, server-side version number in SYNC3 and error code in SYNC4.</td>
+     * </tr>
+     * </table>
+     *
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Join with {@link StatusUpdates}</th>
+     * </tr>
+     * <tr>
+     * <td style="width: 7em;">int</td>
+     * <td style="width: 20em;">{@link #PRESENCE}</td>
+     * <td style="width: 5em;">read-only</td>
+     * <td>IM presence status linked to this data row. Compare with
+     * {@link #CONTACT_PRESENCE}, which contains the contact's presence across
+     * all IM rows. See {@link StatusUpdates} for individual status definitions.
+     * The provider may choose not to store this value
+     * in persistent storage. The expectation is that presence status will be
+     * updated on a regular basic.
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #STATUS}</td>
+     * <td>read-only</td>
+     * <td>Latest status update linked with this data row.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #STATUS_TIMESTAMP}</td>
+     * <td>read-only</td>
+     * <td>The absolute time in milliseconds when the latest status was
+     * inserted/updated for this data row.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #STATUS_RES_PACKAGE}</td>
+     * <td>read-only</td>
+     * <td>The package containing resources for this status: label and icon.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #STATUS_LABEL}</td>
+     * <td>read-only</td>
+     * <td>The resource ID of the label describing the source of status update linked
+     * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #STATUS_ICON}</td>
+     * <td>read-only</td>
+     * <td>The resource ID of the icon for the source of the status update linked
+     * to this data row. This resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td>
+     * </tr>
+     * </table>
+     *
+     * <p>
+     * Columns from the associated raw contact are also available through an
+     * implicit join.
+     * </p>
+     *
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Join with {@link RawContacts}</th>
+     * </tr>
+     * <tr>
+     * <td style="width: 7em;">int</td>
+     * <td style="width: 20em;">{@link #AGGREGATION_MODE}</td>
+     * <td style="width: 5em;">read-only</td>
+     * <td>See {@link RawContacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #DELETED}</td>
+     * <td>read-only</td>
+     * <td>See {@link RawContacts}.</td>
+     * </tr>
+     * </table>
+     *
+     * <p>
+     * Columns from the associated aggregated contact are also available through an
+     * implicit join.
+     * </p>
+     *
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Join with {@link Contacts}</th>
+     * </tr>
+     * <tr>
+     * <td style="width: 7em;">String</td>
+     * <td style="width: 20em;">{@link #LOOKUP_KEY}</td>
+     * <td style="width: 5em;">read-only</td>
+     * <td>See {@link ContactsContract.Contacts}</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #DISPLAY_NAME}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #PHOTO_ID}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #IN_VISIBLE_GROUP}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #HAS_PHONE_NUMBER}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #TIMES_CONTACTED}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #LAST_TIME_CONTACTED}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #STARRED}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CUSTOM_RINGTONE}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #SEND_TO_VOICEMAIL}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #CONTACT_PRESENCE}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CONTACT_STATUS}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_STATUS_TIMESTAMP}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CONTACT_STATUS_RES_PACKAGE}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_STATUS_LABEL}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_STATUS_ICON}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * </table>
      */
     public final static class Data implements DataColumnsWithJoins {
         /**
@@ -859,7 +1984,7 @@
          *
          * This flag is useful (currently) only for vCard exporter in Contacts app, which
          * needs to exclude "un-exportable" data from available data to export, while
-         * Contacts app itself has priviledge to access all data including "un-expotable"
+         * Contacts app itself has priviledge to access all data including "un-exportable"
          * ones and providers return all of them regardless of the callers' intention.
          * <P>Type: INTEGER</p>
          *
@@ -872,7 +1997,7 @@
         /**
          * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}
          * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts}
-         * entry of the given {@link Data} entry.
+         * entry of the given {@link ContactsContract.Data} entry.
          */
         public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) {
             final Cursor cursor = resolver.query(dataUri, new String[] {
@@ -894,8 +2019,141 @@
     }
 
     /**
-     * Constants for the raw contacts entities table, which can be though of as an outer join
-     * of the raw_contacts table with the data table.
+     * <p>
+     * Constants for the raw contacts entities table, which can be though of as
+     * an outer join of the raw_contacts table with the data table.  It is a strictly
+     * read-only table.
+     * </p>
+     * <p>
+     * If a raw contact has data rows, the RawContactsEntity cursor will contain
+     * a one row for each data row. If the raw contact has no data rows, the
+     * cursor will still contain one row with the raw contact-level information
+     * and nulls for data columns.
+     *
+     * <pre>
+     * Uri entityUri = ContentUris.withAppendedId(RawContactsEntity.CONTENT_URI, rawContactId);
+     * Cursor c = getContentResolver().query(entityUri,
+     *          new String[]{
+     *              RawContactsEntity.SOURCE_ID,
+     *              RawContactsEntity.DATA_ID,
+     *              RawContactsEntity.MIMETYPE,
+     *              RawContactsEntity.DATA1
+     *          }, null, null, null);
+     * try {
+     *     while (c.moveToNext()) {
+     *         String sourceId = c.getString(0);
+     *         if (!c.isNull(1)) {
+     *             String mimeType = c.getString(2);
+     *             String data = c.getString(3);
+     *             ...
+     *         }
+     *     }
+     * } finally {
+     *     c.close();
+     * }
+     * </pre>
+     *
+     * <h3>Columns</h3>
+     * RawContactsEntity has a combination of RawContact and Data columns.
+     *
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>RawContacts</th>
+     * </tr>
+     * <tr>
+     * <td style="width: 7em;">long</td>
+     * <td style="width: 20em;">{@link #_ID}</td>
+     * <td style="width: 5em;">read-only</td>
+     * <td>Raw contact row ID. See {@link RawContacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #CONTACT_ID}</td>
+     * <td>read-only</td>
+     * <td>See {@link RawContacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #AGGREGATION_MODE}</td>
+     * <td>read-only</td>
+     * <td>See {@link RawContacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #DELETED}</td>
+     * <td>read-only</td>
+     * <td>See {@link RawContacts}.</td>
+     * </tr>
+     * </table>
+     *
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Data</th>
+     * </tr>
+     * <tr>
+     * <td style="width: 7em;">long</td>
+     * <td style="width: 20em;">{@link #DATA_ID}</td>
+     * <td style="width: 5em;">read-only</td>
+     * <td>Data row ID. It will be null if the raw contact has no data rows.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #MIMETYPE}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Data}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #IS_PRIMARY}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Data}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #IS_SUPER_PRIMARY}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Data}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #DATA_VERSION}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Data}.</td>
+     * </tr>
+     * <tr>
+     * <td>Any type</td>
+     * <td>
+     * {@link #DATA1}<br>
+     * {@link #DATA2}<br>
+     * {@link #DATA3}<br>
+     * {@link #DATA4}<br>
+     * {@link #DATA5}<br>
+     * {@link #DATA6}<br>
+     * {@link #DATA7}<br>
+     * {@link #DATA8}<br>
+     * {@link #DATA9}<br>
+     * {@link #DATA10}<br>
+     * {@link #DATA11}<br>
+     * {@link #DATA12}<br>
+     * {@link #DATA13}<br>
+     * {@link #DATA14}<br>
+     * {@link #DATA15}
+     * </td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Data}.</td>
+     * </tr>
+     * <tr>
+     * <td>Any type</td>
+     * <td>
+     * {@link #SYNC1}<br>
+     * {@link #SYNC2}<br>
+     * {@link #SYNC3}<br>
+     * {@link #SYNC4}
+     * </td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Data}.</td>
+     * </tr>
+     * </table>
      */
     public final static class RawContactsEntity
             implements BaseColumns, DataColumns, RawContactsColumns {
@@ -938,6 +2196,9 @@
         public static final String DATA_ID = "data_id";
     }
 
+    /**
+     * @see PhoneLookup
+     */
     protected interface PhoneLookupColumns {
         /**
          * The phone number as the user entered it.
@@ -961,7 +2222,112 @@
     /**
      * A table that represents the result of looking up a phone number, for
      * example for caller ID. To perform a lookup you must append the number you
-     * want to find to {@link #CONTENT_FILTER_URI}.
+     * want to find to {@link #CONTENT_FILTER_URI}.  This query is highly
+     * optimized.
+     * <pre>
+     * Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
+     * resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...
+     * </pre>
+     *
+     * <h3>Columns</h3>
+     *
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>PhoneLookup</th>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #_ID}</td>
+     * <td>read-only</td>
+     * <td>Data row ID.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #NUMBER}</td>
+     * <td>read-only</td>
+     * <td>Phone number.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #TYPE}</td>
+     * <td>read-only</td>
+     * <td>Phone number type. See {@link CommonDataKinds.Phone}.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #LABEL}</td>
+     * <td>read-only</td>
+     * <td>Custom label for the phone number. See {@link CommonDataKinds.Phone}.</td>
+     * </tr>
+     * </table>
+     * <p>
+     * Columns from the Contacts table are also available through a join.
+     * </p>
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Join with {@link Contacts}</th>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #LOOKUP_KEY}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #DISPLAY_NAME}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #PHOTO_ID}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #IN_VISIBLE_GROUP}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #HAS_PHONE_NUMBER}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #TIMES_CONTACTED}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #LAST_TIME_CONTACTED}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #STARRED}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CUSTOM_RINGTONE}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #SEND_TO_VOICEMAIL}</td>
+     * <td>read-only</td>
+     * <td>See {@link ContactsContract.Contacts}.</td>
+     * </tr>
+     * </table>
      */
     public static final class PhoneLookup implements BaseColumns, PhoneLookupColumns,
             ContactsColumns, ContactOptionsColumns {
@@ -973,10 +2339,9 @@
         /**
          * The content:// style URI for this table. Append the phone number you want to lookup
          * to this URI and query it to perform a lookup. For example:
-         *
-         * {@code
-         * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, phoneNumber);
-         * }
+         * <pre>
+         * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_URI, Uri.encode(phoneNumber));
+         * </pre>
          */
         public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI,
                 "phone_lookup");
@@ -985,6 +2350,8 @@
     /**
      * Additional data mixed in with {@link StatusColumns} to link
      * back to specific {@link ContactsContract.Data#_ID} entries.
+     *
+     * @see StatusUpdates
      */
     protected interface PresenceColumns {
 
@@ -995,6 +2362,7 @@
         public static final String DATA_ID = "presence_data_id";
 
         /**
+         * See {@link CommonDataKinds.Im} for a list of defined protocol constants.
          * <p>Type: NUMBER</p>
          */
         public static final String PROTOCOL = "protocol";
@@ -1024,11 +2392,132 @@
     }
 
     /**
-     * A status update is linked to a {@link Data} row and captures the user's latest status
-     * update via the corresponding source, e.g. "Having lunch" via "Google Talk".
+     * <p>
+     * A status update is linked to a {@link ContactsContract.Data} row and captures
+     * the user's latest status update via the corresponding source, e.g.
+     * "Having lunch" via "Google Talk".
+     * </p>
+     * <p>
+     * There are two ways a status update can be inserted: by explicitly linking
+     * it to a Data row using {@link #DATA_ID} or indirectly linking it to a data row
+     * using a combination of {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and
+     * {@link #IM_HANDLE}.  There is no difference between insert and update, you can use
+     * either.
+     * </p>
+     * <p>
+     * You cannot use {@link ContentResolver#update} to change a status, but
+     * {@link ContentResolver#insert} will replace the latests status if it already
+     * exists.
+     * </p>
+     * <p>
+     * Use {@link ContentResolver#bulkInsert(Uri, ContentValues[])} to insert/update statuses
+     * for multiple contacts at once.
+     * </p>
+     *
+     * <h3>Columns</h3>
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>StatusUpdates</th>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #DATA_ID}</td>
+     * <td>read/write</td>
+     * <td>Reference to the {@link Data#_ID} entry that owns this presence. If this
+     * field is <i>not</i> specified, the provider will attempt to find a data row
+     * that matches the {@link #PROTOCOL} (or {@link #CUSTOM_PROTOCOL}) and
+     * {@link #IM_HANDLE} columns.
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #PROTOCOL}</td>
+     * <td>read/write</td>
+     * <td>See {@link CommonDataKinds.Im} for a list of defined protocol constants.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #CUSTOM_PROTOCOL}</td>
+     * <td>read/write</td>
+     * <td>Name of the custom protocol.  Should be supplied along with the {@link #PROTOCOL} value
+     * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.  Should be null or
+     * omitted if {@link #PROTOCOL} value is not
+     * {@link ContactsContract.CommonDataKinds.Im#PROTOCOL_CUSTOM}.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #IM_HANDLE}</td>
+     * <td>read/write</td>
+     * <td> The IM handle the presence item is for. The handle is scoped to
+     * {@link #PROTOCOL}.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #IM_ACCOUNT}</td>
+     * <td>read/write</td>
+     * <td>The IM account for the local user that the presence data came from.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #PRESENCE}</td>
+     * <td>read/write</td>
+     * <td>Contact IM presence status. The allowed values are:
+     * <p>
+     * <ul>
+     * <li>{@link #OFFLINE}</li>
+     * <li>{@link #INVISIBLE}</li>
+     * <li>{@link #AWAY}</li>
+     * <li>{@link #IDLE}</li>
+     * <li>{@link #DO_NOT_DISTURB}</li>
+     * <li>{@link #AVAILABLE}</li>
+     * </ul>
+     * </p>
+     * <p>
+     * Since presence status is inherently volatile, the content provider
+     * may choose not to store this field in long-term storage.
+     * </p>
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #STATUS}</td>
+     * <td>read/write</td>
+     * <td>Contact's latest status update, e.g. "having toast for breakfast"</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #STATUS_TIMESTAMP}</td>
+     * <td>read/write</td>
+     * <td>The absolute time in milliseconds when the status was
+     * entered by the user. If this value is not provided, the provider will follow
+     * this logic: if there was no prior status update, the value will be left as null.
+     * If there was a prior status update, the provider will default this field
+     * to the current time.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #STATUS_RES_PACKAGE}</td>
+     * <td>read/write</td>
+     * <td> The package containing resources for this status: label and icon.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #STATUS_LABEL}</td>
+     * <td>read/write</td>
+     * <td>The resource ID of the label describing the source of contact status,
+     * e.g. "Google Talk". This resource is scoped by the
+     * {@link #STATUS_RES_PACKAGE}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #STATUS_ICON}</td>
+     * <td>read/write</td>
+     * <td>The resource ID of the icon for the source of contact status. This
+     * resource is scoped by the {@link #STATUS_RES_PACKAGE}.</td>
+     * </tr>
+     * </table>
      */
-    // TODO make final as soon as Presence is removed
-    public static /*final*/ class StatusUpdates implements StatusColumns, PresenceColumns {
+    public static class StatusUpdates implements StatusColumns, PresenceColumns {
 
         /**
          * This utility class cannot be instantiated
@@ -1088,13 +2577,17 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update";
     }
 
+    /**
+     * @deprecated This old name was never meant to be made public. Do not use.
+     */
     @Deprecated
     public static final class Presence extends StatusUpdates {
 
     }
 
     /**
-     * Container for definitions of common data types stored in the {@link Data} table.
+     * Container for definitions of common data types stored in the {@link ContactsContract.Data}
+     * table.
      */
     public static final class CommonDataKinds {
         /**
@@ -1144,7 +2637,69 @@
         }
 
         /**
-         * Parts of the name.
+         * A data kind representing the contact's proper name. You can use all
+         * columns defined for {@link ContactsContract.Data} as well as the following aliases.
+         *
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #DISPLAY_NAME}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #GIVEN_NAME}</td>
+         * <td>{@link #DATA2}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #FAMILY_NAME}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #PREFIX}</td>
+         * <td>{@link #DATA4}</td>
+         * <td>Common prefixes in English names are "Mr", "Ms", "Dr" etc.</td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #MIDDLE_NAME}</td>
+         * <td>{@link #DATA5}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #SUFFIX}</td>
+         * <td>{@link #DATA6}</td>
+         * <td>Common suffixes in English names are "Sr", "Jr", "III" etc.</td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #PHONETIC_GIVEN_NAME}</td>
+         * <td>{@link #DATA7}</td>
+         * <td>Used for phonetic spelling of the name, e.g. Pinyin, Katakana, Hiragana</td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #PHONETIC_MIDDLE_NAME}</td>
+         * <td>{@link #DATA8}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #PHONETIC_FAMILY_NAME}</td>
+         * <td>{@link #DATA9}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class StructuredName implements DataColumnsWithJoins {
             /**
@@ -1213,7 +2768,68 @@
         }
 
         /**
-         * A nickname.
+         * <p>A data kind representing the contact's nickname. For example, for
+         * Bob Parr ("Mr. Incredible"):
+         * <pre>
+         * ArrayList&lt;ContentProviderOperation&gt; ops = Lists.newArrayList();
+         * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
+         *          .withValue(Data.RAW_CONTACT_ID, rawContactId)
+         *          .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
+         *          .withValue(StructuredName.DISPLAY_NAME, &quot;Bob Parr&quot;)
+         *          .build());
+         *
+         * ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
+         *          .withValue(Data.RAW_CONTACT_ID, rawContactId)
+         *          .withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE)
+         *          .withValue(Nickname.NAME, "Mr. Incredible")
+         *          .withValue(Nickname.TYPE, Nickname.TYPE_CUSTOM)
+         *          .withValue(Nickname.LABEL, "Superhero")
+         *          .build());
+         *
+         * getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+         * </pre>
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as well as the
+         * following aliases.
+         * </p>
+         *
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th><th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #NAME}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>
+         * Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_DEFAULT}</li>
+         * <li>{@link #TYPE_OTHER_NAME}</li>
+         * <li>{@link #TYPE_MAINDEN_NAME}</li>
+         * <li>{@link #TYPE_SHORT_NAME}</li>
+         * <li>{@link #TYPE_INITIALS}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Nickname implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1237,7 +2853,64 @@
         }
 
         /**
-         * Common data definition for telephone numbers.
+         * <p>
+         * A data kind representing a telephone number.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #NUMBER}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_HOME}</li>
+         * <li>{@link #TYPE_MOBILE}</li>
+         * <li>{@link #TYPE_WORK}</li>
+         * <li>{@link #TYPE_FAX_WORK}</li>
+         * <li>{@link #TYPE_FAX_HOME}</li>
+         * <li>{@link #TYPE_PAGER}</li>
+         * <li>{@link #TYPE_OTHER}</li>
+         * <li>{@link #TYPE_CALLBACK}</li>
+         * <li>{@link #TYPE_CAR}</li>
+         * <li>{@link #TYPE_COMPANY_MAIN}</li>
+         * <li>{@link #TYPE_ISDN}</li>
+         * <li>{@link #TYPE_MAIN}</li>
+         * <li>{@link #TYPE_OTHER_FAX}</li>
+         * <li>{@link #TYPE_RADIO}</li>
+         * <li>{@link #TYPE_TELEX}</li>
+         * <li>{@link #TYPE_TTY_TDD}</li>
+         * <li>{@link #TYPE_WORK_MOBILE}</li>
+         * <li>{@link #TYPE_WORK_PAGER}</li>
+         * <li>{@link #TYPE_ASSISTANT}</li>
+         * <li>{@link #TYPE_MMS}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Phone implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1365,7 +3038,48 @@
         }
 
         /**
-         * Common data definition for email addresses.
+         * <p>
+         * A data kind representing an email address.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #DATA}</td>
+         * <td>{@link #DATA1}</td>
+         * <td>Email address itself.</td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_HOME}</li>
+         * <li>{@link #TYPE_WORK}</li>
+         * <li>{@link #TYPE_OTHER}</li>
+         * <li>{@link #TYPE_MOBILE}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Email implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1390,22 +3104,50 @@
                     "emails");
 
             /**
+             * <p>
              * The content:// style URL for looking up data rows by email address. The
              * lookup argument, an email address, should be passed as an additional path segment
              * after this URI.
+             * </p>
+             * <p>Example:
+             * <pre>
+             * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(email));
+             * Cursor c = getContentResolver().query(uri,
+             *          new String[]{Email.CONTACT_ID, Email.DISPLAY_NAME, Email.DATA},
+             *          null, null, null);
+             * </pre>
+             * </p>
              */
             public static final Uri CONTENT_LOOKUP_URI = Uri.withAppendedPath(CONTENT_URI,
                     "lookup");
 
             /**
+             * <p>
              * The content:// style URL for email lookup using a filter. The filter returns
              * records of MIME type {@link #CONTENT_ITEM_TYPE}. The filter is applied
              * to display names as well as email addresses. The filter argument should be passed
              * as an additional path segment after this URI.
+             * </p>
+             * <p>The query in the following example will return "Robert Parr (bob@incredibles.com)"
+             * as well as "Bob Parr (incredible@android.com)".
+             * <pre>
+             * Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode("bob"));
+             * Cursor c = getContentResolver().query(uri,
+             *          new String[]{Email.DISPLAY_NAME, Email.DATA},
+             *          null, null, null);
+             * </pre>
+             * </p>
              */
             public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI,
                     "filter");
 
+            /**
+             * The email address.
+             * <P>Type: TEXT</P>
+             * @hide TODO: Unhide in a separate CL
+             */
+            public static final String ADDRESS = DATA1;
+
             public static final int TYPE_HOME = 1;
             public static final int TYPE_WORK = 2;
             public static final int TYPE_OTHER = 3;
@@ -1448,7 +3190,89 @@
         }
 
         /**
-         * Common data definition for postal addresses.
+         * <p>
+         * A data kind representing a postal addresses.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #FORMATTED_ADDRESS}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_HOME}</li>
+         * <li>{@link #TYPE_WORK}</li>
+         * <li>{@link #TYPE_OTHER}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #STREET}</td>
+         * <td>{@link #DATA4}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #POBOX}</td>
+         * <td>{@link #DATA5}</td>
+         * <td>Post Office Box number</td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #NEIGHBORHOOD}</td>
+         * <td>{@link #DATA6}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #CITY}</td>
+         * <td>{@link #DATA7}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #REGION}</td>
+         * <td>{@link #DATA8}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #POSTCODE}</td>
+         * <td>{@link #DATA9}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #COUNTRY}</td>
+         * <td>{@link #DATA10}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class StructuredPostal implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1573,7 +3397,76 @@
         }
 
         /**
-         * Common data definition for IM addresses.
+         * <p>
+         * A data kind representing an IM address
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #DATA}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_HOME}</li>
+         * <li>{@link #TYPE_WORK}</li>
+         * <li>{@link #TYPE_OTHER}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #PROTOCOL}</td>
+         * <td>{@link #DATA5}</td>
+         * <td>
+         * <p>
+         * Allowed values:
+         * <ul>
+         * <li>{@link #PROTOCOL_CUSTOM}. Also provide the actual protocol name
+         * as {@link #CUSTOM_PROTOCOL}.</li>
+         * <li>{@link #PROTOCOL_AIM}</li>
+         * <li>{@link #PROTOCOL_MSN}</li>
+         * <li>{@link #PROTOCOL_YAHOO}</li>
+         * <li>{@link #PROTOCOL_SKYPE}</li>
+         * <li>{@link #PROTOCOL_QQ}</li>
+         * <li>{@link #PROTOCOL_GOOGLE_TALK}</li>
+         * <li>{@link #PROTOCOL_ICQ}</li>
+         * <li>{@link #PROTOCOL_JABBER}</li>
+         * <li>{@link #PROTOCOL_NETMEETING}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #CUSTOM_PROTOCOL}</td>
+         * <td>{@link #DATA6}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Im implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1676,7 +3569,82 @@
         }
 
         /**
-         * Common data definition for organizations.
+         * <p>
+         * A data kind representing an organization.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #COMPANY}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_WORK}</li>
+         * <li>{@link #TYPE_OTHER}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #TITLE}</td>
+         * <td>{@link #DATA4}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #DEPARTMENT}</td>
+         * <td>{@link #DATA5}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #JOB_DESCRIPTION}</td>
+         * <td>{@link #DATA6}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #SYMBOL}</td>
+         * <td>{@link #DATA7}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #PHONETIC_NAME}</td>
+         * <td>{@link #DATA8}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #OFFICE_LOCATION}</td>
+         * <td>{@link #DATA9}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Organization implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1761,7 +3729,58 @@
         }
 
         /**
-         * Common data definition for relations.
+         * <p>
+         * A data kind representing a relation.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #NAME}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_ASSISTANT}</li>
+         * <li>{@link #TYPE_BROTHER}</li>
+         * <li>{@link #TYPE_CHILD}</li>
+         * <li>{@link #TYPE_DOMESTIC_PARTNER}</li>
+         * <li>{@link #TYPE_FATHER}</li>
+         * <li>{@link #TYPE_FRIEND}</li>
+         * <li>{@link #TYPE_MANAGER}</li>
+         * <li>{@link #TYPE_MOTHER}</li>
+         * <li>{@link #TYPE_PARENT}</li>
+         * <li>{@link #TYPE_PARTNER}</li>
+         * <li>{@link #TYPE_REFERRED_BY}</li>
+         * <li>{@link #TYPE_RELATIVE}</li>
+         * <li>{@link #TYPE_SISTER}</li>
+         * <li>{@link #TYPE_SPOUSE}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Relation implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1795,7 +3814,47 @@
         }
 
         /**
-         * Common data definition for events.
+         * <p>
+         * A data kind representing an event.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #START_DATE}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_ANNIVERSARY}</li>
+         * <li>{@link #TYPE_OTHER}</li>
+         * <li>{@link #TYPE_BIRTHDAY}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Event implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1835,7 +3894,33 @@
         }
 
         /**
-         * Photo of the contact.
+         * <p>
+         * A data kind representing an photo for the contact.
+         * </p>
+         * <p>
+         * Some sync adapters will choose to download photos in a separate
+         * pass. A common pattern is to use columns {@link ContactsContract.Data#SYNC1}
+         * through {@link ContactsContract.Data#SYNC4} to store temporary
+         * data, e.g. the image URL or ID, state of download, server-side version
+         * of the image.  It is allowed for the {@link #PHOTO} to be null.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>BLOB</td>
+         * <td>{@link #PHOTO}</td>
+         * <td>{@link #DATA15}</td>
+         * <td>By convention, binary data is stored in DATA15.</td>
+         * </tr>
+         * </table>
          */
         public static final class Photo implements DataColumnsWithJoins {
             /**
@@ -1856,7 +3941,26 @@
         }
 
         /**
+         * <p>
          * Notes about the contact.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #NOTE}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Note implements DataColumnsWithJoins {
             /**
@@ -1875,7 +3979,43 @@
         }
 
         /**
+         * <p>
          * Group Membership.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>long</td>
+         * <td>{@link #GROUP_ROW_ID}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #GROUP_SOURCE_ID}</td>
+         * <td>none</td>
+         * <td>
+         * <p>
+         * The sourceid of the group that this group membership refers to.
+         * Exactly one of this or {@link #GROUP_ROW_ID} must be set when
+         * inserting a row.
+         * </p>
+         * <p>
+         * If this field is specified, the provider will first try to
+         * look up a group with this {@link Groups Groups.SOURCE_ID}.  If such a group
+         * is found, it will use the corresponding row id.  If the group is not
+         * found, it will create one.
+         * </td>
+         * </tr>
+         * </table>
          */
         public static final class GroupMembership implements DataColumnsWithJoins {
             /**
@@ -1903,7 +4043,51 @@
         }
 
         /**
-         * Website related to the contact.
+         * <p>
+         * A data kind representing a website related to the contact.
+         * </p>
+         * <p>
+         * You can use all columns defined for {@link ContactsContract.Data} as
+         * well as the following aliases.
+         * </p>
+         * <h2>Column aliases</h2>
+         * <table class="jd-sumtable">
+         * <tr>
+         * <th>Type</th>
+         * <th>Alias</th><th colspan='2'>Data column</th>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #URL}</td>
+         * <td>{@link #DATA1}</td>
+         * <td></td>
+         * </tr>
+         * <tr>
+         * <td>int</td>
+         * <td>{@link #TYPE}</td>
+         * <td>{@link #DATA2}</td>
+         * <td>Allowed values are:
+         * <p>
+         * <ul>
+         * <li>{@link #TYPE_CUSTOM}. Put the actual type in {@link #LABEL}.</li>
+         * <li>{@link #TYPE_HOMEPAGE}</li>
+         * <li>{@link #TYPE_BLOG}</li>
+         * <li>{@link #TYPE_PROFILE}</li>
+         * <li>{@link #TYPE_HOME}</li>
+         * <li>{@link #TYPE_WORK}</li>
+         * <li>{@link #TYPE_FTP}</li>
+         * <li>{@link #TYPE_OTHER}</li>
+         * </ul>
+         * </p>
+         * </td>
+         * </tr>
+         * <tr>
+         * <td>String</td>
+         * <td>{@link #LABEL}</td>
+         * <td>{@link #DATA3}</td>
+         * <td></td>
+         * </tr>
+         * </table>
          */
         public static final class Website implements DataColumnsWithJoins, CommonColumns {
             /**
@@ -1930,6 +4114,9 @@
         }
     }
 
+    /**
+     * @see Groups
+     */
     protected interface GroupsColumns {
         /**
          * The display title of this group.
@@ -2000,11 +4187,11 @@
         /**
          * The "deleted" flag: "0" by default, "1" if the row has been marked
          * for deletion. When {@link android.content.ContentResolver#delete} is
-         * called on a raw contact, it is marked for deletion and removed from its
-         * aggregate contact. The sync adaptor deletes the raw contact on the server and
-         * then calls ContactResolver.delete once more, this time setting the the
-         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
-         * the data removal.
+         * called on a group, it is marked for deletion. The sync adaptor
+         * deletes the group on the server and then calls ContactResolver.delete
+         * once more, this time setting the the
+         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to
+         * finalize the data removal.
          * <P>Type: INTEGER</P>
          */
         public static final String DELETED = "deleted";
@@ -2019,7 +4206,82 @@
     }
 
     /**
-     * Constants for the groups table.
+     * Constants for the groups table. Only per-account groups are supported.
+     * <h2>Columns</h2>
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Groups</th>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #_ID}</td>
+     * <td>read-only</td>
+     * <td>Row ID. Sync adapter should try to preserve row IDs during updates.
+     * In other words, it would be a really bad idea to delete and reinsert a
+     * group. A sync adapter should always do an update instead.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #TITLE}</td>
+     * <td>read/write</td>
+     * <td>The display title of this group.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #NOTES}</td>
+     * <td>read/write</td>
+     * <td>Notes about the group.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #SYSTEM_ID}</td>
+     * <td>read/write</td>
+     * <td>The ID of this group if it is a System Group, i.e. a group that has a
+     * special meaning to the sync adapter, null otherwise.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #SUMMARY_COUNT}</td>
+     * <td>read-only</td>
+     * <td>The total number of {@link Contacts} that have
+     * {@link CommonDataKinds.GroupMembership} in this group. Read-only value
+     * that is only present when querying {@link Groups#CONTENT_SUMMARY_URI}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #SUMMARY_WITH_PHONES}</td>
+     * <td>read-only</td>
+     * <td>The total number of {@link Contacts} that have both
+     * {@link CommonDataKinds.GroupMembership} in this group, and also have
+     * phone numbers. Read-only value that is only present when querying
+     * {@link Groups#CONTENT_SUMMARY_URI}.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #GROUP_VISIBLE}</td>
+     * <td>read-only</td>
+     * <td>Flag indicating if the contacts belonging to this group should be
+     * visible in any user interface. Allowed values: 0 and 1.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #DELETED}</td>
+     * <td>read/write</td>
+     * <td>The "deleted" flag: "0" by default, "1" if the row has been marked
+     * for deletion. When {@link android.content.ContentResolver#delete} is
+     * called on a group, it is marked for deletion. The sync adaptor deletes
+     * the group on the server and then calls ContactResolver.delete once more,
+     * this time setting the the {@link ContactsContract#CALLER_IS_SYNCADAPTER}
+     * query parameter to finalize the data removal.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #SHOULD_SYNC}</td>
+     * <td>read/write</td>
+     * <td>Whether this group should be synced if the SYNC_EVERYTHING settings
+     * is false for this group's account.</td>
+     * </tr>
+     * </table>
      */
     public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns {
         /**
@@ -2035,7 +4297,7 @@
 
         /**
          * The content:// style URI for this table joined with details data from
-         * {@link Data}.
+         * {@link ContactsContract.Data}.
          */
         public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
                 "groups_summary");
@@ -2052,9 +4314,39 @@
     }
 
     /**
+     * <p>
      * Constants for the contact aggregation exceptions table, which contains
-     * aggregation rules overriding those used by automatic aggregation.  This type only
-     * supports query and update. Neither insert nor delete are supported.
+     * aggregation rules overriding those used by automatic aggregation. This
+     * type only supports query and update. Neither insert nor delete are
+     * supported.
+     * </p>
+     * <h2>Columns</h2>
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>AggregationExceptions</th>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #TYPE}</td>
+     * <td>read/write</td>
+     * <td>The type of exception: {@link #TYPE_KEEP_TOGETHER},
+     * {@link #TYPE_KEEP_SEPARATE} or {@link #TYPE_AUTOMATIC}.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #RAW_CONTACT_ID1}</td>
+     * <td>read/write</td>
+     * <td>A reference to the {@link RawContacts#_ID} of the raw contact that
+     * the rule applies to.</td>
+     * </tr>
+     * <tr>
+     * <td>long</td>
+     * <td>{@link #RAW_CONTACT_ID2}</td>
+     * <td>read/write</td>
+     * <td>A reference to the other {@link RawContacts#_ID} of the raw contact
+     * that the rule applies to.</td>
+     * </tr>
+     * </table>
      */
     public static final class AggregationExceptions implements BaseColumns {
         /**
@@ -2117,6 +4409,9 @@
         public static final String RAW_CONTACT_ID2 = "raw_contact_id2";
     }
 
+    /**
+     * @see Settings
+     */
     protected interface SettingsColumns {
         /**
          * The name of the account instance to which this row belongs.
@@ -2172,8 +4467,68 @@
     }
 
     /**
-     * Contacts-specific settings for various {@link Account}.
+     * <p>
+     * Contacts-specific settings for various {@link Account}'s.
+     * </p>
+     * <h2>Columns</h2>
+     * <table class="jd-sumtable">
+     * <tr>
+     * <th colspan='4'>Settings</th>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #ACCOUNT_NAME}</td>
+     * <td>read/write-once</td>
+     * <td>The name of the account instance to which this row belongs.</td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
+     * <td>{@link #ACCOUNT_TYPE}</td>
+     * <td>read/write-once</td>
+     * <td>The type of account to which this row belongs, which when paired with
+     * {@link #ACCOUNT_NAME} identifies a specific account.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #SHOULD_SYNC}</td>
+     * <td>read/write</td>
+     * <td>Depending on the mode defined by the sync-adapter, this flag controls
+     * the top-level sync behavior for this data source.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #UNGROUPED_VISIBLE}</td>
+     * <td>read/write</td>
+     * <td>Flag indicating if contacts without any
+     * {@link CommonDataKinds.GroupMembership} entries should be visible in any
+     * user interface.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #ANY_UNSYNCED}</td>
+     * <td>read-only</td>
+     * <td>Read-only flag indicating if this {@link #SHOULD_SYNC} or any
+     * {@link Groups#SHOULD_SYNC} under this account have been marked as
+     * unsynced.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #UNGROUPED_COUNT}</td>
+     * <td>read-only</td>
+     * <td>Read-only count of {@link Contacts} from a specific source that have
+     * no {@link CommonDataKinds.GroupMembership} entries.</td>
+     * </tr>
+     * <tr>
+     * <td>int</td>
+     * <td>{@link #UNGROUPED_WITH_PHONES}</td>
+     * <td>read-only</td>
+     * <td>Read-only count of {@link Contacts} from a specific source that have
+     * no {@link CommonDataKinds.GroupMembership} entries, and also have phone
+     * numbers.</td>
+     * </tr>
+     * </table>
      */
+
     public static final class Settings implements SettingsColumns {
         /**
          * This utility class cannot be instantiated
@@ -2252,8 +4607,8 @@
         /**
          * Trigger a dialog that lists the various methods of interacting with
          * the requested {@link Contacts} entry. This may be based on available
-         * {@link Data} rows under that contact, and may also include social
-         * status and presence details.
+         * {@link ContactsContract.Data} rows under that contact, and may also
+         * include social status and presence details.
          *
          * @param context The parent {@link Context} that may be used as the
          *            parent for this dialog.
@@ -2291,8 +4646,8 @@
         /**
          * Trigger a dialog that lists the various methods of interacting with
          * the requested {@link Contacts} entry. This may be based on available
-         * {@link Data} rows under that contact, and may also include social
-         * status and presence details.
+         * {@link ContactsContract.Data} rows under that contact, and may also
+         * include social status and presence details.
          *
          * @param context The parent {@link Context} that may be used as the
          *            parent for this dialog.
@@ -2593,7 +4948,7 @@
             /**
              * The extra field for the contact phone number type.
              * <P>Type: Either an integer value from
-             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
+             * {@link CommonDataKinds.Phone},
              *  or a string specifying a custom label.</P>
              */
             public static final String PHONE_TYPE = "phone_type";
@@ -2613,7 +4968,7 @@
             /**
              * The extra field for an optional second contact phone number type.
              * <P>Type: Either an integer value from
-             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
+             * {@link CommonDataKinds.Phone},
              *  or a string specifying a custom label.</P>
              */
             public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type";
@@ -2627,7 +4982,7 @@
             /**
              * The extra field for an optional third contact phone number type.
              * <P>Type: Either an integer value from
-             * {@link android.provider.Contacts.PhonesColumns PhonesColumns},
+             * {@link CommonDataKinds.Phone},
              *  or a string specifying a custom label.</P>
              */
             public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type";
@@ -2641,7 +4996,7 @@
             /**
              * The extra field for the contact email type.
              * <P>Type: Either an integer value from
-             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
+             * {@link CommonDataKinds.Email}
              *  or a string specifying a custom label.</P>
              */
             public static final String EMAIL_TYPE = "email_type";
@@ -2661,7 +5016,7 @@
             /**
              * The extra field for an optional second contact email type.
              * <P>Type: Either an integer value from
-             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
+             * {@link CommonDataKinds.Email}
              *  or a string specifying a custom label.</P>
              */
             public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type";
@@ -2675,7 +5030,7 @@
             /**
              * The extra field for an optional third contact email type.
              * <P>Type: Either an integer value from
-             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
+             * {@link CommonDataKinds.Email}
              *  or a string specifying a custom label.</P>
              */
             public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type";
@@ -2689,7 +5044,7 @@
             /**
              * The extra field for the contact postal address type.
              * <P>Type: Either an integer value from
-             * {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
+             * {@link CommonDataKinds.StructuredPostal}
              *  or a string specifying a custom label.</P>
              */
             public static final String POSTAL_TYPE = "postal_type";
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index d86b674..e4cc609 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1328,7 +1328,7 @@
                     getKeyDispatcherState().startTracking(event, this);
                     return true;
                 } else if (event.getAction() == KeyEvent.ACTION_UP
-                        && event.isTracking() && !event.isCanceled()) {
+                        && getKeyDispatcherState().isTracking(event) && !event.isCanceled()) {
                     dismiss();
                     return true;
                 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7d6f158..1c3cf3c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -41,6 +41,7 @@
     <protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
     <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
     <protected-broadcast android:name="android.intent.action.CONFIGURATION_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
     <protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.BATTERY_LOW" />
     <protected-broadcast android:name="android.intent.action.BATTERY_OKAY" />
diff --git a/core/res/res/values-ar-rEG/donottranslate-cldr.xml b/core/res/res/values-ar-rEG/donottranslate-cldr.xml
index 2c20ffc..d662590 100644
--- a/core/res/res/values-ar-rEG/donottranslate-cldr.xml
+++ b/core/res/res/values-ar-rEG/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s، %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s، %3$s %2$s - %6$s، %8$s %7$s، %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE، d MMMM y</string>
 </resources>
diff --git a/core/res/res/values-bg-rBG/donottranslate-cldr.xml b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
index 527cdb9..f03b060 100644
--- a/core/res/res/values-bg-rBG/donottranslate-cldr.xml
+++ b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %9$s, %1$s - %8$s %7$s y, %6$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">d MMM y, E</string>
 </resources>
diff --git a/core/res/res/values-ca-rES/donottranslate-cldr.xml b/core/res/res/values-ca-rES/donottranslate-cldr.xml
index d5abeef..a77aa38 100644
--- a/core/res/res/values-ca-rES/donottranslate-cldr.xml
+++ b/core/res/res/values-ca-rES/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s - %6$s %8$s de %7$s de %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d MMM y</string>
 </resources>
diff --git a/core/res/res/values-cs/donottranslate-cldr.xml b/core/res/res/values-cs/donottranslate-cldr.xml
index 53dc312..6235b2c 100644
--- a/core/res/res/values-cs/donottranslate-cldr.xml
+++ b/core/res/res/values-cs/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s - %6$s %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">E d. MMMM y</string>
 </resources>
diff --git a/core/res/res/values-da/donottranslate-cldr.xml b/core/res/res/values-da/donottranslate-cldr.xml
index a4faca2..a731174 100644
--- a/core/res/res/values-da/donottranslate-cldr.xml
+++ b/core/res/res/values-da/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s d. %3$s. %2$s - %6$s d. %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d. MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d. MMM y</string>
 </resources>
diff --git a/core/res/res/values-de/donottranslate-cldr.xml b/core/res/res/values-de/donottranslate-cldr.xml
index 8a9c1a7..ac6c195 100644
--- a/core/res/res/values-de/donottranslate-cldr.xml
+++ b/core/res/res/values-de/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s. - %8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d. MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d. MMM y</string>
 </resources>
diff --git a/core/res/res/values-el/donottranslate-cldr.xml b/core/res/res/values-el/donottranslate-cldr.xml
index e8f02fb..a0174f6 100644
--- a/core/res/res/values-el/donottranslate-cldr.xml
+++ b/core/res/res/values-el/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-en-rAU/donottranslate-cldr.xml b/core/res/res/values-en-rAU/donottranslate-cldr.xml
index 9811b68..cb254f3 100644
--- a/core/res/res/values-en-rAU/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rAU/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">E, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-en-rCA/donottranslate-cldr.xml b/core/res/res/values-en-rCA/donottranslate-cldr.xml
index 1e250c7..597b0af 100644
--- a/core/res/res/values-en-rCA/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rCA/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%2$s %3$s-%8$s, %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s - %6$s, %7$s %8$s, %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, MMMM d</string>
+    <string name="abbrev_wday_month_day_year">E, MMM d, y</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/donottranslate-cldr.xml b/core/res/res/values-en-rGB/donottranslate-cldr.xml
index 65545ba..5416b8e 100644
--- a/core/res/res/values-en-rGB/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rGB/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">E, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-en-rIE/donottranslate-cldr.xml b/core/res/res/values-en-rIE/donottranslate-cldr.xml
index 2e59dcf..93743ba 100644
--- a/core/res/res/values-en-rIE/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rIE/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">E d MMM y</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/donottranslate-cldr.xml b/core/res/res/values-en-rIN/donottranslate-cldr.xml
index e39a59a..9de1ba9 100644
--- a/core/res/res/values-en-rIN/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rIN/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">E d MMM y</string>
 </resources>
diff --git a/core/res/res/values-en-rNZ/donottranslate-cldr.xml b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
index 3a8b50b..e600878 100644
--- a/core/res/res/values-en-rNZ/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">E, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-en-rUS/donottranslate-cldr.xml b/core/res/res/values-en-rUS/donottranslate-cldr.xml
index 286cc0e..14ef2a0 100644
--- a/core/res/res/values-en-rUS/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rUS/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%2$s %3$s – %8$s, %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s – %6$s, %7$s %8$s, %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, MMMM d</string>
+    <string name="abbrev_wday_month_day_year">EEE, MMM d, y</string>
 </resources>
diff --git a/core/res/res/values-en-rZA/donottranslate-cldr.xml b/core/res/res/values-en-rZA/donottranslate-cldr.xml
index 2e2d608..7c7529f 100644
--- a/core/res/res/values-en-rZA/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rZA/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">E dd MMM y</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/donottranslate-cldr.xml b/core/res/res/values-es-rUS/donottranslate-cldr.xml
index 7ade142..1ff3f05 100644
--- a/core/res/res/values-es-rUS/donottranslate-cldr.xml
+++ b/core/res/res/values-es-rUS/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s al %6$s %8$s de %7$s de %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d \'de\' MMMM</string>
+    <string name="abbrev_wday_month_day_year">E d \'de\' MMM \'de\' y</string>
 </resources>
diff --git a/core/res/res/values-es/donottranslate-cldr.xml b/core/res/res/values-es/donottranslate-cldr.xml
index 0de0b64..7cefcce 100644
--- a/core/res/res/values-es/donottranslate-cldr.xml
+++ b/core/res/res/values-es/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s–%8$s de %2$s de %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s – %6$s %8$s de %7$s de %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d \'de\' MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d \'de\' MMM \'de\' y</string>
 </resources>
diff --git a/core/res/res/values-fi-rFI/donottranslate-cldr.xml b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
index 151d935..59cf4ee 100644
--- a/core/res/res/values-fi-rFI/donottranslate-cldr.xml
+++ b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s. – %8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s – %6$s %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d. MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d. MMM y</string>
 </resources>
diff --git a/core/res/res/values-fr/donottranslate-cldr.xml b/core/res/res/values-fr/donottranslate-cldr.xml
index bf93039..675cb7a 100644
--- a/core/res/res/values-fr/donottranslate-cldr.xml
+++ b/core/res/res/values-fr/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">du %3$s au %8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">du %1$s %3$s %2$s au %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">EEE d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d MMM y</string>
 </resources>
diff --git a/core/res/res/values-hi-rIN/donottranslate-cldr.xml b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
index 2a19da4..d9405d8 100644
--- a/core/res/res/values-hi-rIN/donottranslate-cldr.xml
+++ b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%9$s-%2$s-%3$s – %8$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s-%2$s-%3$s – %6$s, yyyy-%7$s-%8$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-hr-rHR/donottranslate-cldr.xml b/core/res/res/values-hr-rHR/donottranslate-cldr.xml
index 6f8d6e5..70f4b64 100644
--- a/core/res/res/values-hr-rHR/donottranslate-cldr.xml
+++ b/core/res/res/values-hr-rHR/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s. - %8$s.%2$s.%9$s.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.%9$s.</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d. MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d.MMM.y.</string>
 </resources>
diff --git a/core/res/res/values-hu-rHU/donottranslate-cldr.xml b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
index 1940889..a34c541 100644
--- a/core/res/res/values-hu-rHU/donottranslate-cldr.xml
+++ b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%9$s. %2$s %3$s-%8$s.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s. %2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">y. MMM d., E</string>
 </resources>
diff --git a/core/res/res/values-id-rID/donottranslate-cldr.xml b/core/res/res/values-id-rID/donottranslate-cldr.xml
index ee33241..6c1496f 100644
--- a/core/res/res/values-id-rID/donottranslate-cldr.xml
+++ b/core/res/res/values-id-rID/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s - %8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">E, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-it/donottranslate-cldr.xml b/core/res/res/values-it/donottranslate-cldr.xml
index 5cc697c..34941e2 100644
--- a/core/res/res/values-it/donottranslate-cldr.xml
+++ b/core/res/res/values-it/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">EEE d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d MMM y</string>
 </resources>
diff --git a/core/res/res/values-ja/donottranslate-cldr.xml b/core/res/res/values-ja/donottranslate-cldr.xml
index dab8e2a..d4884bf 100644
--- a/core/res/res/values-ja/donottranslate-cldr.xml
+++ b/core/res/res/values-ja/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日~%8$s日</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日 (%1$s)~%7$s%8$s日 (%6$s)</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">M月d日 (E)</string>
+    <string name="abbrev_wday_month_day_year">y年M月d日 (E)</string>
 </resources>
diff --git a/core/res/res/values-ko/donottranslate-cldr.xml b/core/res/res/values-ko/donottranslate-cldr.xml
index 6b792c6..67a5e7c 100644
--- a/core/res/res/values-ko/donottranslate-cldr.xml
+++ b/core/res/res/values-ko/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %8$s일</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">MMMM d일 E</string>
+    <string name="abbrev_wday_month_day_year">y년 MMM d일 EEE</string>
 </resources>
diff --git a/core/res/res/values-lt-rLT/donottranslate-cldr.xml b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
index ad410e7..8a8822f 100644
--- a/core/res/res/values-lt-rLT/donottranslate-cldr.xml
+++ b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%9$s m. %2$s %3$s-%8$s d.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s m. %2$s %3$s d., %1$s-%7$s %8$s d., %6$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">MMMM d \'d\'., E</string>
+    <string name="abbrev_wday_month_day_year">y \'m\'. MMM d \'d\'., E</string>
 </resources>
diff --git a/core/res/res/values-lv-rLV/donottranslate-cldr.xml b/core/res/res/values-lv-rLV/donottranslate-cldr.xml
index 2c6765a..3b6e55f 100644
--- a/core/res/res/values-lv-rLV/donottranslate-cldr.xml
+++ b/core/res/res/values-lv-rLV/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%9$s. gada %3$s.-%8$s. %2$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %9$s. gada %3$s. %2$s-%6$s, y. gada %8$s. %7$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d. MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, yyyy. \'g\'. dd. MMM</string>
 </resources>
diff --git a/core/res/res/values-nb/donottranslate-cldr.xml b/core/res/res/values-nb/donottranslate-cldr.xml
index ecf0111..62ec12c 100644
--- a/core/res/res/values-nb/donottranslate-cldr.xml
+++ b/core/res/res/values-nb/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s–%6$s %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d. MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d. MMM y</string>
 </resources>
diff --git a/core/res/res/values-nl/donottranslate-cldr.xml b/core/res/res/values-nl/donottranslate-cldr.xml
index 2360e3f..101250e 100644
--- a/core/res/res/values-nl/donottranslate-cldr.xml
+++ b/core/res/res/values-nl/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d MMM y</string>
 </resources>
diff --git a/core/res/res/values-pl/donottranslate-cldr.xml b/core/res/res/values-pl/donottranslate-cldr.xml
index f20a5b7..00a6d1c 100644
--- a/core/res/res/values-pl/donottranslate-cldr.xml
+++ b/core/res/res/values-pl/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s-%6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/donottranslate-cldr.xml b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
index 197cb6e..f11ad2c 100644
--- a/core/res/res/values-pt-rPT/donottranslate-cldr.xml
+++ b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s de %2$s - %6$s, %8$s de %7$s de %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">EEE, d \'de\' MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d \'de\' MMM \'de\' y</string>
 </resources>
diff --git a/core/res/res/values-pt/donottranslate-cldr.xml b/core/res/res/values-pt/donottranslate-cldr.xml
index 1111658..e80005e 100644
--- a/core/res/res/values-pt/donottranslate-cldr.xml
+++ b/core/res/res/values-pt/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s de %2$s - %6$s, %8$s de %7$s de %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">EEE, d \'de\' MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d \'de\' MMM \'de\' y</string>
 </resources>
diff --git a/core/res/res/values-ro-rRO/donottranslate-cldr.xml b/core/res/res/values-ro-rRO/donottranslate-cldr.xml
index 4622445..ef34103 100644
--- a/core/res/res/values-ro-rRO/donottranslate-cldr.xml
+++ b/core/res/res/values-ro-rRO/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-ru/donottranslate-cldr.xml b/core/res/res/values-ru/donottranslate-cldr.xml
index 4870124..1b9938c 100644
--- a/core/res/res/values-ru/donottranslate-cldr.xml
+++ b/core/res/res/values-ru/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s г.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s - %8$s %7$s %9$s г.</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">E, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-sk-rSK/donottranslate-cldr.xml b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
index 6478074..efd8e6a 100644
--- a/core/res/res/values-sk-rSK/donottranslate-cldr.xml
+++ b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s. - %8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s. %2$s - %6$s %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d. MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d. MMM y</string>
 </resources>
diff --git a/core/res/res/values-sl-rSI/donottranslate-cldr.xml b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
index ae16782..7bffe0c 100644
--- a/core/res/res/values-sl-rSI/donottranslate-cldr.xml
+++ b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s–%6$s, %8$s. %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">E, d. MMM y</string>
 </resources>
diff --git a/core/res/res/values-sr-rRS/donottranslate-cldr.xml b/core/res/res/values-sr-rRS/donottranslate-cldr.xml
index 55ca968..60f81d8 100644
--- a/core/res/res/values-sr-rRS/donottranslate-cldr.xml
+++ b/core/res/res/values-sr-rRS/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s.</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E MMMM d</string>
+    <string name="abbrev_wday_month_day_year">EEE, d. MMM y.</string>
 </resources>
diff --git a/core/res/res/values-sv/donottranslate-cldr.xml b/core/res/res/values-sv/donottranslate-cldr.xml
index 0172755..187e1b1 100644
--- a/core/res/res/values-sv/donottranslate-cldr.xml
+++ b/core/res/res/values-sv/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s – %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d MMM y</string>
 </resources>
diff --git a/core/res/res/values-th-rTH/donottranslate-cldr.xml b/core/res/res/values-th-rTH/donottranslate-cldr.xml
index b3c76a3..8970549 100644
--- a/core/res/res/values-th-rTH/donottranslate-cldr.xml
+++ b/core/res/res/values-th-rTH/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s–%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s – %6$s %8$s %7$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE d MMM y</string>
 </resources>
diff --git a/core/res/res/values-tr/donottranslate-cldr.xml b/core/res/res/values-tr/donottranslate-cldr.xml
index fd8e762..9e614a6 100644
--- a/core/res/res/values-tr/donottranslate-cldr.xml
+++ b/core/res/res/values-tr/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%3$s %2$s %1$s - %8$s %7$s %6$s %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">dd MMMM E</string>
+    <string name="abbrev_wday_month_day_year">dd MMM y EEE</string>
 </resources>
diff --git a/core/res/res/values-uk-rUA/donottranslate-cldr.xml b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
index ed310c8..1b35326 100644
--- a/core/res/res/values-uk-rUA/donottranslate-cldr.xml
+++ b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%3$s – %8$s %2$s %9$s р.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s – %6$s, %8$s %7$s %9$s р.</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d MMM y \'р\'.</string>
 </resources>
diff --git a/core/res/res/values-vi-rVN/donottranslate-cldr.xml b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
index 6f2d342..30e0887 100644
--- a/core/res/res/values-vi-rVN/donottranslate-cldr.xml
+++ b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">Ngày %3$s tháng %2$s - Ngày %8$s tháng M năm %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, ngày %3$s %2$s - %6$s, ngày %8$s %7$s năm %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E d MMMM</string>
+    <string name="abbrev_wday_month_day_year">EEE, d MMM y</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/donottranslate-cldr.xml b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
index 5077e94..e852dd1 100644
--- a/core/res/res/values-zh-rCN/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%9$s 年 %2$s %3$s - %8$s 日</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s 年 %2$s %3$s 日%1$s - %7$s %8$s 日%6$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">MMMM d 日E</string>
+    <string name="abbrev_wday_month_day_year">y 年 MMM d 日EEE</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/donottranslate-cldr.xml b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
index 3e1acf1..63293d8 100644
--- a/core/res/res/values-zh-rTW/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%9$s 年 %2$s %3$s 日至 %8$s 日</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s 年 %2$s %3$s 日%1$s至 %7$s %8$s 日%6$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">MMMM d 日E</string>
+    <string name="abbrev_wday_month_day_year">y 年 MMM d 日EEE</string>
 </resources>
diff --git a/core/res/res/values/donottranslate-cldr.xml b/core/res/res/values/donottranslate-cldr.xml
index 286cc0e..14ef2a0 100644
--- a/core/res/res/values/donottranslate-cldr.xml
+++ b/core/res/res/values/donottranslate-cldr.xml
@@ -144,4 +144,6 @@
     <string name="same_month_mdy1_mdy2">%2$s %3$s – %8$s, %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s – %6$s, %7$s %8$s, %9$s</string>
     <string name="short_format_month">%b</string>
+    <string name="full_wday_month_day_no_year">E, MMMM d</string>
+    <string name="abbrev_wday_month_day_year">EEE, MMM d, y</string>
 </resources>
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c3aeca4..e728091 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -410,6 +410,13 @@
             = new ArrayList<BroadcastRecord>();
 
     /**
+     * Historical data of past broadcasts, for debugging.
+     */
+    static final int MAX_BROADCAST_HISTORY = 100;
+    final BroadcastRecord[] mBroadcastHistory
+            = new BroadcastRecord[MAX_BROADCAST_HISTORY];
+
+    /**
      * Set when we current have a BROADCAST_INTENT_MSG in flight.
      */
     boolean mBroadcastsScheduled = false;
@@ -9392,6 +9399,17 @@
             }
 
             pw.println(" ");
+            pw.println("  Historical broadcasts:");
+            for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
+                BroadcastRecord r = mBroadcastHistory[i];
+                if (r == null) {
+                    break;
+                }
+                pw.println("  Historical Broadcast #" + i + ":");
+                r.dump(pw, "    ");
+            }
+            
+            pw.println(" ");
             pw.println("  mBroadcastsScheduled=" + mBroadcastsScheduled);
             if (mStickyBroadcasts != null) {
                 pw.println(" ");
@@ -11610,7 +11628,7 @@
                     Intent intent = (Intent)allSticky.get(i);
                     BroadcastRecord r = new BroadcastRecord(intent, null,
                             null, -1, -1, null, receivers, null, 0, null, null,
-                            false, true);
+                            false, true, true);
                     if (mParallelBroadcasts.size() == 0) {
                         scheduleBroadcastsLocked();
                     }
@@ -11835,7 +11853,7 @@
             BroadcastRecord r = new BroadcastRecord(intent, callerApp,
                     callerPackage, callingPid, callingUid, requiredPermission,
                     registeredReceivers, resultTo, resultCode, resultData, map,
-                    ordered, false);
+                    ordered, sticky, false);
             if (DEBUG_BROADCAST) Log.v(
                     TAG, "Enqueueing parallel broadcast " + r
                     + ": prev had " + mParallelBroadcasts.size());
@@ -11914,7 +11932,8 @@
                 || resultTo != null) {
             BroadcastRecord r = new BroadcastRecord(intent, callerApp,
                     callerPackage, callingPid, callingUid, requiredPermission,
-                    receivers, resultTo, resultCode, resultData, map, ordered, false);
+                    receivers, resultTo, resultCode, resultData, map, ordered,
+                    sticky, false);
             if (DEBUG_BROADCAST) Log.v(
                     TAG, "Enqueueing ordered broadcast " + r
                     + ": prev had " + mOrderedBroadcasts.size());
@@ -12132,17 +12151,17 @@
             }
             long now = SystemClock.uptimeMillis();
             BroadcastRecord r = mOrderedBroadcasts.get(0);
-            if ((r.startTime+BROADCAST_TIMEOUT) > now) {
+            if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
                 if (DEBUG_BROADCAST) Log.v(TAG,
                         "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
-                        + (r.startTime + BROADCAST_TIMEOUT));
+                        + (r.receiverTime + BROADCAST_TIMEOUT));
                 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
-                mHandler.sendMessageAtTime(msg, r.startTime+BROADCAST_TIMEOUT);
+                mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
                 return;
             }
 
             Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
-            r.startTime = now;
+            r.receiverTime = now;
             r.anrCount++;
 
             // Current receiver has passed its expiration date.
@@ -12290,7 +12309,7 @@
                 }
                 performReceive(filter.receiverList.app, filter.receiverList.receiver,
                     new Intent(r.intent), r.resultCode,
-                    r.resultData, r.resultExtras, r.ordered, r.sticky);
+                    r.resultData, r.resultExtras, r.ordered, r.initialSticky);
                 if (ordered) {
                     r.state = BroadcastRecord.CALL_DONE_RECEIVE;
                 }
@@ -12308,6 +12327,17 @@
         }
     }
 
+    private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
+        if (r.callingUid < 0) {
+            // This was from a registerReceiver() call; ignore it.
+            return;
+        }
+        System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
+                MAX_BROADCAST_HISTORY-1);
+        r.finishTime = SystemClock.uptimeMillis();
+        mBroadcastHistory[0] = r;
+    }
+    
     private final void processNextBroadcast(boolean fromMsg) {
         synchronized(this) {
             BroadcastRecord r;
@@ -12325,6 +12355,7 @@
             // First, deliver any non-serialized broadcasts right away.
             while (mParallelBroadcasts.size() > 0) {
                 r = mParallelBroadcasts.remove(0);
+                r.dispatchTime = SystemClock.uptimeMillis();
                 final int N = r.receivers.size();
                 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing parallel broadcast "
                         + r);
@@ -12335,6 +12366,7 @@
                             + target + ": " + r);
                     deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
                 }
+                addBroadcastToHistoryLocked(r);
                 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Done with parallel broadcast "
                         + r);
             }
@@ -12392,7 +12424,7 @@
                         Log.w(TAG, "Hung broadcast discarded after timeout failure:"
                                 + " now=" + now
                                 + " dispatchTime=" + r.dispatchTime
-                                + " startTime=" + r.startTime
+                                + " startTime=" + r.receiverTime
                                 + " intent=" + r.intent
                                 + " numReceivers=" + numReceivers
                                 + " nextReceiver=" + r.nextReceiver
@@ -12436,6 +12468,7 @@
                             + r);
                     
                     // ... and on to the next...
+                    addBroadcastToHistoryLocked(r);
                     mOrderedBroadcasts.remove(0);
                     r = null;
                     looped = true;
@@ -12448,17 +12481,17 @@
 
             // Keep track of when this receiver started, and make sure there
             // is a timeout message pending to kill it if need be.
-            r.startTime = SystemClock.uptimeMillis();
+            r.receiverTime = SystemClock.uptimeMillis();
             if (recIdx == 0) {
-                r.dispatchTime = r.startTime;
+                r.dispatchTime = r.receiverTime;
 
                 if (DEBUG_BROADCAST_LIGHT) Log.v(TAG, "Processing ordered broadcast "
                         + r);
                 if (DEBUG_BROADCAST) Log.v(TAG,
                         "Submitting BROADCAST_TIMEOUT_MSG for "
-                        + (r.startTime + BROADCAST_TIMEOUT));
+                        + (r.receiverTime + BROADCAST_TIMEOUT));
                 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
-                mHandler.sendMessageAtTime(msg, r.startTime+BROADCAST_TIMEOUT);
+                mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
             }
 
             Object nextReceiver = r.receivers.get(recIdx);
@@ -12801,8 +12834,15 @@
                     }
                 }
                 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
                         null, false, false, MY_PID, Process.SYSTEM_UID);
+                if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
+                    broadcastIntentLocked(null, null,
+                            new Intent(Intent.ACTION_LOCALE_CHANGED),
+                            null, null, 0, null, null,
+                            null, false, false, MY_PID, Process.SYSTEM_UID);
+                }
                 
                 AttributeCache ac = AttributeCache.instance();
                 if (ac != null) {
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index 0eeb393..2e784d3 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -39,8 +39,16 @@
         receiverList.dumpLocal(pw, prefix);
     }
     
+    public void dumpBrief(PrintWriter pw, String prefix) {
+        dumpBroadcastFilterState(pw, prefix);
+    }
+    
     public void dumpInReceiverList(PrintWriter pw, Printer pr, String prefix) {
         super.dump(pr, prefix);
+        dumpBroadcastFilterState(pw, prefix);
+    }
+    
+    void dumpBroadcastFilterState(PrintWriter pw, String prefix) {
         if (requiredPermission != null) {
             pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
         }
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index db0a6cb..75c9600 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -41,11 +41,13 @@
     final int callingUid;   // the uid of who sent this
     final boolean ordered;  // serialize the send to receivers?
     final boolean sticky;   // originated from existing sticky data?
+    final boolean initialSticky; // initial broadcast from register to sticky?
     final String requiredPermission; // a permission the caller has required
     final List receivers;   // contains BroadcastFilter and ResolveInfo
     final IIntentReceiver resultTo; // who receives final result if non-null
     long dispatchTime;      // when dispatch started on this set of receivers
-    long startTime;         // when current receiver started for timeouts.
+    long receiverTime;      // when current receiver started for timeouts.
+    long finishTime;        // when we finished the broadcast.
     int resultCode;         // current result code value.
     String resultData;      // current result data value.
     Bundle resultExtras;    // current result extra data values.
@@ -73,28 +75,55 @@
     void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + this);
         pw.println(prefix + intent);
+        if (sticky) {
+            Bundle bundle = intent.getExtras();
+            if (bundle != null) {
+                pw.println(prefix + "extras: " + bundle.toString());
+            }
+        }
         pw.println(prefix + "proc=" + callerApp);
         pw.println(prefix + "caller=" + callerPackage
                 + " callingPid=" + callingPid
                 + " callingUid=" + callingUid);
-        pw.println(prefix + "requiredPermission=" + requiredPermission);
+        if (requiredPermission != null) {
+            pw.println(prefix + "requiredPermission=" + requiredPermission);
+        }
         pw.println(prefix + "dispatchTime=" + dispatchTime + " ("
-                + (SystemClock.uptimeMillis()-dispatchTime) + " since now)");
-        pw.println(prefix + "startTime=" + startTime + " ("
-                + (SystemClock.uptimeMillis()-startTime) + " since now)");
-        pw.println(prefix + "anrCount=" + anrCount);
-        pw.println(prefix + "resultTo=" + resultTo
-              + " resultCode=" + resultCode + " resultData=" + resultData);
-        pw.println(prefix + "resultExtras=" + resultExtras);
-        pw.println(prefix + "resultAbort=" + resultAbort
-                + " ordered=" + ordered + " sticky=" + sticky);
-        pw.println(prefix + "nextReceiver=" + nextReceiver
-              + " receiver=" + receiver);
-        pw.println(prefix + "curFilter=" + curFilter);
-        pw.println(prefix + "curReceiver="
-                + ((curReceiver != null) ? curReceiver : "(null)"));
-        pw.println(prefix + "curApp=" + curApp);
+                + (SystemClock.uptimeMillis()-dispatchTime) + "ms since now)");
+        if (finishTime != 0) {
+            pw.println(prefix + "finishTime=" + finishTime + " ("
+                    + (SystemClock.uptimeMillis()-finishTime) + "ms since now)");
+        } else {
+            pw.println(prefix + "receiverTime=" + receiverTime + " ("
+                    + (SystemClock.uptimeMillis()-receiverTime) + "ms since now)");
+        }
+        if (anrCount != 0) {
+            pw.println(prefix + "anrCount=" + anrCount);
+        }
+        if (resultTo != null || resultCode != -1 || resultData != null) {
+            pw.println(prefix + "resultTo=" + resultTo
+                  + " resultCode=" + resultCode + " resultData=" + resultData);
+        }
+        if (resultExtras != null) {
+            pw.println(prefix + "resultExtras=" + resultExtras);
+        }
+        if (resultAbort || ordered || sticky || initialSticky) {
+            pw.println(prefix + "resultAbort=" + resultAbort
+                    + " ordered=" + ordered + " sticky=" + sticky
+                    + " initialSticky=" + initialSticky);
+        }
+        if (nextReceiver != 0 || receiver != null) {
+            pw.println(prefix + "nextReceiver=" + nextReceiver
+                  + " receiver=" + receiver);
+        }
+        if (curFilter != null) {
+            pw.println(prefix + "curFilter=" + curFilter);
+        }
+        if (curReceiver != null) {
+            pw.println(prefix + "curReceiver=" + curReceiver);
+        }
         if (curApp != null) {
+            pw.println(prefix + "curApp=" + curApp);
             pw.println(prefix + "curComponent="
                     + (curComponent != null ? curComponent.toShortString() : "--"));
             pw.println(prefix + "curSourceDir=" + curReceiver.applicationInfo.sourceDir);
@@ -114,7 +143,7 @@
             Object o = receivers.get(i);
             pw.println(prefix + "Receiver #" + i + ": " + o);
             if (o instanceof BroadcastFilter)
-                ((BroadcastFilter)o).dump(pw, p2);
+                ((BroadcastFilter)o).dumpBrief(pw, p2);
             else if (o instanceof ResolveInfo)
                 ((ResolveInfo)o).dump(printer, p2);
         }
@@ -124,7 +153,7 @@
             int _callingPid, int _callingUid, String _requiredPermission,
             List _receivers, IIntentReceiver _resultTo, int _resultCode,
             String _resultData, Bundle _resultExtras, boolean _serialized,
-            boolean _sticky) {
+            boolean _sticky, boolean _initialSticky) {
         intent = _intent;
         callerApp = _callerApp;
         callerPackage = _callerPackage;
@@ -138,6 +167,7 @@
         resultExtras = _resultExtras;
         ordered = _serialized;
         sticky = _sticky;
+        initialSticky = _initialSticky;
         nextReceiver = 0;
         state = IDLE;
     }