Merge "Open search ui on touch, and handle related scenarios."
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index b36101e..ff6b7ba 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -21,6 +21,7 @@
     android:layout_height="wrap_content"
     android:id="@+id/call_log_list_item"
     android:orientation="vertical"
+    android:clipChildren="false"
 >
     <!-- Day group heading. Used to show a "today", "yesterday", "last week" or "other" heading
          above a group of call log entries. -->
diff --git a/res/layout/call_log_list_item_actions.xml b/res/layout/call_log_list_item_actions.xml
index eb4aea2..d4e98d0 100644
--- a/res/layout/call_log_list_item_actions.xml
+++ b/res/layout/call_log_list_item_actions.xml
@@ -42,7 +42,8 @@
             android:textSize="@dimen/call_log_secondary_text_size"
             android:nextFocusLeft="@+id/primary_action_view"
             android:nextFocusRight="@+id/voicemail_action"
-            android:focusable="true"/>
+            android:focusable="true"
+            android:singleLine="true"/>
         <TextView
             android:id="@+id/voicemail_action"
             android:background="@drawable/action_button_background"
@@ -57,7 +58,8 @@
             android:textSize="@dimen/call_log_secondary_text_size"
             android:nextFocusLeft="@+id/call_back_action"
             android:nextFocusRight="@+id/delete_action"
-            android:focusable="true"/>
+            android:focusable="true"
+            android:singleLine="true"/>
         <TextView
             android:id="@+id/delete_action"
             android:background="@drawable/action_button_background"
@@ -71,7 +73,24 @@
             android:textColor="@color/call_log_action_delete_text"
             android:textSize="@dimen/call_log_secondary_text_size"
             android:nextFocusLeft="@+id/voicemail_action"
+            android:nextFocusRight="@+id/details_action"
+            android:focusable="true"
+            android:singleLine="true"/>
+        <TextView
+            android:id="@+id/details_action"
+            android:background="@drawable/action_button_background"
+            android:fontFamily="sans-serif-medium"
+            android:gravity="center"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:paddingLeft="@dimen/call_log_action_horizontal_padding"
+            android:paddingRight="@dimen/call_log_action_horizontal_padding"
+            android:text="@string/call_log_action_details"
+            android:textColor="?attr/call_log_secondary_text_color"
+            android:textSize="@dimen/call_log_secondary_text_size"
+            android:nextFocusLeft="@+id/delete_action"
             android:nextFocusRight="@+id/primary_action_view"
-            android:focusable="true"/>
+            android:focusable="true"
+            android:singleLine="true"/>
     </LinearLayout>
 </FrameLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4215f53..04c951b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -429,13 +429,6 @@
     -->
     <string name="description_contact_details">Contact details for <xliff:g id="nameOrNumber">%1$s</xliff:g></string>
 
-    <!-- String describing the button to access call details in the call log.
-
-        Note: AccessibilityServices use this attribute to announce what the view represents.
-              This is especially valuable for views without textual representation like ImageView.
-    -->
-    <string name="description_call_details">Call details</string>
-
     <!-- String indicating a call log entry has an associated voicemail.
 
     Note: AccessibilityServices use this attribute to announce what the view represents.
@@ -684,6 +677,12 @@
          [CHAR LIMIT=30] -->
     <string name="call_log_action_voicemail">LISTEN</string>
 
+    <!-- Button text for the "DETAILS" button displayed underneath an entry in the call log.
+         Tapping navigates the user to the call details screen where the user can view details for
+         the call log entry.
+         [CHAR LIMIT=30] -->
+    <string name="call_log_action_details">DETAILS</string>
+
     <!-- String describing an incoming missed call entry in the call log.
          Note: AccessibilityServices uses this attribute to announce what the view represents.
          [CHAR LIMIT=NONE] -->
@@ -718,6 +717,12 @@
          [CHAR LIMIT=NONE] -->
     <string name="description_delete_action">Delete call log entry for <xliff:g id="nameOrNumber" example="John Smith">%1$s</xliff:g></string>
 
+    <!-- String describing the "details" action for an entry in the call log.  The details action
+         displays the call details screen for an entry in the call log.  This shows the calls to
+         and from the specified number associated with the call log entry.
+         [CHAR LIMIT=NONE] -->
+    <string name="description_details_action">Call details for <xliff:g id="nameOrNumber" example="John Smith">%1$s</xliff:g></string>
+
     <!-- Toast message which appears when a call log entry is deleted.
          [CHAR LIMIT=NONE] -->
     <string name="toast_entry_removed">Call log entry deleted.</string>
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index c4389ad..e1c0acf 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -641,7 +641,7 @@
         views.callType = callType;
         views.voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
         // Stash away the Ids of the calls so that we can support deleting a row in the call log.
-        views.callIds = getCallIds(c, rowId, count);
+        views.callIds = getCallIds(c, count);
 
         final ContactInfo cachedContactInfo = getContactInfoFromCallLog(c);
 
@@ -857,7 +857,8 @@
             // block and block further attempts to set focus.
             boolean focused = views.callBackButtonView.requestAccessibilityFocus() ||
                     views.voicemailButtonView.requestAccessibilityFocus() ||
-                    views.deleteButtonView.requestAccessibilityFocus();
+                    views.deleteButtonView.requestAccessibilityFocus() ||
+                    views.detailsButtonView.requestAccessibilityFocus();
         } else {
             // When recycling a view, it is possible the actionsView ViewStub was previously
             // inflated so we should hide it in this case.
@@ -894,10 +895,14 @@
             views.voicemailButtonView = (TextView)views.actionsView.findViewById(R.id.voicemail_action);
         }
 
-        if ( views.deleteButtonView == null) {
+        if (views.deleteButtonView == null) {
             views.deleteButtonView = (TextView)views.actionsView.findViewById(R.id.delete_action);
         }
 
+        if (views.detailsButtonView == null) {
+            views.detailsButtonView = (TextView)views.actionsView.findViewById(R.id.details_action);
+        }
+
         bindActionButtons(views);
     }
 
@@ -927,9 +932,18 @@
                     IntentProvider.getPlayVoicemailIntentProvider(
                             views.rowId, views.voicemailUri));
             views.voicemailButtonView.setVisibility(View.VISIBLE);
+
+            views.detailsButtonView.setVisibility(View.GONE);
         } else {
             views.voicemailButtonView.setTag(null);
             views.voicemailButtonView.setVisibility(View.GONE);
+
+            views.detailsButtonView.setOnClickListener(mActionListener);
+            views.detailsButtonView.setTag(
+                    IntentProvider.getCallDetailIntentProvider(
+                            views.rowId, views.callIds, null)
+            );
+
         }
 
         views.deleteButtonView.setOnClickListener(this.mDeleteListener);
@@ -1268,11 +1282,10 @@
      * Retrieves the call Ids represented by the current call log row.
      *
      * @param cursor Call log cursor to retrieve call Ids from.
-     * @param id Id of the first call of the grouping.
      * @param groupSize Number of calls associated with the current call log row.
      * @return Array of call Ids.
      */
-    private long[] getCallIds(final Cursor cursor, final long id, final int groupSize) {
+    private long[] getCallIds(final Cursor cursor, final int groupSize) {
         // We want to restore the position in the cursor at the end.
         int startingPosition = cursor.getPosition();
         long[] ids = new long[groupSize];
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index 976726d..baeb382 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -82,6 +82,9 @@
 
         views.deleteButtonView.setContentDescription(
                 mResources.getString(R.string.description_delete_action, views.nameOrNumber));
+
+        views.detailsButtonView.setContentDescription(
+                mResources.getString(R.string.description_details_action, views.nameOrNumber));
     }
 
     /**
diff --git a/src/com/android/dialer/calllog/CallLogListItemViews.java b/src/com/android/dialer/calllog/CallLogListItemViews.java
index 648362e..474b478 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViews.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViews.java
@@ -48,6 +48,8 @@
     public TextView deleteButtonView;
     /** The "voicemail" action button - assigned only when the action section is expanded. */
     public TextView voicemailButtonView;
+    /** The "details" action button - assigned only when the action section is expanded. */
+    public TextView detailsButtonView;
 
     /**
      * The row Id for the first call associated with the call log entry.  Used as a key for the
@@ -122,6 +124,7 @@
         views.callBackButtonView = new TextView(context);
         views.deleteButtonView = new TextView(context);
         views.voicemailButtonView = new TextView(context);
+        views.detailsButtonView = new TextView(context);
         views.actionsView = new View(context);
         return views;
     }
diff --git a/src/com/android/dialer/calllog/IntentProvider.java b/src/com/android/dialer/calllog/IntentProvider.java
index da0c69d..96020be 100644
--- a/src/com/android/dialer/calllog/IntentProvider.java
+++ b/src/com/android/dialer/calllog/IntentProvider.java
@@ -65,39 +65,29 @@
         };
     }
 
+    /**
+     * Retrieves the call details intent provider for an entry in the call log.
+     *
+     * @param id The call ID of the first call in the call group.
+     * @param extraIds The call ID of the other calls grouped together with the call.
+     * @param voicemailUri If call log entry is for a voicemail, the voicemail URI.
+     * @return The call details intent provider.
+     */
     public static IntentProvider getCallDetailIntentProvider(
-            final Cursor cursor, final int position, final long id, final int groupSize) {
+            final long id, final long[] extraIds, final String voicemailUri) {
         return new IntentProvider() {
             @Override
             public Intent getIntent(Context context) {
-                if (cursor.isClosed()) {
-                    // There are reported instances where the cursor is already closed.
-                    // b/10937133
-                    // When causes a crash when it's accessed here.
-                    Log.e(TAG, "getCallDetailIntentProvider() cursor is already closed.");
-                    return null;
-                }
-
-                cursor.moveToPosition(position);
-
                 Intent intent = new Intent(context, CallDetailActivity.class);
                 // Check if the first item is a voicemail.
-                String voicemailUri = cursor.getString(CallLogQuery.VOICEMAIL_URI);
                 if (voicemailUri != null) {
                     intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI,
                             Uri.parse(voicemailUri));
                 }
                 intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK, false);
 
-                if (groupSize > 1) {
-                    // We want to restore the position in the cursor at the end.
-                    long[] ids = new long[groupSize];
-                    // Copy the ids of the rows in the group.
-                    for (int index = 0; index < groupSize; ++index) {
-                        ids[index] = cursor.getLong(CallLogQuery.ID);
-                        cursor.moveToNext();
-                    }
-                    intent.putExtra(CallDetailActivity.EXTRA_CALL_LOG_IDS, ids);
+                if (extraIds != null && extraIds.length > 0) {
+                    intent.putExtra(CallDetailActivity.EXTRA_CALL_LOG_IDS, extraIds);
                 } else {
                     // If there is a single item, use the direct URI for it.
                     intent.setData(ContentUris.withAppendedId(