Merge "Use a "dash" for a phone number that we cannot geocode."
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index 7a84e6d..f595caa 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -181,7 +181,7 @@
         @Override
         public void onTabSelected(Tab tab, FragmentTransaction ft) {
             if (mViewPager.getCurrentItem() != tab.getPosition()) {
-                mViewPager.setCurrentItem(tab.getPosition(), false /* smoothScroll */);
+                mViewPager.setCurrentItem(tab.getPosition(), true);
             }
 
             // During the call, we don't remember the tab position.
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 579c833..b1b7e5e 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -104,7 +104,6 @@
         ContactListFilterController.ContactListFilterListener, ProviderStatusListener {
 
     private static final String TAG = "PeopleActivity";
-    private static final Boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE
 
     private static final int SUBACTIVITY_NEW_GROUP = 2;
     private static final int SUBACTIVITY_EDIT_GROUP = 3;
@@ -284,7 +283,7 @@
     private boolean processIntent(boolean forNewIntent) {
         // Extract relevant information from the intent
         mRequest = mIntentResolver.resolveIntent(getIntent());
-        if (DEBUG) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
             Log.d(TAG, this + " processIntent: forNewIntent=" + forNewIntent
                     + " intent=" + getIntent() + " request=" + mRequest);
         }
@@ -485,14 +484,17 @@
             ContactListFilter filter = null;
             int actionCode = mRequest.getActionCode();
             boolean searchMode = mRequest.isSearchMode();
+            TabState tabToOpen = null;
             switch (actionCode) {
                 case ContactsRequest.ACTION_ALL_CONTACTS:
                     filter = ContactListFilter.createFilterWithType(
                             ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
+                    tabToOpen = TabState.ALL;
                     break;
                 case ContactsRequest.ACTION_CONTACTS_WITH_PHONES:
                     filter = ContactListFilter.createFilterWithType(
                             ContactListFilter.FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY);
+                    tabToOpen = TabState.ALL;
                     break;
 
                 // TODO: handle FREQUENT and STREQUENT according to the spec
@@ -502,11 +504,20 @@
                 case ContactsRequest.ACTION_STARRED:
                     filter = ContactListFilter.createFilterWithType(
                             ContactListFilter.FILTER_TYPE_STARRED);
+                    tabToOpen = TabState.FAVORITES;
                     break;
                 case ContactsRequest.ACTION_VIEW_CONTACT:
-                    if (PhoneCapabilityTester.isUsingTwoPanes(this)) {
-                        mActionBarAdapter.setCurrentTab(TabState.ALL);
-                    }
+                    // We redirect this intent to the detail activity on 1-pane, so we don't get
+                    // here.  It's only for 2-pane.
+                    tabToOpen = TabState.ALL;
+                    break;
+                case ContactsRequest.ACTION_GROUP:
+                    tabToOpen = TabState.GROUPS;
+                    // TODO Select the specified group?  See the TODO in ContactsIntentResolver too.
+                    break;
+            }
+            if (tabToOpen != null) {
+                mActionBarAdapter.setCurrentTab(tabToOpen);
             }
 
             if (filter != null) {
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 3f3fd8d..27dbe9c 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -230,8 +230,7 @@
 
     /** Adapter class to fill in data for the Call Log */
     public final class CallLogAdapter extends GroupingListAdapter
-            implements Runnable, ViewTreeObserver.OnPreDrawListener, View.OnClickListener,
-            GroupCreator {
+            implements Runnable, ViewTreeObserver.OnPreDrawListener, GroupCreator {
         /** The time in millis to delay starting the thread processing requests. */
         private static final int START_PROCESSING_REQUESTS_DELAY_MILLIS = 1000;
 
@@ -272,13 +271,15 @@
         /** Can be set to true by tests to disable processing of requests. */
         private volatile boolean mRequestProcessingDisabled = false;
 
-        @Override
-        public void onClick(View view) {
-            IntentProvider intentProvider = (IntentProvider) view.getTag();
-            if (intentProvider != null) {
-                startActivity(intentProvider.getIntent(CallLogFragment.this.getActivity()));
+        private final View.OnClickListener mCallPlayOnClickListener = new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                IntentProvider intentProvider = (IntentProvider) view.getTag();
+                if (intentProvider != null) {
+                    startActivity(intentProvider.getIntent(CallLogFragment.this.getActivity()));
+                }
             }
-        }
+        };
 
         @Override
         public boolean onPreDraw() {
@@ -655,7 +656,8 @@
         private void findAndCacheViews(View view) {
             // Get the views to bind to.
             CallLogListItemViews views = CallLogListItemViews.fromView(view);
-            views.callView.setOnClickListener(this);
+            views.callView.setOnClickListener(mCallPlayOnClickListener);
+            views.playView.setOnClickListener(mCallPlayOnClickListener);
             // Do nothing when a plain photo is clicked. Without this, the list item will fire.
             views.plainPhotoView.setOnClickListener(null);
             view.setTag(views);
@@ -699,14 +701,17 @@
             if (callType == Calls.VOICEMAIL_TYPE) {
                 String voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
                 final long rowId = c.getLong(CallLogQuery.ID);
-                views.callView.setTag(
+                views.playView.setTag(
                         IntentProvider.getPlayVoicemailIntentProvider(rowId, voicemailUri));
+                views.callView.setTag(null);
             } else if (!TextUtils.isEmpty(number)) {
                 // Store away the number so we can call it directly if you click on the call icon.
                 views.callView.setTag(IntentProvider.getReturnCallIntentProvider(number));
+                views.playView.setTag(null);
             } else {
                 // No action enabled.
                 views.callView.setTag(null);
+                views.playView.setTag(null);
             }
 
             // Lookup contacts with this number
diff --git a/src/com/android/contacts/list/ContactsIntentResolver.java b/src/com/android/contacts/list/ContactsIntentResolver.java
index 3ef68d8..63cadf1 100644
--- a/src/com/android/contacts/list/ContactsIntentResolver.java
+++ b/src/com/android/contacts/list/ContactsIntentResolver.java
@@ -72,6 +72,9 @@
             request.setActionCode(ContactsRequest.ACTION_STREQUENT);
         } else if (UI.LIST_GROUP_ACTION.equals(action)) {
             request.setActionCode(ContactsRequest.ACTION_GROUP);
+
+            // TODO Selecting a group is not implemented, but it doesn't seem to be used anywhere.
+            // Can we remove this?
             String groupName = intent.getStringExtra(UI.GROUP_NAME_EXTRA_KEY);
             if (!TextUtils.isEmpty(groupName)) {
                 request.setGroupName(groupName);
@@ -195,7 +198,6 @@
         if (title != null) {
             request.setActivityTitle(title);
         }
-
         return request;
     }
 }
diff --git a/tests/res/values/donottranslate_strings.xml b/tests/res/values/donottranslate_strings.xml
index 4d4d10b..528b129 100644
--- a/tests/res/values/donottranslate_strings.xml
+++ b/tests/res/values/donottranslate_strings.xml
@@ -27,6 +27,7 @@
         <item>LIST_STARRED_ACTION</item>
         <item>LIST_FREQUENT_ACTION</item>
         <item>LIST_STREQUENT_ACTION</item>
+        <item>LIST_GROUP_ACTION</item>
         <item>ACTION_PICK: contact</item>
         <item>ACTION_PICK: contact (legacy)</item>
         <item>ACTION_PICK: phone</item>
diff --git a/tests/src/com/android/contacts/activities/CallLogActivityTests.java b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
index b642ffe..c186106 100644
--- a/tests/src/com/android/contacts/activities/CallLogActivityTests.java
+++ b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
@@ -16,13 +16,18 @@
 
 package com.android.contacts.activities;
 
+import com.android.contacts.CallDetailActivity;
 import com.android.contacts.R;
 import com.android.contacts.calllog.CallLogFragment;
 import com.android.contacts.calllog.CallLogFragment.CallLogQuery;
 import com.android.contacts.calllog.CallLogFragment.ContactInfo;
 import com.android.contacts.calllog.CallLogListItemViews;
+import com.android.contacts.calllog.IntentProvider;
 import com.android.internal.telephony.CallerInfo;
 
+import android.content.ComponentName;
+import android.content.ContentUris;
+import android.content.Intent;
 import android.content.res.Resources;
 import android.database.MatrixCursor;
 import android.graphics.Bitmap;
@@ -30,6 +35,7 @@
 import android.net.Uri;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.VoicemailContract;
 import android.telephony.PhoneNumberUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -291,6 +297,47 @@
         assertEquals(View.VISIBLE, views.plainPhotoView.getVisibility());
     }
 
+    @MediumTest
+    public void testBindView_CallButton() {
+        mCursor.moveToFirst();
+        insert(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+        mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        IntentProvider intentProvider = (IntentProvider) views.callView.getTag();
+        Intent intent = intentProvider.getIntent(mActivity);
+        // Starts a call.
+        assertEquals(Intent.ACTION_CALL_PRIVILEGED, intent.getAction());
+        // To the entry's number.
+        assertEquals(Uri.parse("tel:" + TEST_NUMBER), intent.getData());
+    }
+
+    @MediumTest
+    public void testBindView_PlayButton() {
+        mCursor.moveToFirst();
+        insertVoicemail(TEST_NUMBER, NOW, 0);
+        View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+        mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+        CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+        IntentProvider intentProvider = (IntentProvider) views.playView.getTag();
+        Intent intent = intentProvider.getIntent(mActivity);
+        // Starts the call detail activity.
+        assertEquals(new ComponentName(mActivity, CallDetailActivity.class),
+                intent.getComponent());
+        // With the given entry.
+        assertEquals(ContentUris.withAppendedId(Calls.CONTENT_URI_WITH_VOICEMAIL, 1),
+                intent.getData());
+        // With the URI of the voicemail.
+        assertEquals(
+                ContentUris.withAppendedId(VoicemailContract.Voicemails.CONTENT_URI, 1),
+                intent.getParcelableExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI));
+        // And starts playback.
+        assertTrue(
+                intent.getBooleanExtra(CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK, false));
+    }
+
     /** Returns the label associated with a given phone type. */
     private CharSequence getTypeLabel(int phoneType) {
         return Phone.getTypeLabel(getActivity().getResources(), phoneType, "");
@@ -464,6 +511,36 @@
     }
 
     /**
+     * Insert a new voicemail entry in the test DB.
+     * @param number The phone number. For unknown and private numbers,
+     *               use CallerInfo.UNKNOWN_NUMBER or CallerInfo.PRIVATE_NUMBER.
+     * @param date In millisec since epoch. Use NOW to use the current time.
+     * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
+     */
+    private void insertVoicemail(String number, long date, int duration) {
+        MatrixCursor.RowBuilder row = mCursor.newRow();
+        // Must have the same index as the row.
+        Uri voicemailUri =
+                ContentUris.withAppendedId(VoicemailContract.Voicemails.CONTENT_URI, mIndex);
+        row.add(mIndex);
+        mIndex ++;
+        row.add(number);
+        if (NOW == date) {
+            row.add(new Date().getTime());
+        } else {
+            row.add(date);
+        }
+        if (duration < 0) {
+            duration = mRnd.nextInt(10 * 60);  // 0 - 10 minutes random.
+        }
+        row.add(duration);  // duration
+        row.add(Calls.VOICEMAIL_TYPE);  // type
+        row.add(TEST_COUNTRY_ISO);  // country ISO
+        row.add(voicemailUri);  // voicemail_uri
+        row.add(CallLogFragment.CallLogQuery.SECTION_OLD_ITEM);  // section
+    }
+
+    /**
      * Insert a new private call entry in the test DB.
      * @param date In millisec since epoch. Use NOW to use the current time.
      * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
@@ -482,11 +559,11 @@
     }
 
     /**
-     * Insert a new voicemail call entry in the test DB.
+     * Insert a new call to voicemail entry in the test DB.
      * @param date In millisec since epoch. Use NOW to use the current time.
      * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
      */
-    private void insertVoicemail(long date, int duration) {
+    private void insertCalltoVoicemail(long date, int duration) {
         // mVoicemail may be null
         if (mVoicemail != null) {
             insert(mVoicemail, date, duration, Calls.OUTGOING_TYPE);
@@ -521,7 +598,7 @@
                 insertUnknown(NOW, RAND_DURATION);
                 privateOrUnknownOrVm[1] = true;
             } else if (2 == type) {
-                insertVoicemail(NOW, RAND_DURATION);
+                insertCalltoVoicemail(NOW, RAND_DURATION);
                 privateOrUnknownOrVm[2] = true;
             } else {
                 int inout = mRnd.nextBoolean() ? Calls.OUTGOING_TYPE :  Calls.INCOMING_TYPE;
diff --git a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
index 8c37a02..e5e6a1c 100644
--- a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
+++ b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
@@ -69,6 +69,7 @@
         LIST_STARRED_ACTION,
         LIST_FREQUENT_ACTION,
         LIST_STREQUENT_ACTION,
+        LIST_GROUP_ACTION,
         ACTION_PICK_CONTACT,
         ACTION_PICK_CONTACT_LEGACY,
         ACTION_PICK_PHONE,
@@ -142,7 +143,7 @@
         switch (ContactsIntent.get(position)) {
             case LIST_DEFAULT: {
                 startContactListActivity(
-                        new Intent(Intent.ACTION_VIEW, Contacts.CONTENT_URI));
+                        new Intent(UI.LIST_DEFAULT, Contacts.CONTENT_URI));
                 break;
             }
             case LIST_ALL_CONTACTS_ACTION: {
@@ -170,6 +171,11 @@
                         new Intent(UI.LIST_STREQUENT_ACTION, Contacts.CONTENT_URI));
                 break;
             }
+            case LIST_GROUP_ACTION: {
+                startContactListActivity(
+                        new Intent(UI.LIST_GROUP_ACTION, Contacts.CONTENT_URI));
+                break;
+            }
             case ACTION_PICK_CONTACT: {
                 startContactSelectionActivityForResult(
                         new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI));