Merge "Do not look up contact for calls to voicemail."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 219ff67..722fc46 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -409,26 +409,6 @@
             </intent-filter>
         </activity>
 
-        <!-- Flushes the QuickContact IntentCache -->
-        <receiver android:name=".quickcontact.PackageIntentReceiver">
-            <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_ADDED" />
-                <data android:scheme="package" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_REPLACED" />
-                <data android:scheme="package" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_REMOVED" />
-                <data android:scheme="package" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_CHANGED" />
-                <data android:scheme="package" />
-            </intent-filter>
-        </receiver>
-
         <activity-alias android:name="ContactShortcut"
             android:targetActivity=".activities.ContactSelectionActivity"
             android:label="@string/shortcutContact"
@@ -567,37 +547,6 @@
             android:theme="@android:style/Theme.Translucent">
         </activity>
 
-        <!-- LIVE FOLDERS -->
-        <activity
-            android:name=".ContactsLiveFolders$AllContacts"
-            android:label="@string/liveFolderAll"
-            android:icon="@mipmap/ic_launcher_folder_live_contacts">
-            <intent-filter>
-                <action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
-        <activity
-            android:name=".ContactsLiveFolders$StarredContacts"
-            android:label="@string/liveFolderFavorites"
-            android:icon="@mipmap/ic_launcher_folder_live_contacts_starred">
-            <intent-filter>
-                <action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
-        <activity
-            android:name=".ContactsLiveFolders$PhoneContacts"
-            android:label="@string/liveFolderPhone"
-            android:icon="@mipmap/ic_launcher_folder_live_contacts_phone">
-            <intent-filter>
-                <action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
         <!-- vCard related -->
         <activity android:name=".vcard.ImportVCardActivity"
             android:configChanges="orientation|screenSize|keyboardHidden"
diff --git a/res/layout/call_log_voicemail_status.xml b/res/layout/call_log_voicemail_status.xml
index 280dfd0..191c821 100644
--- a/res/layout/call_log_voicemail_status.xml
+++ b/res/layout/call_log_voicemail_status.xml
@@ -27,15 +27,9 @@
             android:layout_weight="1"
             android:paddingLeft="@dimen/call_log_outer_margin"
             android:paddingRight="@dimen/call_log_inner_margin"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="?attr/call_log_voicemail_status_text_color"
         />
-        <View
-            android:id="@+id/voicemail_status_divider"
-            android:layout_width="1px"
-            android:layout_height="@dimen/call_log_call_action_size"
-            android:layout_gravity="center_vertical"
-            android:background="@drawable/ic_divider_dashed_holo_dark"
-        />
         <TextView
             android:id="@+id/voicemail_status_action"
             android:layout_width="wrap_content"
@@ -43,7 +37,8 @@
             android:gravity="center_vertical"
             android:paddingLeft="@dimen/call_log_inner_margin"
             android:paddingRight="@dimen/call_log_outer_margin"
-            android:textColor="?attr/call_log_voicemail_status_text_color"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textColor="?attr/call_log_voicemail_status_action_text_color"
             android:background="?android:attr/selectableItemBackground"
             android:clickable="true"
         />
diff --git a/res/layout/contact_tile_frequent_phone.xml b/res/layout/contact_tile_frequent_phone.xml
index d3f64e4..1cee5c6 100644
--- a/res/layout/contact_tile_frequent_phone.xml
+++ b/res/layout/contact_tile_frequent_phone.xml
@@ -67,7 +67,7 @@
                 android:id="@+id/contact_tile_phone_number"
                 android:layout_width="0dip"
                 android:layout_height="wrap_content"
-                android:layout_weight="5"
+                android:layout_weight="?attr/list_item_data_width_weight"
                 android:textSize="14sp"
                 android:textColor="@color/dialtacts_secondary_text_color"
                 android:layout_marginLeft="8dip"
@@ -78,7 +78,7 @@
                 android:id="@+id/contact_tile_phone_type"
                 android:layout_width="0dip"
                 android:layout_height="wrap_content"
-                android:layout_weight="3"
+                android:layout_weight="?attr/list_item_label_width_weight"
                 android:textSize="12sp"
                 android:ellipsize="end"
                 android:singleLine="true"
diff --git a/res/mipmap-hdpi/ic_launcher_folder_live_contacts.png b/res/mipmap-hdpi/ic_launcher_folder_live_contacts.png
deleted file mode 100644
index 84babe2..0000000
--- a/res/mipmap-hdpi/ic_launcher_folder_live_contacts.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-hdpi/ic_launcher_folder_live_contacts_phone.png b/res/mipmap-hdpi/ic_launcher_folder_live_contacts_phone.png
deleted file mode 100644
index 004e849..0000000
--- a/res/mipmap-hdpi/ic_launcher_folder_live_contacts_phone.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-hdpi/ic_launcher_folder_live_contacts_starred.png b/res/mipmap-hdpi/ic_launcher_folder_live_contacts_starred.png
deleted file mode 100644
index 73b4fa5..0000000
--- a/res/mipmap-hdpi/ic_launcher_folder_live_contacts_starred.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_folder_live_contacts.png b/res/mipmap-mdpi/ic_launcher_folder_live_contacts.png
deleted file mode 100644
index d49cc7b..0000000
--- a/res/mipmap-mdpi/ic_launcher_folder_live_contacts.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_folder_live_contacts_phone.png b/res/mipmap-mdpi/ic_launcher_folder_live_contacts_phone.png
deleted file mode 100644
index 0127f84..0000000
--- a/res/mipmap-mdpi/ic_launcher_folder_live_contacts_phone.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_folder_live_contacts_starred.png b/res/mipmap-mdpi/ic_launcher_folder_live_contacts_starred.png
deleted file mode 100644
index 8d56b31..0000000
--- a/res/mipmap-mdpi/ic_launcher_folder_live_contacts_starred.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_folder_live_contacts.png b/res/mipmap-xhdpi/ic_launcher_folder_live_contacts.png
deleted file mode 100644
index 99bb9f8..0000000
--- a/res/mipmap-xhdpi/ic_launcher_folder_live_contacts.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_folder_live_contacts_phone.png b/res/mipmap-xhdpi/ic_launcher_folder_live_contacts_phone.png
deleted file mode 100644
index fd416b8..0000000
--- a/res/mipmap-xhdpi/ic_launcher_folder_live_contacts_phone.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_folder_live_contacts_starred.png b/res/mipmap-xhdpi/ic_launcher_folder_live_contacts_starred.png
deleted file mode 100644
index ff9e326..0000000
--- a/res/mipmap-xhdpi/ic_launcher_folder_live_contacts_starred.png
+++ /dev/null
Binary files differ
diff --git a/res/values-sw580dp/styles.xml b/res/values-sw580dp/styles.xml
index ee65159..3551378 100644
--- a/res/values-sw580dp/styles.xml
+++ b/res/values-sw580dp/styles.xml
@@ -41,8 +41,10 @@
         <item name="list_item_header_text_size">14sp</item>
         <item name="list_item_header_text_color">@color/people_app_theme_color</item>
         <item name="list_item_header_height">26dip</item>
-        <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
         <item name="list_item_header_underline_height">1dip</item>
+        <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+        <item name="list_item_data_width_weight">5</item>
+        <item name="list_item_label_width_weight">3</item>
         <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
         <item name="list_item_contacts_count_text_size">12sp</item>
         <item name="contact_browser_list_padding_left">0dip</item>
@@ -72,8 +74,10 @@
         <item name="list_item_header_text_size">14sp</item>
         <item name="list_item_header_text_color">@color/people_app_theme_color</item>
         <item name="list_item_header_height">24dip</item>
-        <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
         <item name="list_item_header_underline_height">1dip</item>
+        <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+        <item name="list_item_data_width_weight">5</item>
+        <item name="list_item_label_width_weight">3</item>
         <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
         <item name="list_item_contacts_count_text_size">12sp</item>
         <item name="contact_browser_list_padding_left">16dip</item>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index d79d373..b9a534c 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -100,6 +100,8 @@
         <attr name="list_item_contacts_count_text_color" format="color" />
         <attr name="list_item_text_indent" format="dimension" />
         <attr name="list_item_contacts_count_text_size" format="dimension" />
+        <attr name="list_item_data_width_weight" format="integer" />
+        <attr name="list_item_label_width_weight" format="integer" />
     </declare-styleable>
 
     <declare-styleable name="CallLog">
@@ -114,6 +116,7 @@
         <attr name="call_log_voicemail_status_height" format="dimension" />
         <attr name="call_log_voicemail_status_background_color" format="color" />
         <attr name="call_log_voicemail_status_text_color" format="color" />
+        <attr name="call_log_voicemail_status_action_text_color" format="color" />
     </declare-styleable>
 
     <declare-styleable name="Favorites">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ed88aaa..62dac75 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -379,9 +379,6 @@
 
          [CHAR LIMIT=NONE] -->
     <string name="recentCallsIconLabel">Call log</string>
-    <string name="liveFolderAll">All contacts</string>
-    <string name="liveFolderFavorites">Starred contacts</string>
-    <string name="liveFolderPhone">Contacts with phone numbers</string>
 
     <!-- Menu item used to send an SMS or MMS message to a phone number  -->
     <string name="menu_sendTextMessage">Send text message</string>
@@ -522,15 +519,6 @@
         \n<li>Touch the star next to the contact\'s name\n</li>"
     </string>
 
-    <!-- Live folder label for all contacts -->
-    <string name="liveFolder_all_label">All contacts</string>
-
-    <!-- Live folder label for only starred contacts -->
-    <string name="liveFolder_favorites_label">Starred</string>
-
-    <!-- Live folder label for all contacts with phone numbers -->
-    <string name="liveFolder_phones_label">Phones</string>
-
     <!-- Item label: jump to the in-call DTMF dialpad.
          (Part of a list of options shown in the dialer when another call
          is already in progress.) -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index dd62594..62a06f6 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -44,6 +44,8 @@
         <item name="list_item_header_height">24dip</item>
         <item name="list_item_header_underline_height">1dip</item>
         <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+        <item name="list_item_data_width_weight">5</item>
+        <item name="list_item_label_width_weight">3</item>
         <item name="contact_browser_list_padding_left">16dip</item>
         <item name="contact_browser_list_padding_right">0dip</item>
         <item name="contact_browser_background">@android:color/transparent</item>
@@ -55,10 +57,11 @@
         <item name="call_log_secondary_background_color">#333333</item>
         <item name="call_log_header_color">#33b5e5</item>
         <!-- VoicemailStatus -->
-        <item name="call_log_voicemail_status_height">40dip</item>
-        <item name="call_log_voicemail_status_background_color">#FFFFE0</item>
-        <item name="call_log_voicemail_status_text_color">#000000</item>
-        <!-- Favorites -->
+        <item name="call_log_voicemail_status_height">48dip</item>
+        <item name="call_log_voicemail_status_background_color">#262626</item>
+        <item name="call_log_voicemail_status_text_color">#888888</item>
+        <item name="call_log_voicemail_status_action_text_color">#33b5e5</item>
+            <!-- Favorites -->
         <item name="favorites_padding_bottom">?android:attr/actionBarSize</item>
     </style>
 
@@ -72,9 +75,10 @@
         <item name="call_log_secondary_background_color">#333333</item>
         <item name="call_log_header_color">#33b5e5</item>
         <!-- VoicemailStatus -->
-        <item name="call_log_voicemail_status_height">40dip</item>
-        <item name="call_log_voicemail_status_background_color">#FFFFE0</item>
-        <item name="call_log_voicemail_status_text_color">#000000</item>
+        <item name="call_log_voicemail_status_height">48dip</item>
+        <item name="call_log_voicemail_status_background_color">#262626</item>
+        <item name="call_log_voicemail_status_text_color">#888888</item>
+        <item name="call_log_voicemail_status_action_text_color">#33b5e5</item>
     </style>
 
     <style name="DetailActivityTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
@@ -146,6 +150,8 @@
         <item name="list_item_header_height">26dip</item>
         <item name="list_item_header_underline_height">1dip</item>
         <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+        <item name="list_item_data_width_weight">5</item>
+        <item name="list_item_label_width_weight">3</item>
         <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
         <item name="list_item_header_text_indent">8dip</item>
         <item name="contact_browser_list_padding_left">16dip</item>
diff --git a/src/com/android/contacts/ContactsLiveFolders.java b/src/com/android/contacts/ContactsLiveFolders.java
deleted file mode 100644
index 9cb7e72..0000000
--- a/src/com/android/contacts/ContactsLiveFolders.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
-import android.provider.LiveFolders;
-
-public class ContactsLiveFolders {
-    public static class StarredContacts extends Activity {
-        public static final Uri CONTENT_URI =
-                Uri.parse("content://contacts/live_folders/favorites");
-
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-
-            final Intent intent = getIntent();
-            final String action = intent.getAction();
-
-            if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
-                setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
-                        getString(R.string.liveFolder_favorites_label),
-                        R.mipmap.ic_launcher_folder_live_contacts_starred));
-            } else {
-                setResult(RESULT_CANCELED);
-            }
-
-            finish();
-        }
-    }
-
-    public static class PhoneContacts extends Activity {
-        public static final Uri CONTENT_URI =
-                Uri.parse("content://contacts/live_folders/people_with_phones");
-
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-
-            final Intent intent = getIntent();
-            final String action = intent.getAction();
-
-            if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
-                setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
-                        getString(R.string.liveFolder_phones_label),
-                        R.mipmap.ic_launcher_folder_live_contacts_phone));
-            } else {
-                setResult(RESULT_CANCELED);
-            }
-
-            finish();
-        }
-    }
-
-    public static class AllContacts extends Activity {
-        public static final Uri CONTENT_URI =
-                Uri.parse("content://contacts/live_folders/people");
-
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-
-            final Intent intent = getIntent();
-            final String action = intent.getAction();
-
-            if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
-                setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
-                        getString(R.string.liveFolder_all_label),
-                        R.mipmap.ic_launcher_folder_live_contacts));
-            } else {
-                setResult(RESULT_CANCELED);
-            }
-
-            finish();
-        }
-    }
-
-    private static Intent createLiveFolder(Context context, Uri uri, String name,
-            int icon) {
-
-        final Intent intent = new Intent();
-
-        intent.setData(uri);
-        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT,
-                new Intent(Intent.ACTION_VIEW, Contacts.CONTENT_URI));
-        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
-        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
-                Intent.ShortcutIconResource.fromContext(context, icon));
-        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);
-
-        return intent;
-    }
-}
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index f66bbd0..79f3499 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -75,7 +75,6 @@
     private View mStatusMessageView;
     private TextView mStatusMessageText;
     private TextView mStatusMessageAction;
-    private View mStatusMessageDivider;
     private KeyguardManager mKeyguardManager;
 
     @Override
@@ -144,7 +143,6 @@
         mStatusMessageView = view.findViewById(R.id.voicemail_status);
         mStatusMessageText = (TextView) view.findViewById(R.id.voicemail_status_message);
         mStatusMessageAction = (TextView) view.findViewById(R.id.voicemail_status_action);
-        mStatusMessageDivider = view.findViewById(R.id.voicemail_status_divider);
         return view;
     }
 
@@ -186,7 +184,6 @@
             }
             if (message.actionUri != null) {
                 mStatusMessageAction.setVisibility(View.VISIBLE);
-                mStatusMessageDivider.setVisibility(View.VISIBLE);
                 mStatusMessageAction.setOnClickListener(new View.OnClickListener() {
                     @Override
                     public void onClick(View v) {
@@ -196,7 +193,6 @@
                 });
             } else {
                 mStatusMessageAction.setVisibility(View.GONE);
-                mStatusMessageDivider.setVisibility(View.GONE);
             }
         }
     }
diff --git a/src/com/android/contacts/list/ContactListItemView.java b/src/com/android/contacts/list/ContactListItemView.java
index 49957dc..18c4d29 100644
--- a/src/com/android/contacts/list/ContactListItemView.java
+++ b/src/com/android/contacts/list/ContactListItemView.java
@@ -89,11 +89,14 @@
     private final int mTextIndent;
     private Drawable mActivatedBackgroundDrawable;
 
-    // In the future we may need to merge these local padding to View's mPaddingXXX
-    private final int mExtraPaddingTop;
-    private final int mExtraPaddingBottom;
-    private int mExtraPaddingLeft;
-    private int mExtraPaddingRight;
+    /**
+     * Used with {@link #mLabelView}, specifying the width ratio between label and data.
+     */
+    private final int mLabelViewWidthWeight;
+    /**
+     * Used with {@link #mDataView}, specifying the width ratio between label and data.
+     */
+    private final int mDataViewWidthWeight;
 
     // Will be used with adjustListItemSelectionBounds().
     private int mSelectionBoundsMarginLeft;
@@ -230,14 +233,7 @@
                 R.styleable.ContactListItemView_list_item_divider);
         mVerticalDividerMargin = a.getDimensionPixelOffset(
                 R.styleable.ContactListItemView_list_item_vertical_divider_margin, 0);
-        mExtraPaddingTop = a.getDimensionPixelOffset(
-                R.styleable.ContactListItemView_list_item_padding_top, 0);
-        mExtraPaddingBottom = a.getDimensionPixelOffset(
-                R.styleable.ContactListItemView_list_item_padding_bottom, 0);
-        mExtraPaddingLeft = a.getDimensionPixelOffset(
-                R.styleable.ContactListItemView_list_item_padding_left, 0);
-        mExtraPaddingRight = a.getDimensionPixelOffset(
-                R.styleable.ContactListItemView_list_item_padding_right, 0);
+
         mGapBetweenImageAndText = a.getDimensionPixelOffset(
                 R.styleable.ContactListItemView_list_item_gap_between_image_and_text, 0);
         mGapBetweenLabelAndData = a.getDimensionPixelOffset(
@@ -268,6 +264,20 @@
                 R.styleable.ContactListItemView_list_item_contacts_count_text_size, 12);
         mContactsCountTextColor = a.getColor(
                 R.styleable.ContactListItemView_list_item_contacts_count_text_color, Color.BLACK);
+        mDataViewWidthWeight = a.getInteger(
+                R.styleable.ContactListItemView_list_item_data_width_weight, 5);
+        mLabelViewWidthWeight = a.getInteger(
+                R.styleable.ContactListItemView_list_item_label_width_weight, 3);
+
+        setPadding(
+                a.getDimensionPixelOffset(
+                        R.styleable.ContactListItemView_list_item_padding_left, 0),
+                a.getDimensionPixelOffset(
+                        R.styleable.ContactListItemView_list_item_padding_top, 0),
+                a.getDimensionPixelOffset(
+                        R.styleable.ContactListItemView_list_item_padding_right, 0),
+                a.getDimensionPixelOffset(
+                        R.styleable.ContactListItemView_list_item_padding_bottom, 0));
 
         mPrefixHighligher = new PrefixHighlighter(
                 a.getColor(R.styleable.ContactListItemView_list_item_prefix_highlight_color,
@@ -306,9 +316,13 @@
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // We will match parent's width and wrap content vertically, but make sure
         // height is no less than listPreferredItemHeight.
-        int width = resolveSize(0, widthMeasureSpec);
-        int height = 0;
-        int preferredHeight = mPreferredHeight;
+        final int specWidth = resolveSize(0, widthMeasureSpec);
+        final int preferredHeight;
+        if (mHorizontalDividerVisible) {
+            preferredHeight = mPreferredHeight + mHorizontalDividerHeight;
+        } else {
+            preferredHeight = mPreferredHeight;
+        }
 
         mNameTextViewHeight = 0;
         mPhoneticNameTextViewHeight = 0;
@@ -318,51 +332,76 @@
         mSnippetTextViewHeight = 0;
         mStatusTextViewHeight = 0;
 
-        // TODO: measure(0, 0) is *wrong*. At least, we should use correct width for each TextView.
-        //
-        // Reason: TextView applies ellipsis effect in this phase, while measure(0, 0) have those
-        // views prepare the effect based on "unlimited width", which makes ellipsis setting
-        // meaningless. We should pass a widthMeasureSpec with appropriate width setting.
-        // See issue 5439903.
-
         ensurePhotoViewSize();
 
-        // Go over all visible text views and add their heights to get the total height
+        // Width each TextView is able to use.
+        final int effectiveWidth;
+        // All the other Views will honor the photo, so available width for them may be shrunk.
+        if (mPhotoViewWidth > 0 || mKeepHorizontalPaddingForPhotoView) {
+            effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight()
+                    - (mPhotoViewWidth + mGapBetweenImageAndText);
+        } else {
+            effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight();
+        }
+
+        // Go over all visible text views and measure actual width of each of them.
+        // Also calculate their heights to get the total height for this entire view.
+
         if (isVisible(mNameTextView)) {
-            mNameTextView.measure(0, 0);
+            mNameTextView.measure(
+                    MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
             mNameTextViewHeight = mNameTextView.getMeasuredHeight();
         }
 
         if (isVisible(mPhoneticNameTextView)) {
-            mPhoneticNameTextView.measure(0, 0);
+            mPhoneticNameTextView.measure(
+                    MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
             mPhoneticNameTextViewHeight = mPhoneticNameTextView.getMeasuredHeight();
         }
 
+        // If both data (phone number/email address) and label (type like "MOBILE") are quite long,
+        // we should ellipsize both using appropriate ratio.
+        final int dataWidth;
+        final int labelWidth;
         if (isVisible(mDataView)) {
-            mDataView.measure(0, 0);
+            if (isVisible(mLabelView)) {
+                final int totalWidth = effectiveWidth - mGapBetweenLabelAndData;
+                dataWidth = ((totalWidth * mDataViewWidthWeight)
+                        / (mDataViewWidthWeight + mLabelViewWidthWeight));
+                labelWidth = ((totalWidth * mLabelViewWidthWeight) /
+                        (mDataViewWidthWeight + mLabelViewWidthWeight));
+            } else {
+                dataWidth = effectiveWidth;
+                labelWidth = 0;
+            }
+        } else {
+            dataWidth = 0;
+            if (isVisible(mLabelView)) {
+                labelWidth = effectiveWidth;
+            } else {
+                labelWidth = 0;
+            }
+        }
+
+        if (isVisible(mDataView)) {
+            mDataView.measure(MeasureSpec.makeMeasureSpec(dataWidth, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
             mDataViewHeight = mDataView.getMeasuredHeight();
         }
 
         if (isVisible(mLabelView)) {
-            if (mPhotoPosition == PhotoPosition.LEFT) {
-                // Manually calculate the width now and see if ellipsis becomes effective or not.
-                // See also issue 5438757 and 5439903.
-                final int labelViewWidth = width - mExtraPaddingLeft - mExtraPaddingRight
-                        - (mPhotoViewWidth + mGapBetweenImageAndText)
-                        - mDataView.getMeasuredWidth()
-                        - mGapBetweenLabelAndData;
-                final int labelViewWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
-                        labelViewWidth, MeasureSpec.AT_MOST);
-                mLabelView.measure(labelViewWidthMeasureSpec, 0);
-            } else {
-                mLabelView.measure(0, 0);
-            }
+            mLabelView.measure(MeasureSpec.makeMeasureSpec(labelWidth, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
             mLabelTextViewHeight = mLabelView.getMeasuredHeight();
         }
         mLabelAndDataViewMaxHeight = Math.max(mLabelTextViewHeight, mDataViewHeight);
 
         if (isVisible(mSnippetView)) {
-            mSnippetView.measure(0, 0);
+            mSnippetView.measure(
+                    MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
             mSnippetTextViewHeight = mSnippetView.getMeasuredHeight();
         }
 
@@ -373,27 +412,36 @@
         }
 
         if (isVisible(mStatusView)) {
-            mStatusView.measure(0, 0);
-            mStatusTextViewHeight = Math.max(mStatusTextViewHeight,
-                    mStatusView.getMeasuredHeight());
+            // Presence and status are in a same row, so status will be affected by icon size.
+            final int statusWidth;
+            if (isVisible(mPresenceIcon)) {
+                statusWidth = (effectiveWidth - mPresenceIcon.getMeasuredWidth()
+                        - mPresenceIconMargin);
+            } else {
+                statusWidth = effectiveWidth;
+            }
+            mStatusView.measure(MeasureSpec.makeMeasureSpec(statusWidth, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+            mStatusTextViewHeight =
+                    Math.max(mStatusTextViewHeight, mStatusView.getMeasuredHeight());
         }
 
-        // Calculate height including padding
-        height += mNameTextViewHeight + mPhoneticNameTextViewHeight + mLabelAndDataViewMaxHeight +
-                mSnippetTextViewHeight + mStatusTextViewHeight +
-                mExtraPaddingTop + mExtraPaddingBottom;
+        // Calculate height including padding.
+        int height = (mNameTextViewHeight + mPhoneticNameTextViewHeight +
+                mLabelAndDataViewMaxHeight +
+                mSnippetTextViewHeight + mStatusTextViewHeight);
 
         if (isVisible(mCallButton)) {
-            mCallButton.measure(0, 0);
+            mCallButton.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
         }
 
         // Make sure the height is at least as high as the photo
-        height = Math.max(height, mPhotoViewHeight + mExtraPaddingBottom + mExtraPaddingTop);
+        height = Math.max(height, mPhotoViewHeight + getPaddingBottom() + getPaddingTop());
 
         // Add horizontal divider height
         if (mHorizontalDividerVisible) {
             height += mHorizontalDividerHeight;
-            preferredHeight += mHorizontalDividerHeight;
         }
 
         // Make sure height is at least the preferred height
@@ -402,11 +450,11 @@
         // Add the height of the header if visible
         if (mHeaderVisible) {
             mHeaderTextView.measure(
-                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(specWidth, MeasureSpec.EXACTLY),
                     MeasureSpec.makeMeasureSpec(mHeaderBackgroundHeight, MeasureSpec.EXACTLY));
             if (mCountView != null) {
                 mCountView.measure(
-                        MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+                        MeasureSpec.makeMeasureSpec(specWidth, MeasureSpec.AT_MOST),
                         MeasureSpec.makeMeasureSpec(mHeaderBackgroundHeight, MeasureSpec.EXACTLY));
             }
             mHeaderBackgroundHeight = Math.max(mHeaderBackgroundHeight,
@@ -414,7 +462,7 @@
             height += (mHeaderBackgroundHeight + mHeaderUnderlineHeight);
         }
 
-        setMeasuredDimension(width, height);
+        setMeasuredDimension(specWidth, height);
     }
 
     @Override
@@ -425,8 +473,8 @@
         // Determine the vertical bounds by laying out the header first.
         int topBound = 0;
         int bottomBound = height;
-        int leftBound = mExtraPaddingLeft;
-        int rightBound = width - mExtraPaddingRight;
+        int leftBound = getPaddingLeft();
+        int rightBound = width - getPaddingRight();
 
         // Put the header in the top of the contact view (Text + underline view)
         if (mHeaderVisible) {
@@ -435,7 +483,7 @@
                     rightBound,
                     mHeaderBackgroundHeight);
             if (mCountView != null) {
-                mCountView.layout(width - mExtraPaddingRight - mCountView.getMeasuredWidth(),
+                mCountView.layout(rightBound - mCountView.getMeasuredWidth(),
                         0,
                         rightBound,
                         mHeaderBackgroundHeight);
@@ -463,10 +511,6 @@
             mActivatedBackgroundDrawable.setBounds(mBoundsWithoutHeader);
         }
 
-        // Set the top/bottom padding
-        topBound += mExtraPaddingTop;
-        bottomBound -= mExtraPaddingBottom;
-
         final View photoView = mQuickContact != null ? mQuickContact : mPhotoView;
         if (mPhotoPosition == PhotoPosition.LEFT) {
             // Photo is the left most view. All the other Views should on the right of the photo.
@@ -947,7 +991,6 @@
             mLabelView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
             if (mPhotoPosition == PhotoPosition.LEFT) {
                 mLabelView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mCountViewTextSize);
-                mLabelView.setEllipsize(TruncateAt.MIDDLE);
                 mLabelView.setAllCaps(true);
             } else {
                 mLabelView.setTypeface(mLabelView.getTypeface(), Typeface.BOLD);
@@ -1103,7 +1146,9 @@
     }
 
     private TruncateAt getTextEllipsis() {
-        return mActivatedStateSupported ? TruncateAt.START : TruncateAt.MARQUEE;
+        // Note: If we want to choose MARQUEE here, we may need to manually trigger TextView's
+        // startStopMarquee(), which is unfortunately *private*. See also issue 5465510.
+        return TruncateAt.MIDDLE;
     }
 
     public void showDisplayName(Cursor cursor, int nameColumnIndex, int alternativeNameColumnIndex,
@@ -1262,29 +1307,6 @@
     }
 
     /**
-     * Sets custom padding inside this object. Do not use this method without any strong reason.
-     *
-     * Detail: we cannot simply override {@link #setPadding(int, int, int, int)}. {@link View}
-     * does *not* know this view's local padding but has completely different ones.
-     * See View#mPaddingLeft and View#mPaddingRight. View also has View#mUserPaddingLeft, and
-     * View#mUserPaddingRight in addition to View#mPaddingLeft and View#mPaddingRight, to handle
-     * {@link View#setPadding(int, int, int, int)} correctly. If setPadding() is overridden to
-     * reset our {@link #mExtraPaddingLeft} and {@link #mExtraPaddingRight} carelessly, the whole
-     * View layout gets confused.
-     *
-     * To simplify our implementation, this method just modify the local two padding without
-     * confusing its parent.
-     *
-     * If we want to fix this multiple padding issue correctly, we should merge local padding
-     * in this class into View's ones. Also we should remove "list_item_padding_left" and
-     * "list_item_padding_right" attributes, using "android:paddingLeft" and "android:paddingRight".
-     */
-    public void setExtraPadding(int left, int right) {
-        mExtraPaddingLeft = left;
-        mExtraPaddingRight = right;
-    }
-
-    /**
      * Specifies left and right margin for selection bounds. See also
      * {@link #adjustListItemSelectionBounds(Rect)}.
      */
diff --git a/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java b/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
index 25a158b..f817b4c 100644
--- a/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
+++ b/src/com/android/contacts/list/PhoneFavoriteMergedAdapter.java
@@ -163,9 +163,8 @@
             final int localPosition = position - contactTileAdapterCount - 1;
             final ContactListItemView itemView = (ContactListItemView)
                     mContactEntryListAdapter.getView(localPosition, convertView, null);
-            // We cannot simply use setPadding() because of ContactListItemView's restriction.
-            // See comments for setExtraPaddingPadding().
-            itemView.setExtraPadding(mItemPaddingLeft, mItemPaddingRight);
+            itemView.setPadding(mItemPaddingLeft, itemView.getPaddingTop(),
+                    mItemPaddingRight, itemView.getPaddingBottom());
             itemView.setSelectionBoundsHorizontalMargin(mItemPaddingLeft, mItemPaddingRight);
             return itemView;
         }
diff --git a/src/com/android/contacts/quickcontact/PackageIntentReceiver.java b/src/com/android/contacts/quickcontact/PackageIntentReceiver.java
deleted file mode 100644
index 7af4005..0000000
--- a/src/com/android/contacts/quickcontact/PackageIntentReceiver.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.contacts.quickcontact;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Package intent receiver that flushes the {@link ResolveCache} so that Packages are rescanned next
- * time
- */
-public class PackageIntentReceiver extends BroadcastReceiver {
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        ResolveCache.flush();
-    }
-}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 0588c7d..2c62fe4 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -18,7 +18,6 @@
 
 import com.android.contacts.Collapser;
 import com.android.contacts.ContactPhotoManager;
-import com.android.contacts.ContactPresenceIconUtil;
 import com.android.contacts.R;
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.model.DataKind;
diff --git a/src/com/android/contacts/quickcontact/ResolveCache.java b/src/com/android/contacts/quickcontact/ResolveCache.java
index 08a6cf8..aae2ee7 100644
--- a/src/com/android/contacts/quickcontact/ResolveCache.java
+++ b/src/com/android/contacts/quickcontact/ResolveCache.java
@@ -19,6 +19,7 @@
 import com.android.contacts.util.PhoneCapabilityTester;
 import com.google.android.collect.Sets;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -65,16 +66,35 @@
      */
     public synchronized static ResolveCache getInstance(Context context) {
         if (sInstance == null) {
-            return sInstance = new ResolveCache(context.getApplicationContext());
+            final Context applicationContext = context.getApplicationContext();
+            sInstance = new ResolveCache(applicationContext);
+
+            // Register for package-changes so that we can flush our cache
+            final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+            filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+            filter.addDataScheme("package");
+            applicationContext.registerReceiver(sInstance.mPackageIntentReceiver, filter);
         }
         return sInstance;
     }
 
-    public synchronized static void flush() {
+    private synchronized static void flush() {
         sInstance = null;
     }
 
     /**
+     * Called anytime a package is installed, uninstalled etc, so that we can wipe our cache
+     */
+    private BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            flush();
+        }
+    };
+
+    /**
      * Cached entry holding the best {@link ResolveInfo} for a specific
      * MIME-type, along with a {@link SoftReference} to its icon.
      */