Merge "FIX: Must show organization even if "position" is empty; FIX: Split nicknames into separate list (was combined with organizations and resulted in wrong sort order). Bug: 2421235"
diff --git a/res/layout-finger/contacts_list_item.xml b/res/layout-finger/contacts_list_item.xml
index 7520334..67de04d 100644
--- a/res/layout-finger/contacts_list_item.xml
+++ b/res/layout-finger/contacts_list_item.xml
@@ -33,50 +33,10 @@
         android:paddingLeft="14dip"
     >
 
-        <LinearLayout android:id="@+id/right_side"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:orientation="horizontal"
-            android:layout_marginLeft="11dip"
-            android:layout_alignParentRight="true">
-
-            <ImageView android:id="@+id/presence"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginLeft="5dip"
-                android:layout_marginRight="5dip"
-                android:padding="7dip"
-                android:layout_gravity="center_vertical"
-                android:scaleType="centerInside"
-            />
-
-            <LinearLayout android:id="@+id/call_view"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:orientation="horizontal">
-
-                <View android:id="@+id/divider"
-                    android:layout_width="1px"
-                    android:layout_height="match_parent"
-                    android:layout_marginTop="5dip"
-                    android:layout_marginBottom="5dip"
-                    android:background="@drawable/divider_vertical_dark"
-                />
-
-                <com.android.contacts.ui.widget.DontPressWithParentImageView android:id="@+id/call_button"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:paddingLeft="14dip"
-                    android:paddingRight="14dip"
-                    android:layout_centerVertical="true"
-                    android:gravity="center"
-                    android:src="@android:drawable/sym_action_call"
-                    android:background="@drawable/call_background"
-                />
-
-            </LinearLayout>
-
-        </LinearLayout>
+        <include
+            android:id="@+id/right_side"
+            layout="@layout/contacts_list_item_presence_and_action"
+        />
 
         <TextView android:id="@+id/label"
             android:layout_width="wrap_content"
@@ -97,8 +57,8 @@
             android:layout_height="wrap_content"
             android:layout_marginLeft="5dip"
             android:layout_toRightOf="@id/label"
-            android:layout_alignBaseline="@id/label"
             android:layout_toLeftOf="@id/right_side"
+            android:layout_alignBaseline="@id/label"
             android:layout_alignWithParentIfMissing="true"
 
             android:singleLine="true"
@@ -109,12 +69,12 @@
         <TextView android:id="@+id/name"
             android:layout_width="0dip"
             android:layout_height="0dip"
+            android:layout_alignParentLeft="true"
+            android:layout_marginBottom="1dip"
+            android:layout_toLeftOf="@id/right_side"
+            android:layout_alignParentTop="true"
             android:layout_above="@id/label"
             android:layout_alignWithParentIfMissing="true"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"
-            android:layout_toLeftOf="@id/right_side"
-            android:layout_marginBottom="1dip"
 
             android:singleLine="true"
             android:ellipsize="marquee"
diff --git a/res/layout-finger/contacts_list_item_photo.xml b/res/layout-finger/contacts_list_item_photo.xml
index 9dfeb80..cad1bb9 100644
--- a/res/layout-finger/contacts_list_item_photo.xml
+++ b/res/layout-finger/contacts_list_item_photo.xml
@@ -33,49 +33,10 @@
         android:paddingLeft="4dip"
     >
 
-        <LinearLayout android:id="@+id/right_side"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:orientation="horizontal"
-            android:layout_marginLeft="11dip"
-            android:layout_alignParentRight="true">
-
-            <ImageView android:id="@+id/presence"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginLeft="5dip"
-                android:layout_marginRight="5dip"
-                android:padding="7dip"
-                android:layout_gravity="center_vertical"
-                android:scaleType="centerInside"
-            />
-
-            <LinearLayout android:id="@+id/call_view"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:orientation="horizontal">
-
-                <View android:id="@+id/divider"
-                    android:layout_width="1px"
-                    android:layout_height="match_parent"
-                    android:layout_marginTop="5dip"
-                    android:layout_marginBottom="5dip"
-                    android:background="@drawable/divider_vertical_dark"
-                />
-
-                <com.android.contacts.ui.widget.DontPressWithParentImageView android:id="@+id/call_button"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:paddingLeft="14dip"
-                    android:paddingRight="14dip"
-                    android:layout_centerVertical="true"
-                    android:gravity="center"
-                    android:src="@android:drawable/sym_action_call"
-                    android:background="@drawable/call_background"
-                />
-
-            </LinearLayout>
-        </LinearLayout>
+        <include
+            android:id="@+id/right_side"
+            layout="@layout/contacts_list_item_presence_and_action"
+        />
 
         <android.widget.QuickContactBadge android:id="@+id/photo"
             android:layout_alignParentLeft="true"
@@ -134,7 +95,6 @@
             android:gravity="center_vertical|left"
             android:textAppearance="?android:attr/textAppearanceLarge"
         />
-
     </RelativeLayout>
 
     <View android:id="@+id/list_divider"
diff --git a/res/layout-finger/contacts_list_item_photo_and_snippet.xml b/res/layout-finger/contacts_list_item_photo_and_snippet.xml
new file mode 100644
index 0000000..981b956
--- /dev/null
+++ b/res/layout-finger/contacts_list_item_photo_and_snippet.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2009, 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.
+ */
+-->
+
+<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+>
+    <include
+        android:id="@+id/header"
+        layout="@layout/list_section"
+    />
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/listPreferredItemHeight"
+        android:paddingLeft="4dip"
+    >
+
+        <include
+            android:id="@+id/right_side"
+            layout="@layout/contacts_list_item_presence_and_action"
+        />
+
+        <android.widget.QuickContactBadge android:id="@+id/photo"
+            android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="8dip"
+            style="?android:attr/quickContactBadgeStyleWindowMedium"
+        />
+
+        <ImageView android:id="@+id/noQuickContactPhoto"
+            android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="8dip"
+            android:background="@null"
+            style="?android:attr/quickContactBadgeStyleWindowMedium"
+        />
+
+        <TextView android:id="@+id/label"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toRightOf="@id/photo"
+            android:layout_alignParentBottom="true"
+            android:layout_marginBottom="3dip"
+            android:layout_marginTop="-7dip"
+
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textStyle="bold"
+        />
+
+        <TextView android:id="@+id/data"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dip"
+            android:layout_toRightOf="@id/label"
+            android:layout_toLeftOf="@id/right_side"
+            android:layout_alignBaseline="@id/label"
+            android:layout_alignWithParentIfMissing="true"
+
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+        />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_toRightOf="@id/photo"
+            android:layout_toLeftOf="@id/right_side"
+            android:layout_above="@id/label"
+            android:layout_alignParentTop="true"
+            android:layout_alignWithParentIfMissing="true"
+            android:gravity="center_vertical|left"
+            >
+
+            <TextView android:id="@+id/name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentTop="true"
+
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+            />
+
+            <TextView android:id="@+id/snippet_label"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/name"
+                android:layout_alignWithParentIfMissing="true"
+                android:layout_marginTop="-5dip"
+                android:layout_marginBottom="3dip"
+
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+            />
+
+            <TextView android:id="@+id/snippet_data"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toRightOf="@id/snippet_label"
+                android:layout_alignBaseline="@id/snippet_label"
+                android:layout_marginLeft="5dip"
+                android:layout_alignWithParentIfMissing="true"
+
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textStyle="bold"
+            />
+
+        </RelativeLayout>
+    </RelativeLayout>
+
+    <View android:id="@+id/list_divider"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@*android:drawable/divider_horizontal_dark_opaque"
+    />
+</LinearLayout>
diff --git a/res/layout-finger/contacts_list_item_presence_and_action.xml b/res/layout-finger/contacts_list_item_presence_and_action.xml
new file mode 100644
index 0000000..80b275f
--- /dev/null
+++ b/res/layout-finger/contacts_list_item_presence_and_action.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 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.
+ */
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+    android:layout_marginLeft="11dip"
+    android:layout_alignParentRight="true">
+
+    <ImageView android:id="@+id/presence"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="5dip"
+        android:layout_marginRight="5dip"
+        android:padding="7dip"
+        android:layout_gravity="center_vertical"
+        android:scaleType="centerInside"
+    />
+
+    <LinearLayout android:id="@+id/call_view"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:orientation="horizontal">
+
+        <View android:id="@+id/divider"
+            android:layout_width="1px"
+            android:layout_height="match_parent"
+            android:layout_marginTop="5dip"
+            android:layout_marginBottom="5dip"
+            android:background="@drawable/divider_vertical_dark"
+        />
+
+        <view
+            class="com.android.contacts.ui.widget.DontPressWithParentImageView"
+            android:id="@+id/call_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:paddingLeft="14dip"
+            android:paddingRight="14dip"
+            android:layout_centerVertical="true"
+            android:gravity="center"
+            android:src="@android:drawable/sym_action_call"
+            android:background="@drawable/call_background"
+        />
+
+    </LinearLayout>
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d4b093a..a53edb7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1100,4 +1100,10 @@
     <!-- Button displayed underneath the list of filtered visible contacts -->
     <string name="search_for_all_contacts">Search for all contacts</string>
 
+    <!-- Data type: organization -->
+    <string name="organization">Company</string>
+
+    <!-- Data type: nickname -->
+    <string name="nickname">Nickname</string>
+
 </resources>
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 9dae6c8..8ca53cb 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -44,6 +44,7 @@
 import android.content.res.Resources;
 import android.database.CharArrayBuffer;
 import android.database.Cursor;
+import android.database.DatabaseUtils;
 import android.database.MatrixCursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -71,7 +72,10 @@
 import android.provider.ContactsContract.Intents;
 import android.provider.ContactsContract.Presence;
 import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.SearchSnippetColumns;
 import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Nickname;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
@@ -295,8 +299,24 @@
         Contacts.CONTACT_PRESENCE,          // 6
         Contacts.PHOTO_ID,                  // 7
         Contacts.LOOKUP_KEY,                // 8
-        // email lookup doesn't included HAS_PHONE_NUMBER OR LOOKUP_KEY in projection
+        // email lookup doesn't included HAS_PHONE_NUMBER in projection
     };
+
+    static final String[] CONTACTS_SUMMARY_FILTER_PROJECTION = new String[] {
+        Contacts._ID,                       // 0
+        Contacts.DISPLAY_NAME_PRIMARY,      // 1
+        Contacts.DISPLAY_NAME_ALTERNATIVE,  // 2
+        Contacts.SORT_KEY_PRIMARY,          // 3
+        Contacts.STARRED,                   // 4
+        Contacts.TIMES_CONTACTED,           // 5
+        Contacts.CONTACT_PRESENCE,          // 6
+        Contacts.PHOTO_ID,                  // 7
+        Contacts.LOOKUP_KEY,                // 8
+        Contacts.HAS_PHONE_NUMBER,          // 9
+        SearchSnippetColumns.SNIPPET_MIMETYPE, // 10
+        SearchSnippetColumns.SNIPPET_DATA,     // 11
+    };
+
     static final String[] LEGACY_PEOPLE_PROJECTION = new String[] {
         People._ID,                         // 0
         People.DISPLAY_NAME,                // 1
@@ -316,6 +336,8 @@
     static final int SUMMARY_PHOTO_ID_COLUMN_INDEX = 7;
     static final int SUMMARY_LOOKUP_KEY_COLUMN_INDEX = 8;
     static final int SUMMARY_HAS_PHONE_COLUMN_INDEX = 9;
+    static final int SUMMARY_SNIPPET_MIMETYPE_COLUMN_INDEX = 10;
+    static final int SUMMARY_SNIPPET_DATA_COLUMN_INDEX = 11;
 
     static final String[] PHONES_PROJECTION = new String[] {
         Phone._ID, //0
@@ -408,6 +430,8 @@
     private boolean mSearchMode;
     private boolean mShowNumberOfContacts;
 
+    private boolean mShowSearchSnippets;
+
     private String mInitialFilter;
 
     private static final String CLAUSE_ONLY_VISIBLE = Contacts.IN_VISIBLE_GROUP + "=1";
@@ -526,6 +550,7 @@
         // context for the search queries.
         if (UI.FILTER_CONTACTS_ACTION.equals(action)) {
             mSearchMode = true;
+            mShowSearchSnippets = true;
             Bundle extras = intent.getExtras();
             if (extras != null) {
                 mInitialFilter = extras.getString(UI.FILTER_TEXT_EXTRA_KEY);
@@ -656,6 +681,7 @@
             } else {
                 // Otherwise handle the more normal search case
                 mMode = MODE_QUERY;
+                mShowSearchSnippets = true;
                 mInitialFilter = getIntent().getStringExtra(SearchManager.QUERY);
             }
         } else if (ACTION_SEARCH_FOR_SHORTCUT.equals(action)) {
@@ -1980,14 +2006,18 @@
             case MODE_STREQUENT:
             case MODE_FREQUENT:
             case MODE_STARRED:
-            case MODE_QUERY:
-            case MODE_QUERY_PICK:
             case MODE_DEFAULT:
             case MODE_INSERT_OR_EDIT_CONTACT:
             case MODE_GROUP:
             case MODE_PICK_CONTACT:
             case MODE_PICK_OR_CREATE_CONTACT: {
-                return CONTACTS_SUMMARY_PROJECTION;
+                return mSearchMode
+                        ? CONTACTS_SUMMARY_FILTER_PROJECTION
+                        : CONTACTS_SUMMARY_PROJECTION;
+            }
+            case MODE_QUERY:
+            case MODE_QUERY_PICK: {
+                return CONTACTS_SUMMARY_FILTER_PROJECTION;
             }
             case MODE_LEGACY_PICK_PERSON:
             case MODE_LEGACY_PICK_OR_CREATE_PERSON: {
@@ -2065,11 +2095,17 @@
     }
 
     private Uri getContactFilterUri(String filter) {
+        Uri baseUri;
         if (!TextUtils.isEmpty(filter)) {
-            return buildSectionIndexerUri(
-                    Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(filter)));
+            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(filter));
         } else {
-            return CONTACTS_CONTENT_URI_WITH_LETTER_COUNTS;
+            baseUri = Contacts.CONTENT_URI;
+        }
+
+        if (mAdapter.getDisplaySectionHeadersEnabled()) {
+            return buildSectionIndexerUri(baseUri);
+        } else {
+            return baseUri;
         }
     }
 
@@ -2443,7 +2479,6 @@
                     cursor = activity.getShowAllContactsLabelCursor(CONTACTS_SUMMARY_PROJECTION);
                 }
 
-//                activity.setTextFilter(null);
                 activity.mAdapter.changeCursor(cursor);
 
                 // Now that the cursor is populated again, it's possible to restore the list state
@@ -2467,6 +2502,8 @@
         public CharArrayBuffer nameBuffer = new CharArrayBuffer(128);
         public TextView labelView;
         public TextView dataView;
+        public TextView snippetLabelView;
+        public TextView snippetDataView;
         public CharArrayBuffer dataBuffer = new CharArrayBuffer(128);
         public ImageView presenceView;
         public QuickContactBadge photoView;
@@ -2531,7 +2568,11 @@
 
             if ((mMode & MODE_MASK_SHOW_PHOTOS) == MODE_MASK_SHOW_PHOTOS) {
                 mDisplayPhotos = true;
-                setViewResource(R.layout.contacts_list_item_photo);
+                if (mShowSearchSnippets) {
+                    setViewResource(R.layout.contacts_list_item_photo_and_snippet);
+                } else {
+                    setViewResource(R.layout.contacts_list_item_photo);
+                }
             }
         }
 
@@ -2757,6 +2798,9 @@
             }
             cache.nonQuickContactPhotoView = (ImageView) view.findViewById(R.id.noQuickContactPhoto);
             cache.textWithHighlighting = mHighlightingAnimation.createTextWithHighlighting();
+            cache.snippetLabelView = (TextView)view.findViewById(R.id.snippet_label);
+            cache.snippetDataView = (TextView)view.findViewById(R.id.snippet_data);
+
             view.setTag(cache);
             return view;
         }
@@ -2876,6 +2920,29 @@
                 presenceView.setVisibility(View.GONE);
             }
 
+            if (mShowSearchSnippets) {
+                boolean showSnippet = false;
+                String snippetMimeType = cursor.getString(SUMMARY_SNIPPET_MIMETYPE_COLUMN_INDEX);
+                String snippetValue = cursor.getString(SUMMARY_SNIPPET_DATA_COLUMN_INDEX);
+                if (!TextUtils.isEmpty(snippetValue)) {
+                    if (Email.CONTENT_ITEM_TYPE.equals(snippetMimeType)) {
+                        cache.snippetLabelView.setText(R.string.email);
+                        cache.snippetDataView.setText(snippetValue);
+                        showSnippet = true;
+                    } else if (Organization.CONTENT_ITEM_TYPE.equals(snippetMimeType)) {
+                        cache.snippetLabelView.setText(R.string.organization);
+                        cache.snippetDataView.setText(snippetValue);
+                        showSnippet = true;
+                    } else if (Nickname.CONTENT_ITEM_TYPE.equals(snippetMimeType)) {
+                        cache.snippetLabelView.setText(R.string.nickname);
+                        cache.snippetDataView.setText(snippetValue);
+                        showSnippet = true;
+                    }
+                }
+                cache.snippetLabelView.setVisibility(showSnippet ? View.VISIBLE : View.GONE);
+                cache.snippetDataView.setVisibility(showSnippet ? View.VISIBLE : View.GONE);
+            }
+
             if (!displayAdditionalData) {
                 cache.dataView.setVisibility(View.GONE);
                 cache.labelView.setVisibility(View.GONE);