Merge "Introduced ContactTileSquare."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f10ae75..88395bf 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -38,6 +38,8 @@
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+    <uses-permission android:name="com.android.voicemail.permission.READ_WRITE_OWN_VOICEMAIL" />
+    <uses-permission android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL" />
 
     <application
         android:name="com.android.contacts.ContactsApplication"
diff --git a/res/drawable-hdpi/ic_dial_action_call.png b/res/drawable-hdpi/ic_dial_action_call.png
index 1ba3a98..b4bdbd5 100644
--- a/res/drawable-hdpi/ic_dial_action_call.png
+++ b/res/drawable-hdpi/ic_dial_action_call.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_dial_action_delete.png b/res/drawable-hdpi/ic_dial_action_delete.png
index 2e206c8..13ecb30 100644
--- a/res/drawable-hdpi/ic_dial_action_delete.png
+++ b/res/drawable-hdpi/ic_dial_action_delete.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_dial_action_search.png b/res/drawable-hdpi/ic_dial_action_search.png
index 042eed0..48000df 100644
--- a/res/drawable-hdpi/ic_dial_action_search.png
+++ b/res/drawable-hdpi/ic_dial_action_search.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dial_action_call.png b/res/drawable-mdpi/ic_dial_action_call.png
index 1942899..35f8fbf 100644
--- a/res/drawable-mdpi/ic_dial_action_call.png
+++ b/res/drawable-mdpi/ic_dial_action_call.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dial_action_delete.png b/res/drawable-mdpi/ic_dial_action_delete.png
index 440ae37..edbcfd0 100644
--- a/res/drawable-mdpi/ic_dial_action_delete.png
+++ b/res/drawable-mdpi/ic_dial_action_delete.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dial_action_search.png b/res/drawable-mdpi/ic_dial_action_search.png
index 101eeae..a700ce4 100644
--- a/res/drawable-mdpi/ic_dial_action_search.png
+++ b/res/drawable-mdpi/ic_dial_action_search.png
Binary files differ
diff --git a/res/layout/dialpad.xml b/res/layout/dialpad.xml
index 50bc2a9..57a612b 100644
--- a/res/layout/dialpad.xml
+++ b/res/layout/dialpad.xml
@@ -15,122 +15,49 @@
 -->
 
 <!-- Dialpad in the Phone app. -->
-<com.android.phone.ButtonGridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<TableLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/dialpad"
-    android:paddingLeft="7dp"
-    android:paddingRight="7dp"
-    android:paddingTop="6dp"
-    android:paddingBottom="6dp"
-    android:layout_width="wrap_content"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal"
+    android:layout_marginTop="10dip"
     android:layout_weight="1">
 
-        <ImageButton android:id="@+id/one"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_1_no_vm"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_one"
-        />
+    <TableRow>
+        <ImageButton android:id="@+id/one" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_1_no_vm" />
+        <ImageButton android:id="@+id/two" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_2" />
+        <ImageButton android:id="@+id/three" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_3" />
+    </TableRow>
 
-        <ImageButton android:id="@+id/two"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_2"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_two"
-        />
+    <TableRow>
+        <ImageButton android:id="@+id/four" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_4" />
+        <ImageButton android:id="@+id/five" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_5" />
+        <ImageButton android:id="@+id/six" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_6" />
+    </TableRow>
 
-        <ImageButton android:id="@+id/three"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_3"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_three"
-        />
+    <TableRow>
+        <ImageButton android:id="@+id/seven" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_7" />
+        <ImageButton android:id="@+id/eight" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_8" />
+        <ImageButton android:id="@+id/nine" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_9" />
+    </TableRow>
 
-        <ImageButton android:id="@+id/four"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_4"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_four"
-        />
+    <TableRow>
+        <ImageButton android:id="@+id/star" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_star" />
+        <ImageButton android:id="@+id/zero" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_0" />
+        <ImageButton android:id="@+id/pound" style="@style/DialtactsDialpadButtonStyle"
+            android:src="@drawable/dial_num_pound" />
 
-        <ImageButton android:id="@+id/five"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_5"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_five"
-        />
-
-        <ImageButton android:id="@+id/six"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_6"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_six"
-        />
-
-        <ImageButton android:id="@+id/seven"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_7"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_seven"
-        />
-
-        <ImageButton android:id="@+id/eight"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_8"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_eight"
-        />
-
-        <ImageButton android:id="@+id/nine"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_9"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_nine"
-        />
-
-        <ImageButton android:id="@+id/star"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_star"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_star"
-        />
-
-        <ImageButton android:id="@+id/zero"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_0"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_zero"
-        />
-
-        <ImageButton android:id="@+id/pound"
-            android:layout_width="88dp"
-            android:layout_height="@dimen/dialpad_button_height"
-            android:src="@drawable/dial_num_pound"
-            android:background="@drawable/btn_dial"
-            android:soundEffectsEnabled="false"
-            android:contentDescription="@string/description_image_button_pound"
-        />
-</com.android.phone.ButtonGridLayout>
+    </TableRow>
+</TableLayout>
diff --git a/res/layout/dialpad_additional_buttons.xml b/res/layout/dialpad_additional_buttons.xml
index a35fae6..cf91053 100644
--- a/res/layout/dialpad_additional_buttons.xml
+++ b/res/layout/dialpad_additional_buttons.xml
@@ -20,42 +20,42 @@
     android:layout_width="match_parent"
     android:layout_height="@dimen/dialpad_additional_buttons_height"
     android:layout_gravity="center_horizontal"
-    android:layout_marginTop="6dip"
+    android:layout_marginBottom="8dip"
     android:layout_weight="0.25"
     android:orientation="horizontal">
 
     <!-- Onscreen "Search button -->
     <ImageButton android:id="@+id/searchButton"
         android:layout_width="0px"
-        android:layout_weight="0.25"
+        android:layout_weight="0.30"
         android:layout_height="match_parent"
         android:layout_gravity="center_vertical"
         android:state_enabled="false"
-        android:background="@drawable/btn_dial_voicemail"
+        android:background="@null"
         android:contentDescription="@string/description_voicemail_button"
-        android:src="@drawable/ic_dial_action_search" />
+        android:src="@drawable/ic_dial_action_search"/>
 
     <!-- Onscreen "Dial" button, diused on all platforms by
          default. Its usage can be disabled using resources (see
          config.xml.) -->
     <ImageButton android:id="@+id/dialButton"
         android:layout_width="0px"
-        android:layout_weight="0.50"
+        android:layout_weight="0.40"
         android:layout_height="match_parent"
         android:layout_gravity="center_vertical"
         android:state_enabled="false"
-        android:background="@drawable/btn_dial_action"
+        android:background="@null"
         android:contentDescription="@string/description_dial_button"
         android:src="@drawable/ic_dial_action_call" />
 
     <!-- Onscreen "Backspace/Delete" button -->
     <ImageButton android:id="@+id/deleteButton"
         android:layout_width="0px"
-        android:layout_weight="0.25"
+        android:layout_weight="0.30"
         android:layout_height="match_parent"
         android:layout_gravity="center_vertical"
         android:state_enabled="false"
-        android:background="@drawable/btn_dial_delete"
+        android:background="@null"
         android:contentDescription="@string/description_delete_button"
         android:src="@drawable/ic_dial_action_delete" />
 </LinearLayout>
diff --git a/res/layout/dialpad_chooser_list_item.xml b/res/layout/dialpad_chooser_list_item.xml
index 853ca47..ecd4285 100644
--- a/res/layout/dialpad_chooser_list_item.xml
+++ b/res/layout/dialpad_chooser_list_item.xml
@@ -26,7 +26,7 @@
         android:scaleType="center" />
 
     <TextView android:id="@+id/text"
-        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textAppearance="?android:attr/textAppearanceMediumInverse"
         android:layout_gravity="center_vertical"
         android:layout_width="0dip"
         android:layout_weight="1"
diff --git a/res/layout/dialpad_fragment.xml b/res/layout/dialpad_fragment.xml
index 7601dfe..b91c27a 100644
--- a/res/layout/dialpad_fragment.xml
+++ b/res/layout/dialpad_fragment.xml
@@ -25,12 +25,16 @@
     <!-- Text field above the keypad where the digits are displayed.
          It's type is set to NULL (to disable the IME keyboard) in the
          java code.
+
+         Background drawable can be controlled programatically.
     -->
     <EditText android:id="@+id/digits"
         android:layout_width="match_parent"
         android:layout_height="@dimen/dialpad_digits_height"
+        android:layout_marginTop="10dip"
         android:gravity="center"
-        android:textAppearance="@style/DialtactsDigitsTextAppearance" />
+        android:textAppearance="@style/DialtactsDigitsTextAppearance"
+        android:textColor="?android:attr/textColorPrimaryInverse" />
 
     <!-- Keypad section -->
     <include layout="@layout/dialpad" />
diff --git a/res/layout/dialtacts_activity.xml b/res/layout/dialtacts_activity.xml
index 445a332..14fb137 100644
--- a/res/layout/dialtacts_activity.xml
+++ b/res/layout/dialtacts_activity.xml
@@ -4,9 +4,9 @@
      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.
@@ -18,27 +18,11 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <!-- Dialer --> -->
-    <fragment
-        class="com.android.contacts.dialpad.DialpadFragment"
-        android:id="@+id/dialpad_fragment"
+    <android.support.v4.view.ViewPager
+        android:id="@+id/pager"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-    <!-- Call Log -->
-    <fragment
-        class="com.android.contacts.calllog.CallLogFragment"
-        android:id="@+id/call_log_fragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-    <!-- Favorites -->
-    <fragment
-        android:id="@+id/favorites_fragment"
-        class="com.android.contacts.list.StrequentContactListFragment"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent" />
-
     <!-- For phone search UI -->
     <fragment
         android:id="@+id/phone_number_picker_fragment"
diff --git a/res/values-long/dimens.xml b/res/values-long/dimens.xml
index 9208e4b..af51d4c 100644
--- a/res/values-long/dimens.xml
+++ b/res/values-long/dimens.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <resources>
-    <dimen name="dialpad_digits_height">74dip</dimen>
+    <dimen name="dialpad_digits_height">80dip</dimen>
     <dimen name="dialpad_additional_buttons_height">58dip</dimen>
-    <dimen name="dialpad_button_height">58dip</dimen>
+    <dimen name="dialpad_button_height">70dip</dimen>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 6a79817..d89ebcf 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -288,18 +288,23 @@
         <item name="android:paddingRight">20dip</item>
     </style>
 
-    <style name="DialtactsDigitsTextAppearance"
-           parent="@android:attr/textAppearanceMedium">
+    <style name="DialtactsDigitsTextAppearance">
         <item name="android:maxLines">1</item>
         <item name="android:scrollHorizontally">true</item>
         <item name="android:textSize">@dimen/dialpad_digits_text_size</item>
         <item name="android:freezesText">true</item>
-        <item name="android:textColor">@color/dialer_button_text</item>
-        <item name="android:background">@drawable/btn_dial_textfield</item>
         <item name="android:focusableInTouchMode">true</item>
         <item name="android:editable">true</item>
         <item name="android:cursorVisible">false</item>
         <item name="android:layout_weight">0</item>
     </style>
 
+    <style name="DialtactsDialpadButtonStyle">
+        <item name="android:layout_width">0dip</item>
+        <item name="android:layout_height">@dimen/dialpad_button_height</item>
+        <item name="android:layout_weight">1</item>
+        <item name="android:background">@null</item>
+        <item name="android:soundEffectsEnabled">false</item>
+        <item name="android:contentDescription">@string/description_image_button_one</item>
+    </style>
 </resources>
diff --git a/src/com/android/contacts/ContactPhotoManager.java b/src/com/android/contacts/ContactPhotoManager.java
index c57583b..e61d379 100644
--- a/src/com/android/contacts/ContactPhotoManager.java
+++ b/src/com/android/contacts/ContactPhotoManager.java
@@ -627,6 +627,7 @@
                         ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT))
                         .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY,
                                 String.valueOf(MAX_PHOTOS_TO_PRELOAD))
+                        .appendQueryParameter(ContactsContract.ALLOW_PROFILE, "1")
                         .build();
                 cursor = mResolver.query(uri, new String[] { Contacts.PHOTO_ID },
                         Contacts.PHOTO_ID + " NOT NULL AND " + Contacts.PHOTO_ID + "!=0",
@@ -683,7 +684,8 @@
 
             Cursor cursor = null;
             try {
-                cursor = mResolver.query(Data.CONTENT_URI,
+                cursor = mResolver.query(Data.CONTENT_URI.buildUpon()
+                        .appendQueryParameter(ContactsContract.ALLOW_PROFILE, "1").build(),
                         COLUMNS,
                         mStringBuilder.toString(),
                         mPhotoIdsAsStrings.toArray(EMPTY_STRING_ARRAY),
diff --git a/src/com/android/contacts/activities/DialpadActivity.java b/src/com/android/contacts/activities/DialpadActivity.java
index bb122df..cfe17f3 100644
--- a/src/com/android/contacts/activities/DialpadActivity.java
+++ b/src/com/android/contacts/activities/DialpadActivity.java
@@ -30,7 +30,6 @@
 import android.os.SystemClock;
 import android.util.Log;
 import android.view.KeyEvent;
-import android.view.Menu;
 import android.view.ViewConfiguration;
 import android.view.Window;
 import android.view.inputmethod.InputMethodManager;
@@ -60,33 +59,12 @@
 
         mFragment = (DialpadFragment) getFragmentManager().findFragmentById(
                 R.id.dialpad_fragment);
-
-        // Manually run the onRestoreInstanceState() sequence here, but only if
-        // our intent does *not* have the DialtactsActivity.EXTRA_IGNORE_STATE
-        // set (see the references to EXTRA_IGNORE_STATE in DialtactsActivity).
-        // TODO: Find a cleaner way of doing this.
-        if (!mFragment.resolveIntent() && (icicle != null)) {
-            super.onRestoreInstanceState(icicle);
-        }
-    }
-
-    @Override
-    protected void onRestoreInstanceState(Bundle icicle) {
-        // Do nothing, state is restored in onCreate() if needed
     }
 
     @Override
     protected void onNewIntent(Intent newIntent) {
         setIntent(newIntent);
-        mFragment.resolveIntent();
-    }
-
-    @Override
-    protected void onPostCreate(Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-
-        // Pass this lifecycle event down to the fragment
-        mFragment.onPostCreate();
+        mFragment.resolveIntent(newIntent);
     }
 
     public DialpadFragment getFragment() {
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index c912c2e..a7a5410 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -21,12 +21,6 @@
 import com.android.contacts.dialpad.DialpadFragment;
 import com.android.contacts.interactions.ImportExportDialogFragment;
 import com.android.contacts.interactions.PhoneNumberInteraction;
-import com.android.contacts.list.ContactListFilter;
-import com.android.contacts.list.ContactsIntentResolver;
-import com.android.contacts.list.ContactsRequest;
-import com.android.contacts.list.DefaultContactBrowseListFragment;
-import com.android.contacts.list.DirectoryListLoader;
-import com.android.contacts.list.OnContactBrowserActionListener;
 import com.android.contacts.list.OnPhoneNumberPickerActionListener;
 import com.android.contacts.list.PhoneNumberPickerFragment;
 import com.android.contacts.list.StrequentContactListFragment;
@@ -41,6 +35,7 @@
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.net.Uri;
@@ -52,12 +47,17 @@
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Intents.UI;
 import android.provider.Settings;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v4.view.ViewPager.OnPageChangeListener;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.SearchView;
 import android.widget.SearchView.OnCloseListener;
 import android.widget.SearchView.OnQueryTextListener;
@@ -72,14 +72,13 @@
 public class DialtactsActivity extends Activity {
     private static final String TAG = "DialtactsActivity";
 
+    /** Used both by {@link ActionBar} and {@link ViewPagerAdapter} */
     private static final int TAB_INDEX_DIALER = 0;
     private static final int TAB_INDEX_CALL_LOG = 1;
     private static final int TAB_INDEX_FAVORITES = 2;
 
     private static final int TAB_INDEX_COUNT = 3;
 
-    public static final String EXTRA_IGNORE_STATE = "ignore-state";
-
     /** Name of the dialtacts shared preferences */
     static final String PREFS_DIALTACTS = "dialtacts";
     static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false;
@@ -88,11 +87,62 @@
     private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab";
     private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;
 
+    /**
+     * Listener interface for Fragments accommodated in {@link ViewPager} enabling them to know
+     * when it becomes visible or invisible inside the ViewPager.
+     */
+    public interface ViewPagerVisibilityListener {
+        public void onVisibilityChange(boolean visible);
+    }
+
+    public class ViewPagerAdapter extends FragmentPagerAdapter {
+        public ViewPagerAdapter(FragmentManager fm) {
+            super(fm);
+        }
+
+        @Override
+        public Fragment getItem(int position) {
+            switch (position) {
+                case TAB_INDEX_DIALER:
+                    return mDialpadFragment;
+                case TAB_INDEX_CALL_LOG:
+                    return mCallLogFragment;
+                case TAB_INDEX_FAVORITES:
+                    return mStrequentFragment;
+            }
+            throw new IllegalStateException("No fragment at position " + position);
+        }
+
+        @Override
+        public int getCount() {
+            return TAB_INDEX_COUNT;
+        }
+    }
+
+    private class PageChangeListener implements OnPageChangeListener {
+        @Override
+        public void onPageScrolled(
+                int position, float positionOffset, int positionOffsetPixels) {
+        }
+
+        @Override
+        public void onPageSelected(int position) {
+            final ActionBar actionBar = getActionBar();
+            actionBar.selectTab(actionBar.getTabAt(position));
+        }
+
+        @Override
+        public void onPageScrollStateChanged(int state) {
+        }
+    }
+
     private String mFilterText;
     private Uri mDialUri;
+
+    /** Enables horizontal swipe between Fragments. */
+    private ViewPager mViewPager;
     private DialpadFragment mDialpadFragment;
     private CallLogFragment mCallLogFragment;
-    private DefaultContactBrowseListFragment mContactsFragment;
     private StrequentContactListFragment mStrequentFragment;
 
     /**
@@ -183,32 +233,30 @@
 
         setContentView(R.layout.dialtacts_activity);
 
-        final FragmentManager fragmentManager = getFragmentManager();
-        mDialpadFragment = (DialpadFragment) fragmentManager
-                .findFragmentById(R.id.dialpad_fragment);
+        // Instantiate Fragments which ViewPager will accommodate. At this point they aren't
+        // attached to any Activity, so no Views inside them will be ready yet.
+        mDialpadFragment = new DialpadFragment();
         mDialpadFragment.setListener(new DialpadFragment.Listener() {
             @Override
             public void onSearchButtonPressed() {
                 enterSearchUi();
             }
         });
-        mCallLogFragment = (CallLogFragment) fragmentManager
-                .findFragmentById(R.id.call_log_fragment);
-        mContactsFragment = (DefaultContactBrowseListFragment) fragmentManager
-                .findFragmentById(R.id.contacts_fragment);
-        mStrequentFragment = (StrequentContactListFragment) fragmentManager
-                .findFragmentById(R.id.favorites_fragment);
-        mPhoneNumberPickerFragment = (PhoneNumberPickerFragment) fragmentManager
+        mCallLogFragment = new CallLogFragment();
+        mStrequentFragment = new StrequentContactListFragment();
+
+        mViewPager = (ViewPager) findViewById(R.id.pager);
+        mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
+        mViewPager.setOnPageChangeListener(new PageChangeListener());
+
+        // This Fragment is _not_ maintained by ViewPager.
+        mPhoneNumberPickerFragment = (PhoneNumberPickerFragment) getFragmentManager()
                 .findFragmentById(R.id.phone_number_picker_fragment);
         mPhoneNumberPickerFragment.setOnPhoneNumberPickerActionListener(
                 mPhoneNumberPickerActionListener);
         mPhoneNumberPickerFragment.setHighlightSearchPrefix(true);
 
-        // Hide all tabs (the current tab will later be reshown once a tab is selected)
-        final FragmentTransaction transaction = fragmentManager.beginTransaction();
-        transaction.hide(mDialpadFragment);
-        transaction.hide(mCallLogFragment);
-        transaction.hide(mStrequentFragment);
+        final FragmentTransaction transaction = getFragmentManager().beginTransaction();
         transaction.hide(mPhoneNumberPickerFragment);
         transaction.commit();
 
@@ -269,7 +317,6 @@
         tab.setTabListener(new TabChangeListener(mDialpadFragment));
         tab.setIcon(R.drawable.ic_tab_dialer);
         getActionBar().addTab(tab);
-        mDialpadFragment.resolveIntent();
     }
 
     private void setupCallLog() {
@@ -280,32 +327,6 @@
         getActionBar().addTab(tab);
     }
 
-    private void setupContacts() {
-        final Tab tab = getActionBar().newTab();
-        tab.setText("");  // R.string.contactsIconLabel
-        tab.setIcon(R.drawable.ic_tab_contacts);
-        tab.setTabListener(new TabChangeListener(mContactsFragment));
-        getActionBar().addTab(tab);
-
-        // TODO: We should not artificially create Intents and put them into the Fragment.
-        // It would be nicer to directly pass in the UI constant
-        Intent intent = new Intent(UI.LIST_ALL_CONTACTS_ACTION);
-        intent.setClass(this, PeopleActivity.class);
-
-        ContactsIntentResolver resolver = new ContactsIntentResolver(this);
-        ContactsRequest request = resolver.resolveIntent(intent);
-        final ContactListFilter filter = ContactListFilter.createFilterWithType(
-                ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
-        mContactsFragment.setFilter(filter, false);
-        mContactsFragment.setSearchMode(request.isSearchMode());
-        mContactsFragment.setQueryString(request.getQueryString(), false);
-        mContactsFragment.setContactsRequest(request);
-        mContactsFragment.setDirectorySearchMode(request.isDirectorySearchEnabled()
-                ? DirectoryListLoader.SEARCH_MODE_DEFAULT
-                : DirectoryListLoader.SEARCH_MODE_NONE);
-        mContactsFragment.setOnContactListActionListener(mListFragmentListener);
-    }
-
     private void setupFavorites() {
         final Tab tab = getActionBar().newTab();
         tab.setText("");  // R.string.contactsFavoritesLabel
@@ -353,26 +374,23 @@
             return;
         }
 
-        // Tell the children activities that they should ignore any possible saved
-        // state and instead reload their state from the parent's intent
-        intent.putExtra(EXTRA_IGNORE_STATE, true);
-
         // Remember the old manually selected tab index so that it can be restored if it is
         // overwritten by one of the programmatic tab selections
         final int savedTabIndex = mLastManuallySelectedTab;
 
-        if (recentCallsRequest) {
-            getActionBar().selectTab(getActionBar().getTabAt(TAB_INDEX_CALL_LOG));
+        final int tabIndex;
+        if (DialpadFragment.phoneIsInUse() || isDialIntent(intent)) {
+            tabIndex = TAB_INDEX_DIALER;
+        } else if (recentCallsRequest) {
+            tabIndex = TAB_INDEX_CALL_LOG;
         } else {
-            getActionBar().selectTab(getActionBar().getTabAt(mLastManuallySelectedTab));
+            tabIndex = mLastManuallySelectedTab;
         }
+        mViewPager.setCurrentItem(tabIndex);
+        getActionBar().selectTab(getActionBar().getTabAt(tabIndex));
 
         // Restore to the previous manual selection
         mLastManuallySelectedTab = savedTabIndex;
-
-        // Tell the children activities that they should honor their saved states
-        // instead of the state from the parent's intent
-        intent.putExtra(EXTRA_IGNORE_STATE, false);
     }
 
     @Override
@@ -386,8 +404,9 @@
         } else if (isDialIntent(newIntent)) {
             setupDialUri(newIntent);
         }
-        // Fill in a phone number again.
-        mDialpadFragment.resolveIntent();
+        if (mPhoneNumberPickerFragment.isVisible()) {
+            exitSearchUi();
+        }
     }
 
     /** Returns true if the given intent contains a phone number to populate the dialer with */
@@ -479,14 +498,6 @@
         }
     }
 
-    @Override
-    protected void onPostCreate(Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-
-        // Pass this lifecycle event down to the fragment
-        mDialpadFragment.onPostCreate();
-    }
-
     /**
      * Tab change listener that is instantiated once for each tab. Handles showing/hiding tabs
      * and remembers manual tab selections
@@ -500,18 +511,28 @@
 
         @Override
         public void onTabUnselected(Tab tab, FragmentTransaction ft) {
-            ft.hide(mFragment);
+            if (mFragment instanceof ViewPagerVisibilityListener) {
+                ((ViewPagerVisibilityListener) mFragment).onVisibilityChange(false);
+            }
         }
 
         @Override
         public void onTabSelected(Tab tab, FragmentTransaction ft) {
-            ft.show(mFragment);
+            if (mFragment instanceof ViewPagerVisibilityListener) {
+                ((ViewPagerVisibilityListener) mFragment).onVisibilityChange(true);
+            }
+            if (mViewPager.getCurrentItem() != tab.getPosition()) {
+                mViewPager.setCurrentItem(tab.getPosition(), false /* smoothScroll */);
+            }
             ft.hide(mPhoneNumberPickerFragment);
 
-            // Remember this tab index. This function is also called, if the tab is set
-            // automatically in which case the setter (setCurrentTab) has to set this to its old
-            // value afterwards
-            mLastManuallySelectedTab = tab.getPosition();
+            // During the call, we don't remember the tab position.
+            if (!DialpadFragment.phoneIsInUse()) {
+                // Remember this tab index. This function is also called, if the tab is set
+                // automatically in which case the setter (setCurrentTab) has to set this to its old
+                // value afterwards
+                mLastManuallySelectedTab = tab.getPosition();
+            }
         }
 
         @Override
@@ -519,56 +540,6 @@
         }
     }
 
-    private OnContactBrowserActionListener mListFragmentListener =
-            new OnContactBrowserActionListener() {
-        @Override
-        public void onViewContactAction(Uri contactLookupUri) {
-            startActivity(new Intent(Intent.ACTION_VIEW, contactLookupUri));
-        }
-
-        @Override
-        public void onSmsContactAction(Uri contactUri) {
-        }
-
-        @Override
-        public void onSelectionChange() {
-        }
-
-        @Override
-        public void onRemoveFromFavoritesAction(Uri contactUri) {
-        }
-
-        @Override
-        public void onInvalidSelection() {
-        }
-
-        @Override
-        public void onFinishAction() {
-        }
-
-        @Override
-        public void onEditContactAction(Uri contactLookupUri) {
-        }
-
-        @Override
-        public void onDeleteContactAction(Uri contactUri) {
-        }
-
-        @Override
-        public void onCreateNewContactAction() {
-        }
-
-        @Override
-        public void onCallContactAction(Uri contactUri) {
-            PhoneNumberInteraction.startInteractionForPhoneCall(
-                    DialtactsActivity.this, contactUri);
-        }
-
-        @Override
-        public void onAddToFavoritesAction(Uri contactUri) {
-        }
-    };
-
     private StrequentContactListFragment.Listener mStrequentListener =
             new StrequentContactListFragment.Listener() {
         @Override
@@ -650,7 +621,9 @@
         final ActionBar actionBar = getActionBar();
 
         final Tab tab = actionBar.getSelectedTab();
-        if (tab != null) {
+
+        // User can search during the call, but we don't want to remember the status.
+        if (tab != null && !DialpadFragment.phoneIsInUse()) {
             mLastManuallySelectedTab = tab.getPosition();
         }
 
@@ -664,6 +637,24 @@
             mSearchView.setOnQueryTextListener(mPhoneSearchQueryTextListener);
             mSearchView.setOnCloseListener(mPhoneSearchCloseListener);
             mSearchView.requestFocus();
+            // Show soft keyboard when SearchView has a focus. Need to delay the request in order
+            // to let InputMethodManager handle it correctly.
+            mSearchView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+                @Override
+                public void onViewDetachedFromWindow(View v) {
+                }
+
+                @Override
+                public void onViewAttachedToWindow(View v) {
+                    if (mSearchView.hasFocus()) {
+                        mSearchView.postDelayed(new Runnable() {
+                            public void run() {
+                                showInputMethod(mSearchView.findFocus());
+                            }
+                        }, 0);
+                    }
+                }
+            });
             actionBar.setCustomView(searchViewLayout,
                     new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
         } else {
@@ -676,14 +667,19 @@
         // Show the search fragment and hide everything else.
         final FragmentTransaction transaction = getFragmentManager().beginTransaction();
         transaction.show(mPhoneNumberPickerFragment);
-        transaction.hide(mDialpadFragment);
-        transaction.hide(mCallLogFragment);
-        transaction.hide(mStrequentFragment);
         transaction.commit();
+        mViewPager.setVisibility(View.GONE);
 
         mInSearchUi = true;
     }
 
+    private void showInputMethod(View view) {
+        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (imm != null) {
+            imm.showSoftInput(view, 0);
+        }
+    }
+
     /**
      * Goes back to usual Phone UI with tags. Previously selected Tag and associated Fragment
      * should be automatically focused again.
@@ -695,6 +691,12 @@
         actionBar.setDisplayShowCustomEnabled(false);
         actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
 
+        final FragmentTransaction transaction = getFragmentManager().beginTransaction();
+        transaction.hide(mPhoneNumberPickerFragment);
+        transaction.commit();
+
+        mViewPager.setVisibility(View.VISIBLE);
+
         // Request to update option menu.
         invalidateOptionsMenu();
 
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 31373cc..8b09e28 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -21,6 +21,7 @@
 import com.android.contacts.ContactPhotoManager;
 import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
+import com.android.contacts.activities.DialtactsActivity.ViewPagerVisibilityListener;
 import com.android.contacts.util.ExpirableCache;
 import com.android.internal.telephony.CallerInfo;
 import com.google.common.annotations.VisibleForTesting;
@@ -43,7 +44,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.provider.CallLog;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.Contacts;
@@ -75,7 +75,7 @@
  * Displays a list of call log entries.
  */
 public class CallLogFragment extends ListFragment
-        implements View.OnCreateContextMenuListener {
+        implements View.OnCreateContextMenuListener, ViewPagerVisibilityListener {
     private static final String TAG = "CallLogFragment";
 
     /**
@@ -144,6 +144,9 @@
     private String mCurrentCountryIso;
     private boolean mScrollToTop;
 
+    private MenuItem mDeleteAllCallLogMenuItem;
+    private boolean mShowMenu;
+
     public static final class ContactInfo {
         public long personId;
         public String name;
@@ -315,7 +318,7 @@
             values.put(Calls.CACHED_NUMBER_LABEL, ci.label);
 
             try {
-                getActivity().getContentResolver().update(Calls.CONTENT_URI, values,
+                getActivity().getContentResolver().update(Calls.CONTENT_URI_WITH_VOICEMAIL, values,
                         Calls.NUMBER + "='" + ciq.number + "'", null);
             } catch (SQLiteDiskIOException e) {
                 Log.w(TAG, "Exception while updating call info", e);
@@ -886,7 +889,7 @@
 
         ContentValues values = new ContentValues(1);
         values.put(Calls.NEW, "0");
-        mQueryHandler.startUpdate(UPDATE_TOKEN, null, Calls.CONTENT_URI,
+        mQueryHandler.startUpdate(UPDATE_TOKEN, null, Calls.CONTENT_URI_WITH_VOICEMAIL,
                 values, where.toString(), null);
     }
 
@@ -895,15 +898,21 @@
 
         // Cancel any pending queries
         mQueryHandler.cancelOperation(QUERY_TOKEN);
-        mQueryHandler.startQuery(QUERY_TOKEN, null, Calls.CONTENT_URI,
+        mQueryHandler.startQuery(QUERY_TOKEN, null, Calls.CONTENT_URI_WITH_VOICEMAIL,
                 CallLogQuery._PROJECTION, null, null, Calls.DEFAULT_SORT_ORDER);
     }
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         super.onCreateOptionsMenu(menu, inflater);
-        menu.add(0, OptionsMenuItems.DELETE_ALL, 0, R.string.recentCalls_deleteAll).setIcon(
-                android.R.drawable.ic_menu_close_clear_cancel);
+        mDeleteAllCallLogMenuItem = menu.add(0, OptionsMenuItems.DELETE_ALL,
+                0, R.string.recentCalls_deleteAll)
+                .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
+    }
+
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        mDeleteAllCallLogMenuItem.setVisible(mShowMenu);
     }
 
     @Override
@@ -1028,7 +1037,7 @@
                     sb.append(id);
                 }
 
-                getActivity().getContentResolver().delete(Calls.CONTENT_URI,
+                getActivity().getContentResolver().delete(Calls.CONTENT_URI_WITH_VOICEMAIL,
                         Calls._ID + " IN (" + sb + ")", null);
             }
         }
@@ -1121,7 +1130,7 @@
             mAdapter.toggleGroup(position);
         } else {
             Intent intent = new Intent(getActivity(), CallDetailActivity.class);
-            intent.setData(ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI, id));
+            intent.setData(ContentUris.withAppendedId(Calls.CONTENT_URI_WITH_VOICEMAIL, id));
             startActivity(intent);
         }
     }
@@ -1135,4 +1144,9 @@
     public String getVoiceMailNumber() {
         return mVoiceMailNumber;
     }
+
+    @Override
+    public void onVisibilityChange(boolean visible) {
+        mShowMenu = visible;
+    }
 }
diff --git a/src/com/android/contacts/dialpad/DialpadFragment.java b/src/com/android/contacts/dialpad/DialpadFragment.java
index 7be16f5..70dd4b1 100644
--- a/src/com/android/contacts/dialpad/DialpadFragment.java
+++ b/src/com/android/contacts/dialpad/DialpadFragment.java
@@ -20,6 +20,7 @@
 import com.android.contacts.R;
 import com.android.contacts.SpecialCharSequenceMgr;
 import com.android.contacts.activities.DialtactsActivity;
+import com.android.contacts.activities.DialtactsActivity.ViewPagerVisibilityListener;
 import com.android.internal.telephony.ITelephony;
 import com.android.phone.CallLogAsync;
 import com.android.phone.HapticFeedback;
@@ -73,7 +74,8 @@
 public class DialpadFragment extends Fragment
         implements View.OnClickListener,
         View.OnLongClickListener, View.OnKeyListener,
-        AdapterView.OnItemClickListener, TextWatcher {
+        AdapterView.OnItemClickListener, TextWatcher,
+        ViewPagerVisibilityListener {
     private static final String TAG = "DialpadFragment";
 
     private static final String EMPTY_NUMBER = "";
@@ -107,7 +109,8 @@
     private View mDialButton;
     private ListView mDialpadChooser;
     private DialpadChooserAdapter mDialpadChooserAdapter;
-    //Member variables for dialpad options
+
+    // Member variables for dialpad options
     private MenuItem m2SecPauseMenuItem;
     private MenuItem mWaitMenuItem;
     private MenuItem mCallSettingsItem;
@@ -116,6 +119,8 @@
     private static final int MENU_WAIT = 3;
     private static final int MENU_CALL_SETTINGS = 4;
 
+    private boolean mShowMenu;
+
     private boolean mHasVoicemail = false;
 
     // Last number dialed, retrieved asynchronously from the call DB
@@ -190,12 +195,14 @@
             mDigits.getText().clear();
         }
 
-        if (!isDigitsEmpty()) {
+        // Previously we changed background color depending on its text status. Now we don't.
+        // TODO: remove the relevant codes entirely once we're sure we won't use them.
+        /*if (!isDigitsEmpty()) {
             mDigits.setBackgroundDrawable(mDigitsBackground);
         } else {
             mDigits.setCursorVisible(false);
             mDigits.setBackgroundDrawable(mDigitsEmptyBackground);
-        }
+        }*/
 
         updateDialAndDeleteButtonEnabledState();
     }
@@ -229,6 +236,7 @@
         mDigits.setKeyListener(DialerKeyListener.getInstance());
         mDigits.setOnClickListener(this);
         mDigits.setOnKeyListener(this);
+        mDigits.addTextChangedListener(this);
 
         maybeAddNumberFormatting();
 
@@ -276,6 +284,8 @@
         mDialpadChooser = (ListView) fragmentView.findViewById(R.id.dialpadChooser);
         mDialpadChooser.setOnItemClickListener(this);
 
+        resolveIntent(getActivity().getIntent());
+
         return fragmentView;
     }
 
@@ -299,19 +309,9 @@
      *    any possible saved state, and instead reset our state based on the parent's
      *    intent.
      */
-    public boolean resolveIntent() {
+    public boolean resolveIntent(Intent intent) {
         boolean ignoreState = false;
 
-        // Find the proper intent
-        final Intent intent;
-        if (getActivity().isChild()) {
-            intent = getActivity().getParent().getIntent();
-            ignoreState = intent.getBooleanExtra(DialtactsActivity.EXTRA_IGNORE_STATE, false);
-        } else {
-            intent = getActivity().getIntent();
-        }
-        // Log.i(TAG, "==> resolveIntent(): intent: " + intent);
-
         // by default we are not adding a call.
         mIsAddCallMode = false;
 
@@ -418,16 +418,6 @@
         fragmentView.findViewById(R.id.pound).setOnClickListener(this);
     }
 
-    // Do some stuff that needs to happen only once, but which we
-    // can't do directly from onCreate().
-    public void onPostCreate() {
-        // This can't be done in onCreate(), since the auto-restoring of the digits
-        // will play DTMF tones for all the old digits if it is when onRestoreSavedInstanceState()
-        // is called. This method will be called every time the activity is created, and
-        // will always happen after onRestoreSavedInstanceState().
-        mDigits.addTextChangedListener(this);
-    }
-
     @Override
     public void onResume() {
         super.onResume();
@@ -460,13 +450,13 @@
             }
         }
 
-        Activity parent = getActivity().getParent();
+        Activity parent = getActivity();
         // See if we were invoked with a DIAL intent. If we were, fill in the appropriate
         // digits in the dialer field.
-        if (parent != null && parent instanceof DialtactsActivity) {
+        if (parent instanceof DialtactsActivity) {
             Uri dialUri = ((DialtactsActivity) parent).getAndClearDialUri();
             if (dialUri != null) {
-                resolveIntent();
+                resolveIntent(parent.getIntent());
             }
         }
 
@@ -541,7 +531,14 @@
             return;
         }
 
-        // We show "Call Settings" menu every time
+        if (!mShowMenu) {
+            mCallSettingsItem.setVisible(false);
+            mAddToContactMenuItem.setVisible(false);
+            m2SecPauseMenuItem.setVisible(false);
+            mWaitMenuItem.setVisible(false);
+            return;
+        }
+
         mCallSettingsItem.setVisible(true);
         Intent settingsIntent = new Intent(Intent.ACTION_MAIN);
         settingsIntent.setClassName("com.android.phone", "com.android.phone.CallFeaturesSetting");
@@ -1030,7 +1027,7 @@
      * @return true if the phone is "in use", meaning that at least one line
      *              is active (ie. off hook or ringing or dialing).
      */
-    private boolean phoneIsInUse() {
+    public static boolean phoneIsInUse() {
         boolean phoneInUse = false;
         try {
             ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
@@ -1235,4 +1232,9 @@
     public void setListener(Listener listener) {
         mListener = listener;
     }
+
+    @Override
+    public void onVisibilityChange(boolean visible) {
+        mShowMenu = visible;
+    }
 }
diff --git a/src/com/android/contacts/list/PhoneNumberListAdapter.java b/src/com/android/contacts/list/PhoneNumberListAdapter.java
index fee1064..53a9e5f 100644
--- a/src/com/android/contacts/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/list/PhoneNumberListAdapter.java
@@ -27,6 +27,7 @@
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.Directory;
 import android.text.TextUtils;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -34,6 +35,7 @@
  * A cursor adapter for the {@link Phone#CONTENT_TYPE} content type.
  */
 public class PhoneNumberListAdapter extends ContactEntryListAdapter {
+    private static final String TAG = PhoneNumberListAdapter.class.getSimpleName();
 
     protected static final String[] PHONES_PROJECTION = new String[] {
         Phone._ID,                          // 0
@@ -137,11 +139,18 @@
 
     /**
      * Builds a {@link Data#CONTENT_URI} for the given cursor position.
+     *
+     * @return Uri for the data. may be null if the cursor is not ready.
      */
     public Uri getDataUri(int position) {
         Cursor cursor = ((Cursor)getItem(position));
-        long id = cursor.getLong(PHONE_ID_COLUMN_INDEX);
-        return ContentUris.withAppendedId(Data.CONTENT_URI, id);
+        if (cursor != null) {
+            long id = cursor.getLong(PHONE_ID_COLUMN_INDEX);
+            return ContentUris.withAppendedId(Data.CONTENT_URI, id);
+        } else {
+            Log.w(TAG, "Cursor was null in getDataUri() call. Returning null instead.");
+            return null;
+        }
     }
 
     @Override
diff --git a/src/com/android/contacts/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
index b40f80a..3be55ce 100644
--- a/src/com/android/contacts/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
@@ -21,6 +21,7 @@
 
 import android.content.Intent;
 import android.net.Uri;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -30,6 +31,8 @@
  */
 public class PhoneNumberPickerFragment extends ContactEntryListFragment<ContactEntryListAdapter>
         implements OnShortcutIntentCreatedListener {
+    private static final String TAG = PhoneNumberPickerFragment.class.getSimpleName();
+
     private OnPhoneNumberPickerActionListener mListener;
     private String mShortcutAction;
 
@@ -58,12 +61,20 @@
 
     @Override
     protected void onItemClick(int position, long id) {
+        final Uri phoneUri;
         if (!isLegacyCompatibilityMode()) {
             PhoneNumberListAdapter adapter = (PhoneNumberListAdapter)getAdapter();
-            pickPhoneNumber(adapter.getDataUri(position));
+            phoneUri = adapter.getDataUri(position);
+
         } else {
             LegacyPhoneNumberListAdapter adapter = (LegacyPhoneNumberListAdapter)getAdapter();
-            pickPhoneNumber(adapter.getPhoneUri(position));
+            phoneUri = adapter.getPhoneUri(position);
+        }
+
+        if (phoneUri != null) {
+            pickPhoneNumber(phoneUri);
+        } else {
+            Log.w(TAG, "Item at " + position + " was clicked before adapter is ready. Ignoring");
         }
     }