Merge "Add a content observer for voicemail to the call log fragment"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b0d988c..0f3285e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -22,6 +22,7 @@
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
     <uses-permission android:name="android.permission.READ_CALL_LOG" />
     <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+    <uses-permission android:name="android.permission.READ_PROFILE" />
     <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
diff --git a/res/drawable-hdpi/dialer_recent_card_bg.9.png b/res/drawable-hdpi/dialer_recent_card_bg.9.png
index e581943..2bfdbcb 100644
--- a/res/drawable-hdpi/dialer_recent_card_bg.9.png
+++ b/res/drawable-hdpi/dialer_recent_card_bg.9.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_ab_search.png b/res/drawable-hdpi/ic_ab_search.png
new file mode 100644
index 0000000..3702846
--- /dev/null
+++ b/res/drawable-hdpi/ic_ab_search.png
Binary files differ
diff --git a/res/drawable-hdpi/list_item_avatar_bg.png b/res/drawable-hdpi/list_item_avatar_bg.png
index e6eb68e..66e5f3e 100644
--- a/res/drawable-hdpi/list_item_avatar_bg.png
+++ b/res/drawable-hdpi/list_item_avatar_bg.png
Binary files differ
diff --git a/res/drawable-hdpi/shadow_contact_photo.png b/res/drawable-hdpi/shadow_contact_photo.png
index 49cbb97..44b06f2 100644
--- a/res/drawable-hdpi/shadow_contact_photo.png
+++ b/res/drawable-hdpi/shadow_contact_photo.png
Binary files differ
diff --git a/res/drawable-mdpi/dialer_recent_card_bg.9.png b/res/drawable-mdpi/dialer_recent_card_bg.9.png
index cb1d26f..dff6a0b 100644
--- a/res/drawable-mdpi/dialer_recent_card_bg.9.png
+++ b/res/drawable-mdpi/dialer_recent_card_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_ab_search.png b/res/drawable-mdpi/ic_ab_search.png
new file mode 100644
index 0000000..cc9f911
--- /dev/null
+++ b/res/drawable-mdpi/ic_ab_search.png
Binary files differ
diff --git a/res/drawable-mdpi/list_item_avatar_bg.png b/res/drawable-mdpi/list_item_avatar_bg.png
index 1306cfc..640eb3e 100644
--- a/res/drawable-mdpi/list_item_avatar_bg.png
+++ b/res/drawable-mdpi/list_item_avatar_bg.png
Binary files differ
diff --git a/res/drawable-mdpi/shadow_contact_photo.png b/res/drawable-mdpi/shadow_contact_photo.png
index 4734bbd..8665d83 100644
--- a/res/drawable-mdpi/shadow_contact_photo.png
+++ b/res/drawable-mdpi/shadow_contact_photo.png
Binary files differ
diff --git a/res/drawable-xhdpi/dialer_recent_card_bg.9.png b/res/drawable-xhdpi/dialer_recent_card_bg.9.png
index e1a4b67..05d254d 100644
--- a/res/drawable-xhdpi/dialer_recent_card_bg.9.png
+++ b/res/drawable-xhdpi/dialer_recent_card_bg.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_ab_search.png b/res/drawable-xhdpi/ic_ab_search.png
new file mode 100644
index 0000000..718ff49
--- /dev/null
+++ b/res/drawable-xhdpi/ic_ab_search.png
Binary files differ
diff --git a/res/drawable-xhdpi/list_item_avatar_bg.png b/res/drawable-xhdpi/list_item_avatar_bg.png
index 3f271a0..cac7fbd 100644
--- a/res/drawable-xhdpi/list_item_avatar_bg.png
+++ b/res/drawable-xhdpi/list_item_avatar_bg.png
Binary files differ
diff --git a/res/drawable-xhdpi/shadow_contact_photo.png b/res/drawable-xhdpi/shadow_contact_photo.png
index 1077ec1..8359a50 100644
--- a/res/drawable-xhdpi/shadow_contact_photo.png
+++ b/res/drawable-xhdpi/shadow_contact_photo.png
Binary files differ
diff --git a/res/drawable-xxhdpi/dialer_recent_card_bg.9.png b/res/drawable-xxhdpi/dialer_recent_card_bg.9.png
index 6142078..87d95f0 100644
--- a/res/drawable-xxhdpi/dialer_recent_card_bg.9.png
+++ b/res/drawable-xxhdpi/dialer_recent_card_bg.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_ab_search.png b/res/drawable-xxhdpi/ic_ab_search.png
new file mode 100644
index 0000000..4bb5165
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_ab_search.png
Binary files differ
diff --git a/res/drawable-xxhdpi/list_item_avatar_bg.png b/res/drawable-xxhdpi/list_item_avatar_bg.png
index 8b03a65..fcfe2da 100644
--- a/res/drawable-xxhdpi/list_item_avatar_bg.png
+++ b/res/drawable-xxhdpi/list_item_avatar_bg.png
Binary files differ
diff --git a/res/drawable-xxhdpi/shadow_contact_photo.png b/res/drawable-xxhdpi/shadow_contact_photo.png
index 1c60c8d..bfeb0ff 100644
--- a/res/drawable-xxhdpi/shadow_contact_photo.png
+++ b/res/drawable-xxhdpi/shadow_contact_photo.png
Binary files differ
diff --git a/res/drawable/bottom_border_background_pressed.xml b/res/drawable/bottom_border_background_pressed.xml
index 0924914..fc5a5b8 100644
--- a/res/drawable/bottom_border_background_pressed.xml
+++ b/res/drawable/bottom_border_background_pressed.xml
@@ -15,5 +15,5 @@
 -->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
     <item android:drawable="@drawable/bottom_border_background" />
-    <item android:drawable="@*android:drawable/list_selector_background_transition_holo_light" />
+    <item android:drawable="@drawable/list_selector_background_transition_holo_light" />
 </layer-list>
\ No newline at end of file
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index 1bd448c..1d368f6 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -39,8 +39,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_centerVertical="true"
-            android:paddingStart="@dimen/call_log_outer_margin"
-            android:paddingEnd="@dimen/call_log_outer_margin"
+            android:padding="@dimen/call_log_outer_margin"
             android:orientation="horizontal"
             android:gravity="center_vertical"
             android:background="?android:attr/selectableItemBackground"
@@ -60,8 +59,6 @@
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
-                android:paddingTop="@dimen/call_log_inner_margin"
-                android:paddingBottom="@dimen/call_log_inner_margin"
                 android:orientation="vertical"
                 android:gravity="center_vertical"
                 android:layout_marginStart="@dimen/call_log_inner_margin"
@@ -72,7 +69,7 @@
                     android:layout_height="wrap_content"
                     android:layout_marginEnd="@dimen/call_log_icon_margin"
                     android:textColor="?attr/call_log_primary_text_color"
-                    android:textSize="18sp"
+                    android:textSize="16sp"
                     android:singleLine="true"
                 />
                 <LinearLayout
@@ -86,8 +83,7 @@
                         android:layout_height="wrap_content"
                         android:layout_marginEnd="@dimen/call_log_icon_margin"
                         android:textColor="?attr/call_log_secondary_text_color"
-                        android:textStyle="bold"
-                        android:textSize="14sp"
+                        android:textSize="12sp"
                         android:singleLine="true"
                         android:ellipsize="marquee"
                         />
@@ -113,7 +109,7 @@
                         android:layout_marginEnd="@dimen/call_log_icon_margin"
                         android:layout_gravity="center_vertical"
                         android:textColor="?attr/call_log_secondary_text_color"
-                        android:textSize="14sp"
+                        android:textSize="12sp"
                         android:singleLine="true"
                     />
                 </LinearLayout>
diff --git a/res/layout/dialpad.xml b/res/layout/dialpad.xml
index bc910db..4fc3e83 100644
--- a/res/layout/dialpad.xml
+++ b/res/layout/dialpad.xml
@@ -40,7 +40,7 @@
             android:focusable="true" >
             <LinearLayout
                 android:layout_width="wrap_content"
-                android:layout_height="match_parent"
+                android:layout_height="wrap_content"
                 android:layout_gravity="center" >
                 <TextView
                     android:id="@+id/dialpad_key_number"
diff --git a/res/layout/dialpad_fragment.xml b/res/layout/dialpad_fragment.xml
index 32b1d60..e673cea 100644
--- a/res/layout/dialpad_fragment.xml
+++ b/res/layout/dialpad_fragment.xml
@@ -19,7 +19,8 @@
     android:layout_height="match_parent"
     android:orientation="vertical" >
     <!-- spacer view -->
-    <Space
+    <View
+        android:id="@+id/spacer"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1" />
diff --git a/res/layout/dialpad_key.xml b/res/layout/dialpad_key.xml
index e87fde0..c104f8a 100644
--- a/res/layout/dialpad_key.xml
+++ b/res/layout/dialpad_key.xml
@@ -22,7 +22,7 @@
     android:focusable="true" >
     <LinearLayout
         android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:layout_gravity="center">
       <TextView
           android:id="@+id/dialpad_key_number"
diff --git a/res/layout/dialtacts_activity.xml b/res/layout/dialtacts_activity.xml
index 255eb49..e2c3853 100644
--- a/res/layout/dialtacts_activity.xml
+++ b/res/layout/dialtacts_activity.xml
@@ -81,36 +81,41 @@
             android:id="@+id/dialtacts_frame"
             android:clipChildren="false">
         </FrameLayout>
+        <View
+            android:layout_height="2dp"
+            android:layout_width="match_parent"
+            android:background="#33999999"
+        />
         <FrameLayout
-        android:layout_height="@dimen/fake_action_bar_height"
-        android:layout_width="match_parent"
-        android:id="@+id/fake_action_bar"
-        android:background="@color/actionbar_background_color">
-        <ImageButton
-            android:id="@+id/call_history_button"
-            android:layout_width="@dimen/fake_menu_button_min_width"
-            android:layout_height="match_parent"
-            android:layout_gravity="bottom|start"
-            android:background="?android:attr/selectableItemBackground"
-            android:contentDescription="@string/action_menu_call_history_description"
-            android:src="@drawable/ic_menu_history_dk"/>
-        <ImageButton
-            android:id="@+id/dialpad_button"
-            android:layout_width="@dimen/fake_menu_button_min_width"
-            android:layout_height="match_parent"
-            android:layout_gravity="bottom|center"
-            android:background="?android:attr/selectableItemBackground"
-            android:contentDescription="@string/action_menu_dialpad_button"
-            android:src="@drawable/ic_menu_dialpad_dk"/>
-        <ImageButton
-             android:id="@+id/overflow_menu"
-             android:layout_width="@dimen/fake_menu_button_min_width"
-             android:layout_height="match_parent"
-             android:layout_gravity="bottom|end"
-             android:src="@drawable/ic_menu_overflow_dk"
-             android:contentDescription="@string/action_menu_overflow_description"
-             android:background="?android:attr/selectableItemBackground"/>
-    </FrameLayout>
+            android:layout_height="@dimen/fake_action_bar_height"
+            android:layout_width="match_parent"
+            android:id="@+id/fake_action_bar"
+            android:background="@color/actionbar_background_color">
+            <ImageButton
+                android:id="@+id/call_history_button"
+                android:layout_width="@dimen/fake_menu_button_min_width"
+                android:layout_height="match_parent"
+                android:layout_gravity="bottom|start"
+                android:background="?android:attr/selectableItemBackground"
+                android:contentDescription="@string/action_menu_call_history_description"
+                android:src="@drawable/ic_menu_history_dk"/>
+            <ImageButton
+                android:id="@+id/dialpad_button"
+                android:layout_width="@dimen/fake_menu_button_min_width"
+                android:layout_height="match_parent"
+                android:layout_gravity="bottom|center"
+                android:background="?android:attr/selectableItemBackground"
+                android:contentDescription="@string/action_menu_dialpad_button"
+                android:src="@drawable/ic_menu_dialpad_dk"/>
+            <ImageButton
+                 android:id="@+id/overflow_menu"
+                 android:layout_width="@dimen/fake_menu_button_min_width"
+                 android:layout_height="match_parent"
+                 android:layout_gravity="bottom|end"
+                 android:src="@drawable/ic_menu_overflow_dk"
+                 android:contentDescription="@string/action_menu_overflow_description"
+                 android:background="?android:attr/selectableItemBackground"/>
+        </FrameLayout>
         <View
             android:id="@+id/dialtacts_bottom_padding"
             android:layout_width="match_parent"
diff --git a/res/layout/phone_favorite_regular_row_view.xml b/res/layout/phone_favorite_regular_row_view.xml
index a90117f..012c9be 100644
--- a/res/layout/phone_favorite_regular_row_view.xml
+++ b/res/layout/phone_favorite_regular_row_view.xml
@@ -49,7 +49,8 @@
                 android:id="@id/contact_tile_name"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:textSize="16sp"
+                android:textColor="@color/dialtacts_primary_text_color"/>
                 android:singleLine="true"
                 android:fadingEdge="horizontal"
                 android:fadingEdgeLength="3dip"
diff --git a/res/layout/phone_favorite_tile_view.xml b/res/layout/phone_favorite_tile_view.xml
index fce25ea..8806d39 100644
--- a/res/layout/phone_favorite_tile_view.xml
+++ b/res/layout/phone_favorite_tile_view.xml
@@ -55,7 +55,7 @@
                 android:layout_height="wrap_content"
                 android:gravity="center_vertical"
                 android:textColor="@color/contact_tile_name_color"
-                android:fontFamily="sans-serif-light"
+                android:fontFamily="sans-serif"
                 android:singleLine="true"
                 android:textSize="16sp"
                 android:fadingEdge="horizontal"
@@ -68,7 +68,7 @@
                 android:layout_height="wrap_content"
                 android:gravity="center_vertical"
                 android:textColor="@color/contact_tile_name_color"
-                android:fontFamily="sans-serif-light"
+                android:fontFamily="sans-serif"
                 android:singleLine="true"
                 android:textSize="12sp"
                 android:paddingBottom="2dp"
@@ -168,7 +168,7 @@
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:fontFamily="sans-serif-light"
+                android:fontFamily="sans-serif"
                 android:textSize="13sp"
                 android:ellipsize="marquee"
                 android:singleLine="true"
diff --git a/res/layout/show_all_contact_button.xml b/res/layout/show_all_contact_button.xml
index 824d10c..30060d7 100644
--- a/res/layout/show_all_contact_button.xml
+++ b/res/layout/show_all_contact_button.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<LinearLayout
+<com.android.contacts.common.list.ContactListItemView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/show_all_contact_button"
     android:orientation="horizontal"
@@ -23,23 +23,4 @@
     android:layout_height="match_parent"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center"
-    android:background="?android:attr/selectableItemBackground"
-    android:focusable="true">
-
-    <ImageView
-        android:layout_height="match_parent"
-        android:layout_width="wrap_content"
-        android:layout_gravity="center"
-        android:src="@drawable/ic_menu_all_contacts_dk"
-        android:layout_marginEnd="10dp"/>
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:textSize="14sp"
-        android:ellipsize="marquee"
-        android:singleLine="true"
-        android:text="@string/show_all_contacts_button_text"
-        android:textAlignment="center"
-        android:gravity="center"/>
-</LinearLayout>
\ No newline at end of file
+    android:focusable="true" />
\ No newline at end of file
diff --git a/res/values/animation_constants.xml b/res/values/animation_constants.xml
index b41b316..4e4bc36 100644
--- a/res/values/animation_constants.xml
+++ b/res/values/animation_constants.xml
@@ -24,7 +24,7 @@
     <integer name="max_dismiss_velocity">2000</integer>
     <integer name="snap_animation_duration">350</integer>
     <integer name="swipe_scroll_slop">2</integer>
-    <dimen name="min_swipe">5dip</dimen>
+    <dimen name="min_swipe">0dip</dimen>
     <dimen name="min_vert">10dip</dimen>
     <dimen name="min_lock">20dip</dimen>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 439ccc2..a8ddf2b 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -17,7 +17,7 @@
 <resources>
 
     <!-- Secondary text color in the Phone app -->
-    <color name="dialtacts_primary_text_color">#111111</color>
+    <color name="dialtacts_primary_text_color">#000000</color>
     <color name="dialtacts_secondary_text_color">#888888</color>
     <color name="dialpad_text_color">#ffffff</color>
 
@@ -41,7 +41,7 @@
     <color name="background_dialer_light">#cecece</color>
 
     <!-- Background color of dialer list items (contacts, call log entries) -->
-    <color name="background_dialer_list_items">#f5f5f5</color>
+    <color name="background_dialer_list_items">#eeeeee</color>
 
     <!-- Background color of new dialpad -->
     <color name="background_dialpad">#f2020709</color>
@@ -52,7 +52,7 @@
     <color name="dialpad_secondary_text_color">#aaaaaa</color>
 
     <!-- Background color of action bars -->
-    <color name="actionbar_background_color">#e6e6e6</color>
+    <color name="actionbar_background_color">#ffffff</color>
 
     <!-- Color of the 1dp divider that separates favorites -->
     <color name="favorite_contacts_separator_color">#d0d0d0</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e4e847c..1743952 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -30,7 +30,7 @@
     <dimen name="call_button_height">74dp</dimen>
 
     <!--  Search View -->
-    <dimen name="search_text_size">16sp</dimen>
+    <dimen name="search_text_size">14sp</dimen>
 
     <!-- Call Log -->
     <dimen name="call_log_call_action_size">32dip</dimen>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index f3b4098..89678fc 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -54,9 +54,9 @@
         <item name="contact_browser_background">@android:color/transparent</item>
         <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
         <!-- CallLog -->
-        <item name="call_log_primary_text_color">#111111</item>
+        <item name="call_log_primary_text_color">#000000</item>
         <item name="call_log_primary_background_color">#000000</item>
-        <item name="call_log_secondary_text_color">#555555</item>
+        <item name="call_log_secondary_text_color">@color/dialtacts_secondary_text_color</item>
         <item name="call_log_secondary_background_color">#333333</item>
         <item name="call_log_header_color">#33b5e5</item>
         <!-- VoicemailStatus -->
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index b0c8e68..a24940d 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -17,11 +17,13 @@
 package com.android.dialer;
 
 import android.app.Activity;
+import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.Loader;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
@@ -30,9 +32,10 @@
 import android.os.Bundle;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
-import android.provider.Contacts.Intents.Insert;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.DisplayNameSources;
+import android.provider.ContactsContract.Intents.Insert;
 import android.provider.VoicemailContract.Voicemails;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
@@ -54,6 +57,8 @@
 import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.ClipboardUtils;
 import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
 import com.android.contacts.common.util.UriUtils;
 import com.android.dialer.BackScrollManager.ScrollableHeader;
 import com.android.dialer.calllog.CallDetailHistoryAdapter;
@@ -80,6 +85,9 @@
 public class CallDetailActivity extends Activity implements ProximitySensorAware {
     private static final String TAG = "CallDetail";
 
+    private static final int LOADER_ID = 0;
+    private static final String BUNDLE_CONTACT_URI_EXTRA = "contact_uri_extra";
+
     private static final char LEFT_TO_RIGHT_EMBEDDING = '\u202A';
     private static final char POP_DIRECTIONAL_FORMATTING = '\u202C';
 
@@ -252,6 +260,35 @@
         }
     };
 
+    private final LoaderCallbacks<Contact> mLoaderCallbacks = new LoaderCallbacks<Contact>() {
+        @Override
+        public void onLoaderReset(Loader<Contact> loader) {
+        }
+
+        @Override
+        public void onLoadFinished(Loader<Contact> loader, Contact data) {
+            final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+            intent.setType(Contacts.CONTENT_ITEM_TYPE);
+            if (data.getDisplayNameSource() >= DisplayNameSources.ORGANIZATION) {
+                intent.putExtra(Insert.NAME, data.getDisplayName());
+            }
+            intent.putExtra(Insert.DATA, data.getContentValues());
+            bindContactPhotoAction(intent, R.drawable.ic_add_contact_holo_dark,
+                    getString(R.string.description_add_contact));
+        }
+
+        @Override
+        public Loader<Contact> onCreateLoader(int id, Bundle args) {
+            final Uri contactUri = args.getParcelable(BUNDLE_CONTACT_URI_EXTRA);
+            if (contactUri == null) {
+                Log.wtf(TAG, "No contact lookup uri provided.");
+            }
+            return new ContactLoader(CallDetailActivity.this, contactUri,
+                    false /* loadGroupMetaData */, false /* loadInvitableAccountTypes */,
+                    false /* postViewNotification */, true /* computeFormattedPhoneNumber */);
+        }
+    };
+
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -452,6 +489,8 @@
                     nameOrNumber = firstDetails.number;
                 }
 
+                boolean skipBind = false;
+
                 if (contactUri != null && !UriUtils.isEncodedContactUri(contactUri)) {
                     mainActionIntent = new Intent(Intent.ACTION_VIEW, contactUri);
                     // This will launch People's detail contact screen, so we probably want to
@@ -461,6 +500,14 @@
                     mainActionIcon = R.drawable.ic_contacts_holo_dark;
                     mainActionDescription =
                             getString(R.string.description_view_contact, nameOrNumber);
+                } else if (UriUtils.isEncodedContactUri(contactUri)) {
+                    final Bundle bundle = new Bundle(1);
+                    bundle.putParcelable(BUNDLE_CONTACT_URI_EXTRA, contactUri);
+                    getLoaderManager().initLoader(LOADER_ID, bundle, mLoaderCallbacks);
+                    mainActionIntent = null;
+                    mainActionIcon = R.drawable.ic_add_contact_holo_dark;
+                    mainActionDescription = getString(R.string.description_add_contact);
+                    skipBind = true;
                 } else if (isVoicemailNumber) {
                     mainActionIntent = null;
                     mainActionIcon = 0;
@@ -485,31 +532,16 @@
                     mainActionIcon = R.drawable.ic_add_contact_holo_dark;
                     mainActionDescription = getString(R.string.description_add_contact);
                 } else {
-                    // If we cannot call the number, when we probably cannot add it as a contact either.
-                    // This is usually the case of private, unknown, or payphone numbers.
+                    // If we cannot call the number, when we probably cannot add it as a contact
+                    // either. This is usually the case of private, unknown, or payphone numbers.
                     mainActionIntent = null;
                     mainActionIcon = 0;
                     mainActionDescription = null;
                 }
 
-                if (mainActionIntent == null) {
-                    mMainActionView.setVisibility(View.INVISIBLE);
-                    mMainActionPushLayerView.setVisibility(View.GONE);
-                    mHeaderTextView.setVisibility(View.INVISIBLE);
-                    mHeaderOverlayView.setVisibility(View.INVISIBLE);
-                } else {
-                    mMainActionView.setVisibility(View.VISIBLE);
-                    mMainActionView.setImageResource(mainActionIcon);
-                    mMainActionPushLayerView.setVisibility(View.VISIBLE);
-                    mMainActionPushLayerView.setOnClickListener(new View.OnClickListener() {
-                        @Override
-                        public void onClick(View v) {
-                            startActivity(mainActionIntent);
-                        }
-                    });
-                    mMainActionPushLayerView.setContentDescription(mainActionDescription);
-                    mHeaderTextView.setVisibility(View.VISIBLE);
-                    mHeaderOverlayView.setVisibility(View.VISIBLE);
+                if (!skipBind) {
+                    bindContactPhotoAction(mainActionIntent, mainActionIcon,
+                            mainActionDescription);
                 }
 
                 // This action allows to call the number that places the call.
@@ -597,6 +629,29 @@
         mAsyncTaskExecutor.submit(Tasks.UPDATE_PHONE_CALL_DETAILS, new UpdateContactDetailsTask());
     }
 
+    private void bindContactPhotoAction(final Intent actionIntent, int actionIcon,
+            String actionDescription) {
+        if (actionIntent == null) {
+            mMainActionView.setVisibility(View.INVISIBLE);
+            mMainActionPushLayerView.setVisibility(View.GONE);
+            mHeaderTextView.setVisibility(View.INVISIBLE);
+            mHeaderOverlayView.setVisibility(View.INVISIBLE);
+        } else {
+            mMainActionView.setVisibility(View.VISIBLE);
+            mMainActionView.setImageResource(actionIcon);
+            mMainActionPushLayerView.setVisibility(View.VISIBLE);
+            mMainActionPushLayerView.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    startActivity(actionIntent);
+                }
+            });
+            mMainActionPushLayerView.setContentDescription(actionDescription);
+            mHeaderTextView.setVisibility(View.VISIBLE);
+            mHeaderOverlayView.setVisibility(View.VISIBLE);
+        }
+    }
+
     /** Return the phone call details for a given call log URI. */
     private PhoneCallDetails getPhoneCallDetailsForUri(Uri callUri) {
         ContentResolver resolver = getContentResolver();
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 82d5c3f..04934c7 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -27,6 +27,7 @@
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -38,8 +39,11 @@
 import android.speech.RecognizerIntent;
 import android.telephony.TelephonyManager;
 import android.text.Editable;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.style.ImageSpan;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -507,7 +511,19 @@
         mVoiceSearchButton.setOnClickListener(this);
         mSearchView = (EditText) findViewById(R.id.search_view);
         mSearchView.addTextChangedListener(mPhoneSearchQueryTextListener);
-        mSearchView.setHint(getString(R.string.dialer_hint_find_contact));
+
+        final String hintText = getString(R.string.dialer_hint_find_contact);
+
+        // The following code is used to insert an icon into a CharSequence (copied from
+        // SearchView)
+        final SpannableStringBuilder ssb = new SpannableStringBuilder("   "); // for the icon
+        ssb.append(hintText);
+        final Drawable searchIcon = getResources().getDrawable(R.drawable.ic_ab_search);
+        final int textSize = (int) (mSearchView.getTextSize() * 1.20);
+        searchIcon.setBounds(0, 0, textSize, textSize);
+        ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        mSearchView.setHint(ssb);
     }
 
     final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
@@ -852,7 +868,6 @@
         }
         // Go all the way back to the favorites fragment, regardless of how many times we
         // transitioned between search fragments
-        final BackStackEntry entry = getFragmentManager().getBackStackEntryAt(0);
         getFragmentManager().popBackStack(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);
         setNotInSearchUi();
     }
diff --git a/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java b/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
index 52435aa..8af3b82 100644
--- a/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
+++ b/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
@@ -150,7 +150,7 @@
                 DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_YEAR);
         dateView.setText(dateValue);
         // Set the duration
-        if (callType == Calls.MISSED_TYPE || callType == Calls.VOICEMAIL_TYPE) {
+        if (Calls.VOICEMAIL_TYPE == callType || CallTypeHelper.isMissedCallType(callType)) {
             durationView.setVisibility(View.GONE);
         } else {
             durationView.setVisibility(View.VISIBLE);
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 9392410..e4fd0d8 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -388,7 +388,16 @@
         NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso);
         ContactInfo existingInfo = mContactInfoCache.getPossiblyExpired(numberCountryIso);
 
-        boolean updated = !info.equals(existingInfo);
+        final boolean isRemoteSource = info.sourceType != 0;
+
+        // Don't force redraw if existing info in the cache is equal to {@link ContactInfo#EMPTY}
+        // to avoid updating the data set for every new row that is scrolled into view.
+        // see (https://googleplex-android-review.git.corp.google.com/#/c/166680/)
+
+        // Exception: Photo uris for contacts from remote sources are not cached in the call log
+        // cache, so we have to force a redraw for these contacts regardless.
+        boolean updated = (existingInfo != ContactInfo.EMPTY || isRemoteSource) &&
+                !info.equals(existingInfo);
 
         // Store the data in the cache so that the UI thread can use to display it. Store it
         // even if it has not changed so that it is marked as not expired.
diff --git a/src/com/android/dialer/calllog/CallLogGroupBuilder.java b/src/com/android/dialer/calllog/CallLogGroupBuilder.java
index 1e4684e..213f1e7 100644
--- a/src/com/android/dialer/calllog/CallLogGroupBuilder.java
+++ b/src/com/android/dialer/calllog/CallLogGroupBuilder.java
@@ -78,8 +78,7 @@
                 shouldGroup = false;
             } else {
                 // Incoming, outgoing, and missed calls group together.
-                shouldGroup = (callType == Calls.INCOMING_TYPE || callType == Calls.OUTGOING_TYPE ||
-                        callType == Calls.MISSED_TYPE);
+                shouldGroup = callType != Calls.VOICEMAIL_TYPE;
             }
 
             if (shouldGroup) {
diff --git a/src/com/android/dialer/calllog/CallTypeHelper.java b/src/com/android/dialer/calllog/CallTypeHelper.java
index 0f9b737..1c4f44f 100644
--- a/src/com/android/dialer/calllog/CallTypeHelper.java
+++ b/src/com/android/dialer/calllog/CallTypeHelper.java
@@ -64,7 +64,7 @@
                 return mVoicemailName;
 
             default:
-                throw new IllegalArgumentException("invalid call type: " + callType);
+                return mMissedName;
         }
     }
 
@@ -86,7 +86,15 @@
                 return mNewVoicemailColor;
 
             default:
-                throw new IllegalArgumentException("invalid call type: " + callType);
+                // Don't highlight calls of unknown types. They are treated as missed calls by
+                // the rest of the UI, but since they will never be marked as read by
+                // {@link CallLogQueryHandler}, just don't ever highlight them anyway.
+                return null;
         }
     }
+
+    public static boolean isMissedCallType(int callType) {
+        return (callType != Calls.INCOMING_TYPE && callType != Calls.OUTGOING_TYPE &&
+                callType != Calls.VOICEMAIL_TYPE);
+    }
 }
diff --git a/src/com/android/dialer/calllog/CallTypeIconsView.java b/src/com/android/dialer/calllog/CallTypeIconsView.java
index e835128..a65f2c2 100644
--- a/src/com/android/dialer/calllog/CallTypeIconsView.java
+++ b/src/com/android/dialer/calllog/CallTypeIconsView.java
@@ -86,7 +86,11 @@
             case Calls.VOICEMAIL_TYPE:
                 return mResources.voicemail;
             default:
-                throw new IllegalArgumentException("invalid call type: " + callType);
+                // It is possible for users to end up with calls with unknown call types in their
+                // call history, possibly due to 3rd party call log implementations (e.g. to
+                // distinguish between rejected and missed calls). Instead of crashing, just
+                // assume that all unknown call types are missed calls.
+                return mResources.missed;
         }
     }
 
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index 9ebf112..00b8281 100644
--- a/src/com/android/dialer/dialpad/DialpadFragment.java
+++ b/src/com/android/dialer/dialpad/DialpadFragment.java
@@ -206,6 +206,8 @@
     private ToneGenerator mToneGenerator;
     private final Object mToneGeneratorLock = new Object();
     private View mDialpad;
+    private View mSpacer;
+
     /**
      * Set of dialpad keys that are currently being pressed
      */
@@ -428,6 +430,18 @@
             mDelete.setOnLongClickListener(this);
         }
 
+        mSpacer = fragmentView.findViewById(R.id.spacer);
+        mSpacer.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                if (isDigitsEmpty()) {
+                    hideAndClearDialpad();
+                    return true;
+                }
+                return false;
+            }
+        });
+
         mDialpad = fragmentView.findViewById(R.id.dialpad);  // This is null in landscape mode.
 
         // In landscape we put the keyboard in phone mode.
diff --git a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
index a13ecd8..3690796 100644
--- a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
+++ b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
@@ -162,6 +162,8 @@
     }
 
     private void releaseResources(Cursor cursor) {
-        cursor.close();
+        if (cursor != null) {
+            cursor.close();
+        }
     }
 }
diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java
index 73703a0..34666ee 100644
--- a/src/com/android/dialer/list/PhoneFavoriteFragment.java
+++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java
@@ -27,6 +27,7 @@
 import android.content.CursorLoader;
 import android.content.Loader;
 import android.content.SharedPreferences;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -50,6 +51,7 @@
 import com.android.contacts.common.ContactTileLoaderFactory;
 import com.android.contacts.common.GeoUtil;
 import com.android.contacts.common.list.ContactEntry;
+import com.android.contacts.common.list.ContactListItemView;
 import com.android.contacts.common.list.ContactTileView;
 import com.android.dialer.DialtactsActivity;
 import com.android.dialer.R;
@@ -290,21 +292,12 @@
 
         mShowAllContactsInEmptyViewButton = mParentView.findViewById(
                 R.id.show_all_contact_button_in_nofav);
-        mShowAllContactsInEmptyViewButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                showAllContacts();
-            }
-        });
+        prepareAllContactsButton(mShowAllContactsInEmptyViewButton);
 
         mShowAllContactsButton = inflater.inflate(R.layout.show_all_contact_button, mListView,
                 false);
-        mShowAllContactsButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                showAllContacts();
-            }
-        });
+
+        prepareAllContactsButton(mShowAllContactsButton);
 
         mContactTileFrame = mParentView.findViewById(R.id.contact_tile_frame);
 
@@ -638,4 +631,33 @@
                 .apply();
         fetchCalls();
     }
+
+    /**
+     * Returns a view that is laid out and styled to look like a regular contact, with the correct
+     * click behavior (to launch the all contacts activity when it is clicked).
+     */
+    private View prepareAllContactsButton(View v) {
+        final ContactListItemView view = (ContactListItemView) v;
+        view.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                showAllContacts();
+            }
+        });
+
+        view.setPhotoPosition(ContactListItemView.PhotoPosition.LEFT);
+        final Resources resources = getResources();
+        view.setBackgroundResource(R.drawable.contact_list_item_background);
+
+        view.setPaddingRelative(
+                resources.getDimensionPixelSize(R.dimen.favorites_row_start_padding),
+                resources.getDimensionPixelSize(R.dimen.favorites_row_end_padding),
+                resources.getDimensionPixelSize(R.dimen.favorites_row_top_padding),
+                resources.getDimensionPixelSize(R.dimen.favorites_row_bottom_padding));
+
+        view.setDisplayName(resources.getString(R.string.show_all_contacts_button_text));
+        view.setDrawableResource(R.drawable.list_item_avatar_bg,
+                R.drawable.ic_menu_all_contacts_dk);
+        return view;
+    }
 }