Merge change 25770 into eclair

* changes:
  New dial action button at the bottom of the dialer.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 68e66ba..6f6e3cd 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.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.
@@ -349,6 +349,7 @@
                 <data android:mimeType="vnd.android.cursor.dir/contact" />
                 <data android:mimeType="vnd.android.cursor.dir/raw_contact" />
             </intent-filter>
+
         </activity>
 
         <!-- Stub service used to keep our process alive long enough for
@@ -360,7 +361,7 @@
         <!-- Views the details of a single contact -->
         <activity android:name="ContactOptionsActivity"
             android:label="@string/contactOptionsTitle"
-        >   
+        >
             <intent-filter>
                 <action android:name="android.intent.action.EDIT" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -377,10 +378,10 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
             />
-        </activity>        
+        </activity>
 
         <!-- Makes .ContactsListActivity the search target for any activity in Contacts -->
-        <meta-data android:name="android.app.default_searchable" 
+        <meta-data android:name="android.app.default_searchable"
                    android:value=".ContactsListActivity" />
 
 
diff --git a/res/drawable-finger/divider_vertical_dark.png b/res/drawable-finger/divider_vertical_dark.png
deleted file mode 100644
index dcf850e..0000000
--- a/res/drawable-finger/divider_vertical_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-finger/frame_sm_track.9.png b/res/drawable-finger/frame_sm_track.9.png
deleted file mode 100644
index 5147392..0000000
--- a/res/drawable-finger/frame_sm_track.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-finger/list_item_secondary_button.xml b/res/drawable-finger/list_item_secondary_button.xml
deleted file mode 100644
index c71d16f..0000000
--- a/res/drawable-finger/list_item_secondary_button.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"
-        android:drawable="@drawable/list_item_secondary_button_pressed" />
-    <item android:state_focused="true"
-        android:drawable="@drawable/list_item_secondary_button_selected" />
-    <item
-        android:drawable="@drawable/list_item_secondary_button_default" />
-</selector>
diff --git a/res/drawable-finger/list_item_secondary_button_default.9.png b/res/drawable-finger/list_item_secondary_button_default.9.png
deleted file mode 100644
index 7c627e2..0000000
--- a/res/drawable-finger/list_item_secondary_button_default.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-finger/list_item_secondary_button_pressed.9.png b/res/drawable-finger/list_item_secondary_button_pressed.9.png
deleted file mode 100644
index 215397e..0000000
--- a/res/drawable-finger/list_item_secondary_button_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-finger/list_item_secondary_button_selected.9.png b/res/drawable-finger/list_item_secondary_button_selected.9.png
deleted file mode 100644
index 21b59b1..0000000
--- a/res/drawable-finger/list_item_secondary_button_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-finger/social_picture_border_in_list.9.png b/res/drawable-finger/social_picture_border_in_list.9.png
deleted file mode 100644
index 8fc6ab3..0000000
--- a/res/drawable-finger/social_picture_border_in_list.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-finger/tab_divider.xml b/res/drawable-finger/tab_divider.xml
deleted file mode 100644
index 2590ce7..0000000
--- a/res/drawable-finger/tab_divider.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/tab_divider_res"
-    android:height="48dip"
-/>
diff --git a/res/drawable-hdpi-finger/divider_vertical_dark.9.png b/res/drawable-hdpi-finger/divider_vertical_dark.9.png
new file mode 100644
index 0000000..30a68d0
--- /dev/null
+++ b/res/drawable-hdpi-finger/divider_vertical_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/ic_tab_selected_dialer.png b/res/drawable-hdpi-finger/ic_tab_selected_dialer.png
new file mode 100644
index 0000000..a84f8ab
--- /dev/null
+++ b/res/drawable-hdpi-finger/ic_tab_selected_dialer.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/ic_tab_unselected_dialer.png b/res/drawable-hdpi-finger/ic_tab_unselected_dialer.png
new file mode 100644
index 0000000..51b0656
--- /dev/null
+++ b/res/drawable-hdpi-finger/ic_tab_unselected_dialer.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/tab_focused.9.png b/res/drawable-hdpi-finger/tab_focused.9.png
new file mode 100644
index 0000000..a65b8f5
--- /dev/null
+++ b/res/drawable-hdpi-finger/tab_focused.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_divider_res.9.png b/res/drawable-hdpi-finger/tab_focused_bottom.9.png
similarity index 65%
copy from res/drawable-finger/tab_divider_res.9.png
copy to res/drawable-hdpi-finger/tab_focused_bottom.9.png
index 3fdc372..2fe4a9b 100644
--- a/res/drawable-finger/tab_divider_res.9.png
+++ b/res/drawable-hdpi-finger/tab_focused_bottom.9.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/tab_left_arrow.png b/res/drawable-hdpi-finger/tab_left_arrow.png
new file mode 100644
index 0000000..c2274f1
--- /dev/null
+++ b/res/drawable-hdpi-finger/tab_left_arrow.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/tab_pressed.9.png b/res/drawable-hdpi-finger/tab_pressed.9.png
new file mode 100644
index 0000000..0f90065
--- /dev/null
+++ b/res/drawable-hdpi-finger/tab_pressed.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_divider_res.9.png b/res/drawable-hdpi-finger/tab_pressed_bottom.9.png
similarity index 65%
copy from res/drawable-finger/tab_divider_res.9.png
copy to res/drawable-hdpi-finger/tab_pressed_bottom.9.png
index 3fdc372..00361aa 100644
--- a/res/drawable-finger/tab_divider_res.9.png
+++ b/res/drawable-hdpi-finger/tab_pressed_bottom.9.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/tab_right_arrow.png b/res/drawable-hdpi-finger/tab_right_arrow.png
new file mode 100644
index 0000000..8a847e0
--- /dev/null
+++ b/res/drawable-hdpi-finger/tab_right_arrow.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/tab_selected.9.png b/res/drawable-hdpi-finger/tab_selected.9.png
new file mode 100644
index 0000000..08a39ff
--- /dev/null
+++ b/res/drawable-hdpi-finger/tab_selected.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_divider_res.9.png b/res/drawable-hdpi-finger/tab_selected_bottom.9.png
similarity index 65%
rename from res/drawable-finger/tab_divider_res.9.png
rename to res/drawable-hdpi-finger/tab_selected_bottom.9.png
index 3fdc372..3cc26bc 100644
--- a/res/drawable-finger/tab_divider_res.9.png
+++ b/res/drawable-hdpi-finger/tab_selected_bottom.9.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/tab_unselected.9.png b/res/drawable-hdpi-finger/tab_unselected.9.png
new file mode 100644
index 0000000..6150b5b
--- /dev/null
+++ b/res/drawable-hdpi-finger/tab_unselected.9.png
Binary files differ
diff --git a/res/drawable-mdpi-finger/divider_vertical_dark.9.png b/res/drawable-mdpi-finger/divider_vertical_dark.9.png
new file mode 100644
index 0000000..30a68d0
--- /dev/null
+++ b/res/drawable-mdpi-finger/divider_vertical_dark.9.png
Binary files differ
diff --git a/res/drawable-finger/ic_tab_selected_dialer.png b/res/drawable-mdpi-finger/ic_tab_selected_dialer.png
similarity index 100%
rename from res/drawable-finger/ic_tab_selected_dialer.png
rename to res/drawable-mdpi-finger/ic_tab_selected_dialer.png
Binary files differ
diff --git a/res/drawable-finger/ic_tab_unselected_dialer.png b/res/drawable-mdpi-finger/ic_tab_unselected_dialer.png
similarity index 100%
rename from res/drawable-finger/ic_tab_unselected_dialer.png
rename to res/drawable-mdpi-finger/ic_tab_unselected_dialer.png
Binary files differ
diff --git a/res/drawable-finger/tab_focused.9.png b/res/drawable-mdpi-finger/tab_focused.9.png
similarity index 100%
rename from res/drawable-finger/tab_focused.9.png
rename to res/drawable-mdpi-finger/tab_focused.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_focused_bottom.9.png b/res/drawable-mdpi-finger/tab_focused_bottom.9.png
similarity index 100%
rename from res/drawable-finger/tab_focused_bottom.9.png
rename to res/drawable-mdpi-finger/tab_focused_bottom.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_left_arrow.png b/res/drawable-mdpi-finger/tab_left_arrow.png
similarity index 100%
rename from res/drawable-finger/tab_left_arrow.png
rename to res/drawable-mdpi-finger/tab_left_arrow.png
Binary files differ
diff --git a/res/drawable-finger/tab_pressed.9.png b/res/drawable-mdpi-finger/tab_pressed.9.png
similarity index 100%
rename from res/drawable-finger/tab_pressed.9.png
rename to res/drawable-mdpi-finger/tab_pressed.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_pressed_bottom.9.png b/res/drawable-mdpi-finger/tab_pressed_bottom.9.png
similarity index 100%
rename from res/drawable-finger/tab_pressed_bottom.9.png
rename to res/drawable-mdpi-finger/tab_pressed_bottom.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_right_arrow.png b/res/drawable-mdpi-finger/tab_right_arrow.png
similarity index 100%
rename from res/drawable-finger/tab_right_arrow.png
rename to res/drawable-mdpi-finger/tab_right_arrow.png
Binary files differ
diff --git a/res/drawable-finger/tab_selected.9.png b/res/drawable-mdpi-finger/tab_selected.9.png
similarity index 100%
rename from res/drawable-finger/tab_selected.9.png
rename to res/drawable-mdpi-finger/tab_selected.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_selected_bottom.9.png b/res/drawable-mdpi-finger/tab_selected_bottom.9.png
similarity index 100%
rename from res/drawable-finger/tab_selected_bottom.9.png
rename to res/drawable-mdpi-finger/tab_selected_bottom.9.png
Binary files differ
diff --git a/res/drawable-finger/tab_unselected.9.png b/res/drawable-mdpi-finger/tab_unselected.9.png
similarity index 100%
rename from res/drawable-finger/tab_unselected.9.png
rename to res/drawable-mdpi-finger/tab_unselected.9.png
Binary files differ
diff --git a/res/drawable/bg_stream.png b/res/drawable/bg_stream.png
deleted file mode 100644
index 0cec313..0000000
--- a/res/drawable/bg_stream.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/bubble_stream.9.png b/res/drawable/bubble_stream.9.png
deleted file mode 100644
index 8a34d52..0000000
--- a/res/drawable/bubble_stream.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/bubble_stream_dither.xml b/res/drawable/bubble_stream_dither.xml
deleted file mode 100644
index 1b5310e..0000000
--- a/res/drawable/bubble_stream_dither.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/bubble_stream"
-    android:dither="true"
-/>
diff --git a/res/drawable/stream_bot.png b/res/drawable/stream_bot.png
deleted file mode 100644
index cea0eb3..0000000
--- a/res/drawable/stream_bot.png
+++ /dev/null
Binary files differ
diff --git a/res/layout-finger/all_tab_indicator.xml b/res/layout-finger/all_tab_indicator.xml
index c8a4c44..25294c4 100644
--- a/res/layout-finger/all_tab_indicator.xml
+++ b/res/layout-finger/all_tab_indicator.xml
@@ -18,8 +18,8 @@
     android:layout_width="wrap_content"
     android:layout_height="40dip"
     android:layout_weight="1"
-    android:layout_marginLeft="-4dip"
-    android:layout_marginRight="-4dip"
+    android:layout_marginLeft="-3dip"
+    android:layout_marginRight="-3dip"
     android:minWidth="72dip"
     android:background="@+drawable/tab_indicator_bg">
 
diff --git a/res/layout-finger/list_item_text_icons.xml b/res/layout-finger/list_item_text_icons.xml
index c551740..051dde9 100644
--- a/res/layout-finger/list_item_text_icons.xml
+++ b/res/layout-finger/list_item_text_icons.xml
@@ -92,13 +92,12 @@
     />
 
     <ImageView android:id="@+id/secondary_action_button"
-        android:layout_width="50dip"
-        android:layout_height="50dip"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:layout_marginLeft="5dip"
         android:layout_marginRight="7dip"
         android:gravity="center"
         android:scaleType="centerInside"
-        android:background="@drawable/list_item_secondary_button"
     />
 
 </LinearLayout>
diff --git a/res/layout-finger/social_list.xml b/res/layout-finger/social_list.xml
deleted file mode 100644
index 28ff590..0000000
--- a/res/layout-finger/social_list.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:contacts="http://schemas.android.com/apk/res/com.android.contacts"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:orientation="vertical">
-
-    <com.android.contacts.EdgeTriggerView
-        android:id="@+id/edge_trigger"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
-        contacts:edgeWidth="80dip"
-        contacts:listenEdges="left">
-
-        <ListView
-            android:id="@android:id/list"
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"
-            android:fastScrollEnabled="true"            
-            android:divider="#0000"
-            android:dividerHeight="0dip"
-        />
-
-    </com.android.contacts.EdgeTriggerView>
-
-    <ScrollView
-        android:id="@android:id/empty"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
-        android:fillViewport="true">
-
-        <TextView
-            android:id="@+id/emptyText"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/noContacts"
-            android:textSize="20sp"
-            android:textColor="?android:attr/textColorSecondary"
-            android:paddingLeft="10dip"
-            android:paddingRight="10dip"
-            android:paddingTop="10dip"
-            android:lineSpacingMultiplier="0.92" />
-
-    </ScrollView>
-
-</LinearLayout>
diff --git a/res/layout-finger/social_list_item.xml b/res/layout-finger/social_list_item.xml
deleted file mode 100644
index ab4eddf..0000000
--- a/res/layout-finger/social_list_item.xml
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeight"
->
-
-    <View
-        android:id="@+id/divider"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentTop="true"
-
-        android:background="?android:attr/listDivider"
-    />
-
-    <ImageView
-        android:id="@+id/sourceIcon"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentTop="true"
-        android:layout_centerVertical="true"
-        android:layout_marginTop="15dip"
-        android:layout_marginLeft="5dip"
-        android:layout_marginRight="8dip"
-
-        android:gravity="center"
-        android:scaleType="centerInside"
-    />
-
-    <ImageView
-        android:id="@+id/photo"
-        android:layout_width="54dip"
-        android:layout_height="54dip"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentTop="true"
-        android:layout_centerVertical="true"
-        android:layout_marginTop="1dip"
-        android:layout_marginRight="8dip"
-
-        android:background="@drawable/social_picture_border_in_list"
-        android:cropToPadding="true"
-        android:gravity="center"
-        android:padding="5dip"
-        android:scaleType="fitCenter"
-    />
-
-    <LinearLayout
-        android:layout_width="0dip"
-        android:layout_height="wrap_content"
-        android:layout_toRightOf="@id/photo"
-        android:layout_toLeftOf="@id/sourceIcon"
-        android:paddingTop="5dip"
-        android:paddingBottom="5dip"
-        android:orientation="vertical"
-    >
-    
-        <TextView
-            android:id="@+id/content"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-                
-            android:maxLines="6"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorPrimary"
-        />
-    
-        <TextView
-            android:id="@+id/summary"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-    
-            android:paddingLeft="20dip"
-            android:paddingBottom="5dip"
-            android:maxLines="2"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="#38F"
-        />
-    
-        <ImageView
-            android:id="@+id/thumbnail"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="20dip"
-            
-            android:maxHeight="54dip"
-            android:maxWidth="100dip"
-            android:scaleType="fitStart"
-        />
-    
-        <TextView
-            android:id="@+id/published"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-    
-            android:lines="1"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorSecondary"
-            android:textSize="12sp"
-        />
-    </LinearLayout>
-
-</RelativeLayout>
diff --git a/res/layout-finger/social_list_item_reply.xml b/res/layout-finger/social_list_item_reply.xml
deleted file mode 100644
index b7c06a0..0000000
--- a/res/layout-finger/social_list_item_reply.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:paddingBottom="5dip"
->
-
-    <ImageView
-        android:id="@+id/photo"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentTop="true"
-        android:layout_centerVertical="true"
-        android:layout_marginTop="15dip"
-        android:layout_marginLeft="50dip"
-
-        android:background="@drawable/social_picture_border_in_list"
-        android:cropToPadding="true"
-        android:gravity="center"
-        android:padding="5dip"
-        android:scaleType="fitCenter"
-    />
-
-    <LinearLayout
-        android:layout_width="0dip"
-        android:layout_height="wrap_content"
-        android:layout_toRightOf="@id/photo"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentTop="true"
-        android:layout_marginLeft="-6dip"
-        android:layout_marginRight="5dip"
-        
-        android:paddingTop="8dip"
-        android:paddingRight="8dip"
-        android:paddingBottom="8dip"
-        android:paddingLeft="18dip"
-        android:orientation="vertical"
-        android:background="@drawable/bubble_stream_dither"
-    >
-    
-        <TextView
-            android:id="@+id/content"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-                
-            android:maxLines="6"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorPrimary"
-        />
-    
-        <TextView
-            android:id="@+id/summary"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-    
-            android:paddingLeft="20dip"
-            android:paddingBottom="5dip"
-            android:maxLines="2"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="#38F"
-        />
-    
-        <ImageView
-            android:id="@+id/thumbnail"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="20dip"
-            
-            android:maxHeight="54dip"
-            android:maxWidth="100dip"
-            android:scaleType="fitStart"
-        />
-    
-        <TextView
-            android:id="@+id/published"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-    
-            android:lines="1"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorSecondary"
-            android:textSize="12sp"
-        />
-    </LinearLayout>
-</RelativeLayout>
diff --git a/res/layout-finger/tab_divider.xml b/res/layout-finger/tab_divider.xml
deleted file mode 100644
index 8e0e65d..0000000
--- a/res/layout-finger/tab_divider.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="fill_parent"
-    android:background="@drawable/tab_divider"/>
\ No newline at end of file
diff --git a/res/layout-finger/tab_indicator.xml b/res/layout-finger/tab_indicator.xml
index dad6031..1158eb0 100644
--- a/res/layout-finger/tab_indicator.xml
+++ b/res/layout-finger/tab_indicator.xml
@@ -18,8 +18,8 @@
     android:layout_width="wrap_content"
     android:layout_height="40dip"
     android:layout_weight="1"
-    android:layout_marginLeft="-4dip"
-    android:layout_marginRight="-4dip"
+    android:layout_marginLeft="-3dip"
+    android:layout_marginRight="-3dip"
     android:minWidth="72dip"
     android:background="@+drawable/tab_indicator_bg">
 
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 892569a..7a5bba8 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -30,4 +30,13 @@
 
     <item type="id" name="dialog_import_export" />
 
+    <!-- For ImportVCardActivity -->
+    <item type="id" name="dialog_sdcard_not_found" />
+    <item type="id" name="dialog_vcard_not_found" />
+    <item type="id" name="dialog_select_import_type" />
+    <item type="id" name="dialog_select_one_vcard" />
+    <item type="id" name="dialog_select_multiple_vcard" />
+    <item type="id" name="dialog_reading_vcard" />
+    <item type="id" name="dialog_io_exception" />
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fcb6d1e..43c1c82 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -344,6 +344,9 @@
     <!-- The group type that displays "Starred in Android" contacts -->
     <string name="starredInAndroid">Starred in Android</string>
 
+    <!-- Displayed in a spinner dialog after the user creates a contact and it's being saved to the database -->
+    <string name="savingContact">Saving contact...</string>
+
     <!-- Toast displayed when a contact is created -->
     <string name="contactCreatedToast">Contact created.</string>
 
diff --git a/src/com/android/contacts/AttachImage.java b/src/com/android/contacts/AttachImage.java
index 8c91722..fd820e2 100644
--- a/src/com/android/contacts/AttachImage.java
+++ b/src/com/android/contacts/AttachImage.java
@@ -17,12 +17,16 @@
 package com.android.contacts;
 
 import android.app.Activity;
+import android.content.ContentUris;
+import android.content.ContentValues;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Bundle;
-import android.provider.Contacts;
-import android.provider.Contacts.People;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.widget.Toast;
 
 import java.io.ByteArrayOutputStream;
 
@@ -42,6 +46,9 @@
 
     }
 
+    /**
+     * Is the raw_contact uri for the contact the user selected
+     */
     Uri mContactUri;
 
     @Override
@@ -52,7 +59,7 @@
             mContactUri = icicle.getParcelable(CONTACT_URI_KEY);
         } else {
             Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
-            intent.setType(People.CONTENT_ITEM_TYPE);
+            intent.setType(Contacts.CONTENT_ITEM_TYPE);
             startActivityForResult(intent, REQUEST_PICK_CONTACT);
         }
     }
@@ -74,7 +81,6 @@
         }
 
         if (requestCode == REQUEST_PICK_CONTACT) {
-            mContactUri = result.getData();
             // A contact was picked. Launch the cropper to get face detection, the right size, etc.
             // TODO: get these values from constants somewhere
             Intent myIntent = getIntent();
@@ -89,6 +95,20 @@
             intent.putExtra("outputY", 96);
             intent.putExtra("return-data", true);
             startActivityForResult(intent, REQUEST_CROP_PHOTO);
+
+            // while they're cropping, convert the contact into a raw_contact
+            final long contactId = ContentUris.parseId(result.getData());
+            final long rawContactId = ContactsUtils.queryForRawContactId(getContentResolver(),
+                    contactId);
+
+            if (rawContactId == -1) {
+                Toast.makeText(this, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show();
+            }
+
+            mContactUri = Uri.withAppendedPath(
+                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+                    RawContacts.Data.CONTENT_DIRECTORY);
+
         } else if (requestCode == REQUEST_CROP_PHOTO) {
             final Bundle extras = result.getExtras();
             if (extras != null) {
@@ -96,8 +116,12 @@
                 if (photo != null) {
                     ByteArrayOutputStream stream = new ByteArrayOutputStream();
                     photo.compress(Bitmap.CompressFormat.JPEG, 75, stream);
-                    Contacts.People.setPhotoData(getContentResolver(), mContactUri,
-                            stream.toByteArray());
+
+                    final ContentValues imageValues = new ContentValues();
+                    imageValues.put(Photo.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
+                    imageValues.put(Photo.PHOTO, stream.toByteArray());
+                    imageValues.put(RawContacts.Data.IS_SUPER_PRIMARY, 1);
+                    getContentResolver().insert(mContactUri, imageValues);
                 }
             }
             finish();
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 5e8519e..970deea 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -16,15 +16,7 @@
 
 package com.android.contacts;
 
-import com.android.contacts.model.ContactsSource;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.model.Sources;
-import com.android.contacts.model.ContactsSource.DataKind;
-import com.android.contacts.model.ContactsSource.EditType;
-import com.android.contacts.ui.DisplayGroupsActivity;
-import com.android.contacts.ui.DisplayGroupsActivity.Prefs;
-import com.android.contacts.util.Constants;
-
+import android.accounts.Account;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -97,17 +89,25 @@
 import android.widget.FasttrackBadgeWidget;
 import android.widget.Filter;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.ResourceCursorAdapter;
 import android.widget.SectionIndexer;
 import android.widget.TextView;
 import android.widget.AbsListView.OnScrollListener;
 
+import com.android.contacts.model.ContactsSource;
+import com.android.contacts.model.Sources;
+import com.android.contacts.model.ContactsSource.DataKind;
+import com.android.contacts.model.ContactsSource.EditType;
+import com.android.contacts.ui.DisplayGroupsActivity;
+import com.android.contacts.ui.DisplayGroupsActivity.Prefs;
+import com.android.contacts.util.Constants;
+
 import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
 
 /*TODO(emillar) I commented most of the code that deals with modes and filtering. It should be
@@ -294,6 +294,8 @@
 
     private static final int QUERY_TOKEN = 42;
 
+    static final String KEY_PICKER_MODE = "picker_mode";
+
     private ContactItemListAdapter mAdapter;
 
     int mMode = MODE_DEFAULT;
@@ -592,11 +594,11 @@
 
     private void setEmptyText() {
         TextView empty = (TextView) findViewById(R.id.emptyText);
-        // Center the text by default
-        int gravity = Gravity.CENTER;
+        int gravity = Gravity.NO_GRAVITY;
 
         if (mDisplayOnlyPhones) {
             empty.setText(getText(R.string.noContactsWithPhoneNumbers));
+            gravity = Gravity.CENTER;
         } else if (mMode == MODE_STREQUENT || mMode == MODE_STARRED) {
             empty.setText(getText(R.string.noFavoritesHelpText));
         } else {
@@ -616,7 +618,6 @@
                     empty.setText(getText(R.string.noContactsNoSimHelpText));
                 }
             }
-            gravity = Gravity.NO_GRAVITY;
         }
         empty.setGravity(gravity);
     }
@@ -785,10 +786,98 @@
             case R.id.dialog_import_export: {
                 return createImportExportDialog();
             }
+            case R.string.import_from_sim:
+            case R.string.import_from_sdcard: {
+                return createSelectAccountDialog(id);
+            }
         }
         return super.onCreateDialog(id);
     }
 
+    private class AccountSelectedListener
+        implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
+
+        final private List<Account> mAccountList;
+        final private int mResId;
+
+        public AccountSelectedListener(List<Account> accountList, int resId) {
+            if (accountList == null || accountList.size() == 0) {
+                // TODO: Add all the contacts into phone-local account.
+                Log.e(TAG, "The size of Account list is 0");
+            }
+            mAccountList = accountList;
+            mResId = resId;
+        }
+
+        public void onClick(DialogInterface dialog, int which) {
+            dialog.dismiss();
+            switch (mResId) {
+                case R.string.import_from_sim: {
+                    doImportFromSim(mAccountList.get(which));
+                    break;
+                }
+                case R.string.import_from_sdcard: {
+                    doImportFromSdCard(mAccountList.get(which));
+                    break;
+                }
+            }
+        }
+
+        public void onCancel(DialogInterface dialog) {
+            dialog.dismiss();
+        }
+    }
+
+    private Dialog createSelectAccountDialog(int resId) {
+        // A lot of codes are copied from EditContactActivity.
+        // TODO: Can we share the logic?
+        final Sources sources = Sources.getInstance(this);
+        final List<Account> accountList = sources.getAccounts(true);
+
+        // Wrap our context to inflate list items using correct theme
+        final Context dialogContext = new ContextThemeWrapper(
+                this, android.R.style.Theme_Light);
+        final LayoutInflater dialogInflater = (LayoutInflater)dialogContext
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final ArrayAdapter<Account> accountAdapter =
+            new ArrayAdapter<Account>(this, android.R.layout.simple_list_item_2, accountList) {
+
+            @Override
+            public View getView(int position, View convertView,
+                    ViewGroup parent) {
+                if (convertView == null) {
+                    convertView = dialogInflater.inflate(
+                            android.R.layout.simple_list_item_2,
+                            parent, false);
+                }
+
+                // TODO: show icon along with title
+                final TextView text1 =
+                        (TextView)convertView.findViewById(android.R.id.text1);
+                final TextView text2 =
+                        (TextView)convertView.findViewById(android.R.id.text2);
+
+                final Account account = this.getItem(position);
+                final ContactsSource source =
+                    sources.getInflatedSource(account.type,
+                            ContactsSource.LEVEL_SUMMARY);
+
+                text1.setText(source.getDisplayLabel(ContactsListActivity.this));
+                text2.setText(account.name);
+
+                return convertView;
+            }
+        };
+
+        AccountSelectedListener listener = new AccountSelectedListener(accountList, resId);
+        final AlertDialog.Builder builder =
+                new AlertDialog.Builder(this)
+                    .setTitle(R.string.dialog_new_contact_account)
+                    .setSingleChoiceItems(accountAdapter, 0, listener)
+                    .setOnCancelListener(listener);
+        return builder.create();
+    }
+
     /**
      * Create a {@link Dialog} that allows the user to pick from a bulk import
      * or bulk export task across all contacts.
@@ -832,12 +921,9 @@
 
                 final int resId = adapter.getItem(which);
                 switch (resId) {
-                    case R.string.import_from_sim: {
-                        doImportFromSim();
-                        break;
-                    }
+                    case R.string.import_from_sim:
                     case R.string.import_from_sdcard: {
-                        doImportFromSdCard();
+                        showDialog(resId);
                         break;
                     }
                     case R.string.export_to_sdcard: {
@@ -855,16 +941,20 @@
         return builder.create();
     }
 
-    private void doImportFromSim() {
+    private void doImportFromSim(Account account) {
         Intent importIntent = new Intent(Intent.ACTION_VIEW);
         importIntent.setType("vnd.android.cursor.item/sim-contact");
+        importIntent.putExtra("account_name", account.name);
+        importIntent.putExtra("account_type", account.type);
         importIntent.setClassName("com.android.phone", "com.android.phone.SimContacts");
         startActivity(importIntent);
     }
 
-    private void doImportFromSdCard() {
-        Intent intent = new Intent(this, ImportVCardActivity.class);
-        startActivity(intent);
+    private void doImportFromSdCard(Account account) {
+        Intent importIntent = new Intent(this, ImportVCardActivity.class);
+        importIntent.putExtra("account_name", account.name);
+        importIntent.putExtra("account_type", account.type);
+        startActivity(importIntent);
     }
 
     private void doExportToSdCard() {
@@ -878,7 +968,6 @@
         switch (requestCode) {
             case SUBACTIVITY_NEW_CONTACT:
                 if (resultCode == RESULT_OK) {
-                    // Contact was created, pass it back
                     returnPickerResult(null, data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME),
                             data.getData(), 0);
                 }
@@ -1040,7 +1129,6 @@
         if (mMode == MODE_INSERT_OR_EDIT_CONTACT) {
             Intent intent;
             if (position == 0) {
-                // Insert
                 intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
             } else {
                 // Edit
@@ -1048,10 +1136,14 @@
                 intent = new Intent(Intent.ACTION_EDIT, uri);
             }
             intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
-            final Bundle extras = getIntent().getExtras();
-            if (extras != null) {
-                intent.putExtras(extras);
+            Bundle extras = getIntent().getExtras();
+
+            if (extras == null) {
+                extras = new Bundle();
             }
+            intent.putExtras(extras);
+            extras.putBoolean(KEY_PICKER_MODE, (mMode & MODE_MASK_PICKER) == MODE_MASK_PICKER);
+
             startActivity(intent);
             finish();
         } else if (id != -1) {
@@ -1094,9 +1186,8 @@
             }
         } else if ((mMode & MODE_MASK_CREATE_NEW) == MODE_MASK_CREATE_NEW
                 && position == 0) {
-            // TODO: Hook this up to new edit contact activity (bug 2092559)
-            /*Intent newContact = new Intent(Intents.Insert.ACTION, People.CONTENT_URI);
-            startActivityForResult(newContact, SUBACTIVITY_NEW_CONTACT);*/
+            Intent newContact = new Intent(Intents.Insert.ACTION, Contacts.CONTENT_URI);
+            startActivityForResult(newContact, SUBACTIVITY_NEW_CONTACT);
         } else {
             signalError();
         }
diff --git a/src/com/android/contacts/ImportVCardActivity.java b/src/com/android/contacts/ImportVCardActivity.java
index c0b7634..ad544c5 100644
--- a/src/com/android/contacts/ImportVCardActivity.java
+++ b/src/com/android/contacts/ImportVCardActivity.java
@@ -19,10 +19,12 @@
 import android.accounts.Account;
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.Dialog;
 import android.app.ProgressDialog;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
 import android.content.DialogInterface.OnCancelListener;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
@@ -43,17 +45,9 @@
 import android.pim.vcard.exception.VCardVersionException;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
+import android.text.TextUtils;
 import android.text.style.RelativeSizeSpan;
 import android.util.Log;
-import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-import com.android.contacts.model.ContactsSource;
-import com.android.contacts.model.Sources;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -103,6 +97,10 @@
 
     private ProgressDialog mProgressDialog;
     private Handler mHandler = new Handler();
+    private Account mAccount;
+
+    private List<VCardFile> mAllVCardFileList;
+    private VCardReadThread mVCardReadThread;
 
     private class CancelListener
         implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
@@ -146,24 +144,18 @@
         private PowerManager.WakeLock mWakeLock;
         private String mCanonicalPath;
 
-        // For reading multiple files.
-        private List<VCardFile> mVCardFileList;
+        private List<VCardFile> mSelectedVCardFileList;
         private List<String> mErrorFileNameList;
 
-        final private Account mAccount;
-        
-        public VCardReadThread(String canonicalPath, Account account) {
+        public VCardReadThread(String canonicalPath) {
             mCanonicalPath = canonicalPath;
-            mVCardFileList = null;
-            mAccount = account;
             init();
         }
 
-        public VCardReadThread(List<VCardFile> vcardFileList, Account account) {
+        public VCardReadThread(final List<VCardFile> selectedVCardFileList) {
             mCanonicalPath = null;
-            mVCardFileList = vcardFileList;
+            mSelectedVCardFileList = selectedVCardFileList;
             mErrorFileNameList = new ArrayList<String>();
-            mAccount = account;
             init();
         }
 
@@ -242,10 +234,10 @@
                 } else {  // Read multiple files.
                     mProgressDialog.setProgressNumberFormat(
                             getString(R.string.reading_vcard_files));
-                    mProgressDialog.setMax(mVCardFileList.size());
+                    mProgressDialog.setMax(mSelectedVCardFileList.size());
                     mProgressDialog.setProgress(0);
                     
-                    for (VCardFile vcardFile : mVCardFileList) {
+                    for (VCardFile vcardFile : mSelectedVCardFileList) {
                         if (mCanceled) {
                             return;
                         }
@@ -286,7 +278,7 @@
                         }
                         
                         mHandler.post(new ErrorDisplayer(
-                                getString(R.string.fail_reason_failed_to_read_files, 
+                                getString(R.string.fail_reason_failed_to_read_files,
                                         builder.toString())));
                     }
                 }
@@ -367,7 +359,7 @@
                 } else {
                     mHandler.post(new ErrorDisplayer(
                             getString(R.string.fail_reason_io_error,
-                                    e.getMessage())));                    
+                                    e.getMessage())));
                 }
                 return false;
             } catch (VCardNotSupportedException e) {
@@ -410,26 +402,20 @@
         public static final int IMPORT_ALL = 2;
         public static final int IMPORT_TYPE_SIZE = 3;
         
-        final private List<VCardFile> mVCardFileList;
-        final private Account mAccount;
         private int mCurrentIndex;
 
-        public ImportTypeSelectedListener(List<VCardFile> vcardFileList, Account account) {
-            mVCardFileList = vcardFileList;
-            mAccount = account;
-        }
-
         public void onClick(DialogInterface dialog, int which) {
             if (which == DialogInterface.BUTTON_POSITIVE) {
                 switch (mCurrentIndex) {
                 case IMPORT_ALL:
-                    importMultipleVCardFromSDCard(mVCardFileList, mAccount);
+                    importMultipleVCardFromSDCard(mAllVCardFileList);
                     break;
                 case IMPORT_MULTIPLE:
-                    showVCardFileSelectDialog(mVCardFileList, mAccount, true);
+                    showDialog(R.id.dialog_select_multiple_vcard);
                     break;
                 default:
-                    showVCardFileSelectDialog(mVCardFileList, mAccount, false);
+                    showDialog(R.id.dialog_select_one_vcard);
+                    break;
                 }
             } else if (which == DialogInterface.BUTTON_NEGATIVE) {
                 finish();
@@ -438,44 +424,13 @@
             }
         }
     }
-
-    private class AccountSelectedListener
-            implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
-
-        final private List<Account> mAccountList;
-        final private List<VCardFile> mVCardFileList;
-
-        public AccountSelectedListener(List<Account> accountList, List<VCardFile> vcardFileList) {
-            if (accountList == null || accountList.size() == 0) {
-                Log.e(LOG_TAG, "The size of Account list is 0");
-            }
-            mAccountList = accountList;
-            mVCardFileList = vcardFileList;
-        }
-
-        public void onClick(DialogInterface dialog, int which) {
-            dialog.dismiss();
-            startVCardSelectAndImport(mVCardFileList, mAccountList.get(which));
-        }
-
-        public void onCancel(DialogInterface dialog) {
-            finish();
-        }
-    }
     
     private class VCardSelectedListener implements
             DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener {
-        final private List<VCardFile> mVCardFileList;
-        final private Account mAccount;
         private int mCurrentIndex;
         private Set<Integer> mSelectedIndexSet;
 
-        public VCardSelectedListener(
-                List<VCardFile> vcardFileList,
-                Account account,
-                boolean multipleSelect) {
-            mVCardFileList = vcardFileList;
-            mAccount = account;
+        public VCardSelectedListener(boolean multipleSelect) {
             mCurrentIndex = 0;
             if (multipleSelect) {
                 mSelectedIndexSet = new HashSet<Integer>();
@@ -486,17 +441,16 @@
             if (which == DialogInterface.BUTTON_POSITIVE) {
                 if (mSelectedIndexSet != null) {
                     List<VCardFile> selectedVCardFileList = new ArrayList<VCardFile>();
-                    int size = mVCardFileList.size();
+                    int size = mAllVCardFileList.size();
                     // We'd like to sort the files by its index, so we do not use Set iterator. 
                     for (int i = 0; i < size; i++) {
                         if (mSelectedIndexSet.contains(i)) {
-                            selectedVCardFileList.add(mVCardFileList.get(i));
+                            selectedVCardFileList.add(mAllVCardFileList.get(i));
                         }
                     }
-                    importMultipleVCardFromSDCard(selectedVCardFileList, mAccount);
+                    importMultipleVCardFromSDCard(selectedVCardFileList);
                 } else {
-                    importOneVCardFromSDCard(mVCardFileList.get(mCurrentIndex).getCanonicalPath(),
-                            mAccount);
+                    importOneVCardFromSDCard(mAllVCardFileList.get(mCurrentIndex).getCanonicalPath());
                 }
             } else if (which == DialogInterface.BUTTON_NEGATIVE) {
                 finish();
@@ -516,7 +470,7 @@
         public void onClick(DialogInterface dialog, int which, boolean isChecked) {
             if (mSelectedIndexSet == null || (mSelectedIndexSet.contains(which) == isChecked)) {
                 Log.e(LOG_TAG, String.format("Inconsist state in index %d (%s)", which,
-                        mVCardFileList.get(which).getCanonicalPath()));
+                        mAllVCardFileList.get(which).getCanonicalPath()));
             } else {
                 onClick(dialog, which);
             }
@@ -532,9 +486,6 @@
         private boolean mGotIOException;
         private File mRootDirectory;
 
-        // null when search operation is canceled.
-        private List<VCardFile> mVCardFileList;
-
         // To avoid recursive link.
         private Set<String> mCheckedPaths;
         private PowerManager.WakeLock mWakeLock;
@@ -547,7 +498,6 @@
             mGotIOException = false;
             mRootDirectory = sdcardDirectory;
             mCheckedPaths = new HashSet<String>();
-            mVCardFileList = new Vector<VCardFile>();
             PowerManager powerManager = (PowerManager)ImportVCardActivity.this.getSystemService(
                     Context.POWER_SERVICE);
             mWakeLock = powerManager.newWakeLock(
@@ -557,6 +507,7 @@
 
         @Override
         public void run() {
+            mAllVCardFileList = new Vector<VCardFile>();
             try {
                 mWakeLock.acquire();
                 getVCardFileRecursively(mRootDirectory);
@@ -569,7 +520,7 @@
             }
 
             if (mCanceled) {
-                mVCardFileList = null;
+                mAllVCardFileList = null;
             }
 
             mProgressDialog.dismiss();
@@ -577,95 +528,23 @@
             if (mGotIOException) {
                 mHandler.post(new Runnable() {
                     public void run() {
-                        String message = (getString(R.string.scanning_sdcard_failed_message,
-                                getString(R.string.fail_reason_io_error)));
-
-                        AlertDialog.Builder builder =
-                            new AlertDialog.Builder(ImportVCardActivity.this)
-                                .setTitle(R.string.scanning_sdcard_failed_title)
-                                .setIcon(android.R.drawable.ic_dialog_alert)
-                                .setMessage(message)
-                                .setOnCancelListener(mCancelListener)
-                                .setPositiveButton(android.R.string.ok, mCancelListener);
-                        builder.show();
+                        showDialog(R.id.dialog_io_exception);
                     }
                 });
             } else if (mCanceled) {
                 finish();
             } else {
-                // TODO: too many nest. Clean up this code...
-                mHandler.post(new Runnable() {
-                    public void run() {
-                        int size = mVCardFileList.size();
-                        final Context context = ImportVCardActivity.this;
-                        if (size == 0) {
-                            String message = (getString(R.string.scanning_sdcard_failed_message,
-                                    getString(R.string.fail_reason_no_vcard_file)));
-
-                            AlertDialog.Builder builder =
-                                new AlertDialog.Builder(context)
-                                    .setTitle(R.string.scanning_sdcard_failed_title)
-                                    .setMessage(message)
-                                    .setOnCancelListener(mCancelListener)
-                                    .setPositiveButton(android.R.string.ok, mCancelListener);
-                            builder.show();
-                            return;
-                        } else {
-                            final Sources sources = Sources.getInstance(context);
-                            final List<Account> accountList = sources.getAccounts(true);
-                            if (accountList == null || accountList.size() == 0) {
-                                startVCardSelectAndImport(mVCardFileList, null);
-                            } else {
-                                // A lot of codes are copied from EditContactActivity.
-                                // TODO: Can we share the logic?
-
-                                // Wrap our context to inflate list items using correct theme
-                                final Context dialogContext = new ContextThemeWrapper(
-                                        context, android.R.style.Theme_Light);
-                                final LayoutInflater dialogInflater = (LayoutInflater)dialogContext
-                                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-                                final ArrayAdapter<Account> accountAdapter =
-                                    new ArrayAdapter<Account>(context,
-                                        android.R.layout.simple_list_item_2, accountList) {
-                                    @Override
-                                    public View getView(int position, View convertView,
-                                            ViewGroup parent) {
-                                        if (convertView == null) {
-                                            convertView = dialogInflater.inflate(
-                                                    android.R.layout.simple_list_item_2,
-                                                    parent, false);
-                                        }
-
-                                        // TODO: show icon along with title
-                                        final TextView text1 =
-                                            (TextView)convertView.findViewById(android.R.id.text1);
-                                        final TextView text2 =
-                                            (TextView)convertView.findViewById(android.R.id.text2);
-
-                                        final Account account = this.getItem(position);
-                                        final ContactsSource source =
-                                            sources.getInflatedSource(account.type,
-                                                    ContactsSource.LEVEL_SUMMARY);
-
-                                        text1.setText(source.getDisplayLabel(context));
-                                        text2.setText(account.name);
-
-                                        return convertView;
-                                    }
-                                };
-
-                                AccountSelectedListener listener =
-                                    new AccountSelectedListener(accountList, mVCardFileList);
-                                final AlertDialog.Builder builder =
-                                    new AlertDialog.Builder(context)
-                                        .setTitle(R.string.dialog_new_contact_account)
-                                        .setSingleChoiceItems(accountAdapter, 0, listener)
-                                        .setOnCancelListener(listener);
-                                builder.show();
-                            }
+                int size = mAllVCardFileList.size();
+                final Context context = ImportVCardActivity.this;
+                if (size == 0) {
+                    mHandler.post(new Runnable() {
+                        public void run() {
+                            showDialog(R.id.dialog_vcard_not_found);
                         }
-                    }
-                });
+                    });
+                } else {
+                    startVCardSelectAndImport();
+                }
             }
         }
 
@@ -693,7 +572,7 @@
                     String fileName = file.getName();
                     VCardFile vcardFile = new VCardFile(
                             fileName, canonicalPath, file.lastModified());
-                    mVCardFileList.add(vcardFile);
+                    mAllVCardFileList.add(vcardFile);
                 }
             }
         }
@@ -709,46 +588,55 @@
         }
     }
 
-    private void startVCardSelectAndImport(final List<VCardFile> vcardFileList,
-            final Account account) {
-        final Context context = ImportVCardActivity.this;
-        final int size = vcardFileList.size();
-        if (context.getResources().getBoolean(
-                R.bool.config_import_all_vcard_from_sdcard_automatically)) {
-            importMultipleVCardFromSDCard(vcardFileList, account);
+    private void startVCardSelectAndImport() {
+        int size = mAllVCardFileList.size();
+        if (getResources().getBoolean(R.bool.config_import_all_vcard_from_sdcard_automatically)) {
+            importMultipleVCardFromSDCard(mAllVCardFileList);
         } else if (size == 1) {
-            importOneVCardFromSDCard(vcardFileList.get(0).getCanonicalPath(), account);
-        } else if (context.getResources().getBoolean(
-                R.bool.config_allow_users_select_all_vcard_import)) {
-            showSelectImportTypeDialog(vcardFileList, account);
+            importOneVCardFromSDCard(mAllVCardFileList.get(0).getCanonicalPath());
+        } else if (getResources().getBoolean(R.bool.config_allow_users_select_all_vcard_import)) {
+            mHandler.post(new Runnable() {
+                public void run() {
+                    showDialog(R.id.dialog_select_import_type);
+                }
+            });
         } else {
-            // Let a user to select one vCard file.
-            showVCardFileSelectDialog(vcardFileList, account, false);
+            mHandler.post(new Runnable() {
+                public void run() {
+                    showDialog(R.id.dialog_select_one_vcard);
+                }
+            });
         }
     }
     
-    private void importOneVCardFromSDCard(final String canonicalPath, Account account) {
-        VCardReadThread thread = new VCardReadThread(canonicalPath, account);
-        showReadingVCardDialog(thread);
-        thread.start();
+    private void importMultipleVCardFromSDCard(final List<VCardFile> selectedVCardFileList) {
+        mHandler.post(new Runnable() {
+            public void run() {
+                mVCardReadThread = new VCardReadThread(selectedVCardFileList);
+                mVCardReadThread.start();
+                showDialog(R.id.dialog_reading_vcard);
+            }
+        });
     }
 
-    private void importMultipleVCardFromSDCard(final List<VCardFile> vcardFileList,
-            final Account account) {
-        VCardReadThread thread = new VCardReadThread(vcardFileList, account);
-        showReadingVCardDialog(thread);
-        thread.start();
+    private void importOneVCardFromSDCard(final String canonicalPath) {
+        mHandler.post(new Runnable() {
+            public void run() {
+                mVCardReadThread = new VCardReadThread(canonicalPath);
+                mVCardReadThread.start();
+                showDialog(R.id.dialog_reading_vcard);
+            }
+        });
     }
 
-    private void showSelectImportTypeDialog(List<VCardFile> vcardFileList, Account account) {
+    private Dialog getSelectImportTypeDialog() {
         DialogInterface.OnClickListener listener =
-            new ImportTypeSelectedListener(vcardFileList, account);
-        AlertDialog.Builder builder =
-            new AlertDialog.Builder(ImportVCardActivity.this)
-                .setTitle(R.string.select_vcard_title)
-                .setPositiveButton(android.R.string.ok, listener)
-                .setOnCancelListener(mCancelListener)
-                .setNegativeButton(android.R.string.cancel, mCancelListener);
+            new ImportTypeSelectedListener();
+        AlertDialog.Builder builder = new AlertDialog.Builder(this)
+            .setTitle(R.string.select_vcard_title)
+            .setPositiveButton(android.R.string.ok, listener)
+            .setOnCancelListener(mCancelListener)
+            .setNegativeButton(android.R.string.cancel, mCancelListener);
 
         String[] items = new String[ImportTypeSelectedListener.IMPORT_TYPE_SIZE];
         items[ImportTypeSelectedListener.IMPORT_ONE] =
@@ -757,16 +645,13 @@
             getString(R.string.import_multiple_vcard_string);
         items[ImportTypeSelectedListener.IMPORT_ALL] =
             getString(R.string.import_all_vcard_string);
-        builder.setSingleChoiceItems(items,
-                ImportTypeSelectedListener.IMPORT_ONE, listener);
-        builder.show();
+        builder.setSingleChoiceItems(items, ImportTypeSelectedListener.IMPORT_ONE, listener);
+        return builder.create();
     }
 
-    private void showVCardFileSelectDialog(
-            List<VCardFile> vcardFileList, Account account, boolean multipleSelect) {
-        int size = vcardFileList.size();
-        VCardSelectedListener listener =
-            new VCardSelectedListener(vcardFileList, account, multipleSelect);
+    private Dialog getVCardFileSelectDialog(boolean multipleSelect) {
+        int size = mAllVCardFileList.size();
+        VCardSelectedListener listener = new VCardSelectedListener(multipleSelect);
         AlertDialog.Builder builder =
             new AlertDialog.Builder(this)
                 .setTitle(R.string.select_vcard_title)
@@ -777,7 +662,7 @@
         CharSequence[] items = new CharSequence[size];
         DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         for (int i = 0; i < size; i++) {
-            VCardFile vcardFile = vcardFileList.get(i);
+            VCardFile vcardFile = mAllVCardFileList.get(i);
             SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
             stringBuilder.append(vcardFile.getName());
             stringBuilder.append('\n');
@@ -797,27 +682,88 @@
         } else {
             builder.setSingleChoiceItems(items, 0, listener);
         }
-        builder.show();
+        return builder.create();
     }
 
-    private void showReadingVCardDialog(DialogInterface.OnCancelListener listener) {
+    private Dialog getReadingVCardDialog() {
         String title = getString(R.string.reading_vcard_title);
         String message = getString(R.string.reading_vcard_message);
         mProgressDialog = new ProgressDialog(this);
         mProgressDialog.setTitle(title);
         mProgressDialog.setMessage(message);
         mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
-        mProgressDialog.setOnCancelListener(listener);
-        mProgressDialog.show();
+        mProgressDialog.setOnCancelListener(mVCardReadThread);
+        return mProgressDialog;
     }
 
     @Override
     protected void onCreate(Bundle bundle) {
         super.onCreate(bundle);
 
+        Intent intent = getIntent();
+        if (intent != null) {
+            final String accountName = intent.getStringExtra("account_name");
+            final String accountType = intent.getStringExtra("account_type");
+            if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
+                mAccount = new Account(accountName, accountType);
+            }
+        } else {
+            Log.e(LOG_TAG, "intent does not exist");
+        }
+
         startImportVCardFromSdCard();
     }
 
+    @Override
+    protected Dialog onCreateDialog(int resId) {
+        switch (resId) {
+            case R.id.dialog_sdcard_not_found: {
+                AlertDialog.Builder builder = new AlertDialog.Builder(this)
+                    .setTitle(R.string.no_sdcard_title)
+                    .setIcon(android.R.drawable.ic_dialog_alert)
+                    .setMessage(R.string.no_sdcard_message)
+                    .setOnCancelListener(mCancelListener)
+                    .setPositiveButton(android.R.string.ok, mCancelListener);
+                return builder.create();
+            }
+            case R.id.dialog_vcard_not_found: {
+                String message = (getString(R.string.scanning_sdcard_failed_message,
+                        getString(R.string.fail_reason_no_vcard_file)));
+                AlertDialog.Builder builder = new AlertDialog.Builder(this)
+                    .setTitle(R.string.scanning_sdcard_failed_title)
+                    .setMessage(message)
+                    .setOnCancelListener(mCancelListener)
+                    .setPositiveButton(android.R.string.ok, mCancelListener);
+                return builder.create();
+            }
+            case R.id.dialog_select_import_type: {
+                return getSelectImportTypeDialog();
+            }
+            case R.id.dialog_select_multiple_vcard: {
+                return getVCardFileSelectDialog(true);
+            }
+            case R.id.dialog_select_one_vcard: {
+                return getVCardFileSelectDialog(false);
+            }
+            case R.id.dialog_reading_vcard: {
+                return getReadingVCardDialog();
+            }
+            case R.id.dialog_io_exception: {
+                String message = (getString(R.string.scanning_sdcard_failed_message,
+                        getString(R.string.fail_reason_io_error)));
+                AlertDialog.Builder builder = new AlertDialog.Builder(this)
+                    .setTitle(R.string.scanning_sdcard_failed_title)
+                    .setIcon(android.R.drawable.ic_dialog_alert)
+                    .setMessage(message)
+                    .setOnCancelListener(mCancelListener)
+                    .setPositiveButton(android.R.string.ok, mCancelListener);
+                return builder.create();
+            }
+        }
+
+        return super.onCreateDialog(resId);
+    }
+
     /**
      * Tries to start importing VCard. If there's no SDCard available,
      * an error dialog is shown. If there is, start scanning using another thread
@@ -827,13 +773,7 @@
     public void startImportVCardFromSdCard() {
         File file = new File("/sdcard");
         if (!file.exists() || !file.isDirectory() || !file.canRead()) {
-            new AlertDialog.Builder(this)
-                    .setTitle(R.string.no_sdcard_title)
-                    .setIcon(android.R.drawable.ic_dialog_alert)
-                    .setMessage(R.string.no_sdcard_message)
-                    .setOnCancelListener(mCancelListener)
-                    .setPositiveButton(android.R.string.ok, mCancelListener)
-                    .show();
+            showDialog(R.id.dialog_sdcard_not_found);
         } else {
             String title = getString(R.string.searching_vcard_title);
             String message = getString(R.string.searching_vcard_message);
diff --git a/src/com/android/contacts/SocialStreamActivity.java b/src/com/android/contacts/SocialStreamActivity.java
deleted file mode 100644
index 2d84df2..0000000
--- a/src/com/android/contacts/SocialStreamActivity.java
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package com.android.contacts;
-
-import com.android.contacts.ui.FastTrackWindow;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.app.ListActivity;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.CommonDataKinds;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Intents;
-import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.SocialContract.Activities;
-import android.text.SpannableStringBuilder;
-import android.text.format.DateUtils;
-import android.text.style.StyleSpan;
-import android.text.style.UnderlineSpan;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Xml;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.OnClickListener;
-import android.widget.CursorAdapter;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.RemoteViews;
-import android.widget.TextView;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-
-public class SocialStreamActivity extends ListActivity implements OnClickListener {
-    private static final String TAG = "SocialStreamActivity";
-
-    private static final String[] PROJ_ACTIVITIES = new String[] {
-        Activities._ID,
-        Activities.RES_PACKAGE,
-        Activities.MIMETYPE,
-        Activities.AUTHOR_CONTACT_ID,
-        RawContacts.CONTACT_ID,
-        Contacts.DISPLAY_NAME,
-        Activities.PUBLISHED,
-        Activities.TITLE,
-        Activities.SUMMARY,
-        Activities.THREAD_PUBLISHED,
-        Activities.LINK,
-        Activities.THUMBNAIL,
-    };
-
-    private static final int COL_ID = 0;
-    private static final int COL_PACKAGE = 1;
-    private static final int COL_MIMETYPE = 2;
-    private static final int COL_AUTHOR_CONTACT_ID = 3;
-    private static final int COL_AGGREGATE_ID = 4;
-    private static final int COL_DISPLAY_NAME = 5;
-    private static final int COL_PUBLISHED = 6;
-    private static final int COL_TITLE = 7;
-    private static final int COL_SUMMARY = 8;
-    private static final int COL_THREAD_PUBLISHED = 9;
-    private static final int COL_LINK = 10;
-    private static final int COL_THUMBNAIL = 11;
-
-    public static final int PHOTO_SIZE = 54;
-    public static final int THUMBNAIL_SIZE = 54;
-
-    private SocialAdapter mAdapter;
-
-    private ListView mListView;
-    private FastTrackWindow mFastTrack;
-    private MappingCache mMappingCache;
-
-    private ContactsCache mContactsCache;
-
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        setContentView(R.layout.social_list);
-
-        mContactsCache = new ContactsCache(this);
-        mMappingCache = MappingCache.createAndFill(this);
-
-        Cursor cursor = managedQuery(Activities.CONTENT_URI, PROJ_ACTIVITIES, null, null);
-        mAdapter = new SocialAdapter(this, cursor, mContactsCache, mMappingCache);
-        mAdapter.setPhotoListener(this);
-
-        setListAdapter(mAdapter);
-
-        mListView = getListView();
-        mFastTrack = new FastTrackWindow(this);
-    }
-
-    /** {@inheritDoc} */
-    public void onClick(View v) {
-        // Clicked on photo, so show fast-track
-        showFastTrack(v, (Long)v.getTag());
-    }
-
-    private int[] mLocation = new int[2];
-    private Rect mRect = new Rect();
-
-    private void showFastTrack(View anchor, long aggId) {
-        Uri aggUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, aggId);
-
-        anchor.getLocationInWindow(mLocation);
-        mRect.left = mLocation[0];
-        mRect.top = mLocation[1];
-        mRect.right = mRect.left + anchor.getWidth();
-        mRect.bottom = mRect.top + anchor.getHeight();
-
-        mFastTrack.dismiss();
-        mFastTrack.show(aggUri, mRect, Intents.MODE_MEDIUM, null);
-    }
-
-    @Override
-    public void onBackPressed() {
-        if (mFastTrack.isShowing()) {
-            // Back key dismisses fast-track when its visible
-            mFastTrack.dismiss();
-        } else {
-            super.onBackPressed();
-        }
-    }
-
-    @Override
-    protected void onListItemClick(ListView l, View v, int position, long id) {
-        Cursor cursor = (Cursor)getListAdapter().getItem(position);
-
-        // TODO check mime type and if it is supported, launch the corresponding app
-        String link = cursor.getString(COL_LINK);
-        if (link == null) {
-            return;
-        }
-        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
-    }
-
-    /**
-     * List adapter for social stream data queried from
-     * {@link Activities#CONTENT_URI}.
-     */
-    private static class SocialAdapter extends CursorAdapter {
-        private final Context mContext;
-        private final LayoutInflater mInflater;
-        private final ContactsCache mContactsCache;
-        private final MappingCache mMappingCache;
-        private final StyleSpan mTextStyleName;
-        private final UnderlineSpan mTextStyleLink;
-        private OnClickListener mPhotoListener;
-        private SpannableStringBuilder mBuilder = new SpannableStringBuilder();
-
-        public static final int TYPE_ACTIVITY = 0;
-        public static final int TYPE_REPLY = 1;
-
-        private static class SocialHolder {
-            ImageView photo;
-            ImageView sourceIcon;
-            TextView content;
-            TextView summary;
-            ImageView thumbnail;
-            TextView published;
-        }
-
-        public SocialAdapter(Context context, Cursor c, ContactsCache contactsCache,
-                MappingCache mappingCache) {
-            super(context, c, true);
-            mContext = context;
-            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            mContactsCache = contactsCache;
-            mMappingCache = mappingCache;
-            mTextStyleName = new StyleSpan(android.graphics.Typeface.BOLD);
-            mTextStyleLink = new UnderlineSpan();
-        }
-
-        public void setPhotoListener(OnClickListener listener) {
-            mPhotoListener = listener;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            return 2;
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            Cursor cursor = (Cursor) getItem(position);
-            return isReply(cursor) ? TYPE_ACTIVITY : TYPE_REPLY;
-        }
-
-        @Override
-        public void bindView(View view, Context context, Cursor cursor) {
-            SocialHolder holder = (SocialHolder)view.getTag();
-
-            long aggId = cursor.getLong(COL_AGGREGATE_ID);
-            long contactId = cursor.getLong(COL_AUTHOR_CONTACT_ID);
-            String name = cursor.getString(COL_DISPLAY_NAME);
-            String title = cursor.getString(COL_TITLE);
-            String summary = cursor.getString(COL_SUMMARY);
-            long published = cursor.getLong(COL_PUBLISHED);
-            byte[] thumbnailBlob = cursor.getBlob(COL_THUMBNAIL);
-
-            // TODO: trigger async query to find actual name and photo instead
-            // of using this lazy caching mechanism
-            Bitmap photo = mContactsCache.getPhoto(contactId);
-            if (photo != null) {
-                holder.photo.setImageBitmap(photo);
-            } else {
-                holder.photo.setImageResource(R.drawable.ic_contact_list_picture);
-            }
-            holder.photo.setTag(aggId);
-
-            mBuilder.clear();
-            mBuilder.append(name);
-            mBuilder.append(" ");
-            mBuilder.append(title);
-            mBuilder.setSpan(mTextStyleName, 0, name.length(), 0);
-            holder.content.setText(mBuilder);
-
-            if (summary == null) {
-                holder.summary.setVisibility(View.GONE);
-            } else {
-                mBuilder.clear();
-                mBuilder.append(summary);
-                mBuilder.setSpan(mTextStyleLink, 0, summary.length(), 0);
-                holder.summary.setText(mBuilder);
-                holder.summary.setVisibility(View.VISIBLE);
-            }
-
-            if (thumbnailBlob != null) {
-                Bitmap thumbnail =
-                        BitmapFactory.decodeByteArray(thumbnailBlob, 0, thumbnailBlob.length);
-                holder.thumbnail.setImageBitmap(thumbnail);
-                holder.thumbnail.setVisibility(View.VISIBLE);
-            } else {
-                holder.thumbnail.setVisibility(View.GONE);
-            }
-
-            CharSequence relativePublished = DateUtils.getRelativeTimeSpanString(published,
-                    System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS);
-            holder.published.setText(relativePublished);
-
-            if (holder.sourceIcon != null) {
-                String packageName = cursor.getString(COL_PACKAGE);
-                String mimeType = cursor.getString(COL_MIMETYPE);
-                Mapping mapping = mMappingCache.findMapping(packageName, mimeType);
-                if (mapping != null && mapping.icon != null) {
-                    holder.sourceIcon.setImageBitmap(mapping.icon);
-                } else {
-                    holder.sourceIcon.setImageDrawable(null);
-                }
-            }
-        }
-
-        @Override
-        public View newView(Context context, Cursor cursor, ViewGroup parent) {
-            View view = mInflater.inflate(
-                    isReply(cursor) ? R.layout.social_list_item_reply : R.layout.social_list_item,
-                    parent, false);
-
-            SocialHolder holder = new SocialHolder();
-            holder.photo = (ImageView) view.findViewById(R.id.photo);
-            holder.sourceIcon = (ImageView) view.findViewById(R.id.sourceIcon);
-            holder.content = (TextView) view.findViewById(R.id.content);
-            holder.summary = (TextView) view.findViewById(R.id.summary);
-            holder.thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
-            holder.published = (TextView) view.findViewById(R.id.published);
-            view.setTag(holder);
-
-            holder.photo.setOnClickListener(mPhotoListener);
-
-            return view;
-        }
-
-        private boolean isReply(Cursor cursor) {
-
-            /*
-             * Comparing the message timestamp to the thread timestamp rather than checking the
-             * in_reply_to field.  The rationale for this approach is that in the case when the
-             * original message to which the reply was posted is missing, we want to display
-             * the message as if it was an original; otherwise it would appear to be a reply
-             * to whatever message preceded it in the list.  In the case when the original message
-             * of the thread is missing, the two timestamps will be the same.
-             */
-            long published = cursor.getLong(COL_PUBLISHED);
-            long threadPublished = cursor.getLong(COL_THREAD_PUBLISHED);
-            return published != threadPublished;
-        }
-    }
-
-    /**
-     * Keep a cache that maps from {@link RawContacts#_ID} to {@link Photo#PHOTO}
-     * values.
-     */
-    private static class ContactsCache {
-        private static final String TAG = "ContactsCache";
-
-        private static final String[] PROJ_DETAILS = new String[] {
-            Data.MIMETYPE,
-            Data.RAW_CONTACT_ID,
-            Photo.PHOTO,
-        };
-
-        private static final int COL_MIMETYPE = 0;
-        private static final int COL_RAW_CONTACT_ID = 1;
-        private static final int COL_PHOTO = 2;
-
-        private HashMap<Long, Bitmap> mPhoto = new HashMap<Long, Bitmap>();
-
-        public ContactsCache(Context context) {
-            Log.d(TAG, "building ContactsCache...");
-
-            ContentResolver resolver = context.getContentResolver();
-            Cursor cursor = resolver.query(Data.CONTENT_URI, PROJ_DETAILS,
-                    Data.MIMETYPE + "=?", new String[] { Photo.CONTENT_ITEM_TYPE }, null);
-
-            while (cursor.moveToNext()) {
-                long contactId = cursor.getLong(COL_RAW_CONTACT_ID);
-                String mimeType = cursor.getString(COL_MIMETYPE);
-                if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    byte[] photoBlob = cursor.getBlob(COL_PHOTO);
-                    Bitmap photo = BitmapFactory.decodeByteArray(photoBlob, 0, photoBlob.length);
-                    photo = Utilities.createBitmapThumbnail(photo, context, PHOTO_SIZE);
-
-                    mPhoto.put(contactId, photo);
-                }
-            }
-
-            cursor.close();
-            Log.d(TAG, "done building ContactsCache");
-        }
-
-        public Bitmap getPhoto(long contactId) {
-            return mPhoto.get(contactId);
-        }
-    }
-
-    /**
-     * Store a mapping from a package name and mime-type pair to a set of
-     * {@link RemoteViews}, default icon, and column to use from the
-     * {@link Data} table to use as a summary.
-     * 
-     * @deprecated use {@link ContactsSource} instead
-     */
-    @Deprecated
-    public static class Mapping {
-        String packageName;
-        String mimeType;
-        String summaryColumn;
-        String detailColumn;
-        int remoteViewsRes;
-        Bitmap icon;
-
-        public Mapping() {
-        }
-
-        public Mapping(String packageName, String mimeType) {
-            this.packageName = packageName;
-            this.mimeType = mimeType;
-        }
-    }
-
-    /**
-     * Store a parsed <code>Mapping</code> object, which maps package and
-     * mime-type combinations to {@link RemoteViews} XML resources, default
-     * icons, and summary columns in the {@link Data} table.
-     * 
-     * @deprecated use {@link Sources} instead
-     */
-    @Deprecated
-    public static class MappingCache extends HashMap<String, Mapping> {
-        private static final String TAG = "MappingCache";
-
-        private static final String TAG_MAPPINGSET = "MappingSet";
-        private static final String TAG_MAPPING = "Mapping";
-
-        private static final String MAPPING_METADATA = "com.android.contacts.stylemap";
-
-
-        /**
-         * Only allow inflating through
-         * {@link MappingCache#createAndFill(Context)}.
-         */
-        private MappingCache() {
-        }
-
-        /**
-         * Add a {@link Mapping} instance to this cache, correctly using
-         * {@link #generateKey(String, String)} when storing.
-         */
-        public void addMapping(Mapping mapping) {
-            String hashKey = generateKey(mapping.packageName, mapping.mimeType);
-            put(hashKey, mapping);
-        }
-
-        /**
-         * Generate a key used internally for mapping a specific package name
-         * and mime-type to a {@link Mapping}.
-         */
-        private String generateKey(String packageName, String mimeType) {
-            return packageName + ";" + mimeType;
-        }
-
-        /**
-         * Find matching mapping for requested package and mime-type. Returns
-         * null if no mapping found.
-         */
-        public Mapping findMapping(String packageName, String mimeType) {
-            // Search for common mapping first
-            final String commonMapping = generateKey(CommonDataKinds.PACKAGE_COMMON, mimeType);
-            if (containsKey(commonMapping)) {
-                return get(commonMapping);
-            }
-
-            // Otherwise search for package-specific mapping
-            final String specificMapping = generateKey(packageName, mimeType);
-            return get(specificMapping);
-        }
-
-        /**
-         * Create a new {@link MappingCache} object and fill by walking across
-         * all packages to find those that provide mappings.
-         */
-        public static MappingCache createAndFill(Context context) {
-            Log.d(TAG, "building mime-type mapping cache...");
-            final PackageManager pm = context.getPackageManager();
-            MappingCache building = new MappingCache();
-            List<ApplicationInfo> installed = pm
-                    .getInstalledApplications(PackageManager.GET_META_DATA);
-            for (ApplicationInfo info : installed) {
-                if (info.metaData != null && info.metaData.containsKey(MAPPING_METADATA)) {
-                    try {
-                        // Found metadata, so clone into their context to
-                        // inflate reference
-                        Context theirContext = context.createPackageContext(info.packageName, 0);
-                        XmlPullParser mappingParser = info.loadXmlMetaData(pm, MAPPING_METADATA);
-                        building.inflateMappings(theirContext, info.uid, info.packageName,
-                                mappingParser);
-                    } catch (NameNotFoundException e) {
-                        Log.w(TAG, "Problem creating context for remote package", e);
-                    } catch (InflateException e) {
-                        Log.w(TAG, "Problem inflating MappingSet from remote package", e);
-                    }
-                }
-            }
-            return building;
-        }
-
-        public static class InflateException extends Exception {
-            public InflateException(String message) {
-                super(message);
-            }
-
-            public InflateException(String message, Throwable throwable) {
-                super(message, throwable);
-            }
-        }
-
-        /**
-         * Inflate a <code>MappingSet</code> from an XML resource, assuming the
-         * given package name as the source.
-         */
-        public void inflateMappings(Context context, int uid, String packageName,
-                XmlPullParser parser) throws InflateException {
-            final AttributeSet attrs = Xml.asAttributeSet(parser);
-            final Resources res = context.getResources();
-
-            try {
-                int type;
-                while ((type = parser.next()) != XmlPullParser.START_TAG
-                        && type != XmlPullParser.END_DOCUMENT) {
-                    // Drain comments and whitespace
-                }
-
-                if (type != XmlPullParser.START_TAG) {
-                    throw new InflateException("No start tag found");
-                }
-
-                if (!TAG_MAPPINGSET.equals(parser.getName())) {
-                    throw new InflateException("Top level element must be MappingSet");
-                }
-
-                // Parse all children actions
-                final int depth = parser.getDepth();
-                while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
-                        && type != XmlPullParser.END_DOCUMENT) {
-                    if (type == XmlPullParser.END_TAG) {
-                        continue;
-                    }
-
-                    if (!TAG_MAPPING.equals(parser.getName())) {
-                        throw new InflateException("Expected Mapping tag");
-                    }
-
-                    // Parse kind, mime-type, and RemoteViews reference
-                    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Mapping);
-
-                    Mapping mapping = new Mapping();
-                    mapping.packageName = packageName;
-                    mapping.mimeType = a.getString(R.styleable.Mapping_mimeType);
-                    mapping.summaryColumn = a.getString(R.styleable.Mapping_summaryColumn);
-                    mapping.detailColumn = a.getString(R.styleable.Mapping_detailColumn);
-                    mapping.remoteViewsRes = a.getResourceId(R.styleable.Mapping_remoteViews, -1);
-
-                    // Read and resize icon if provided
-                    int iconRes = a.getResourceId(R.styleable.Mapping_icon, -1);
-                    if (iconRes != -1) {
-                        mapping.icon = BitmapFactory.decodeResource(res, iconRes);
-                    }
-
-                    addMapping(mapping);
-                    Log.d(TAG, "Added mapping for packageName=" + mapping.packageName
-                            + ", mimetype=" + mapping.mimeType);
-                }
-            } catch (XmlPullParserException e) {
-                throw new InflateException("Problem reading XML", e);
-            } catch (IOException e) {
-                throw new InflateException("Problem reading XML", e);
-            }
-        }
-    }
-
-    /**
-     * Borrowed from Launcher for {@link Bitmap} resizing.
-     */
-    static final class Utilities {
-        private static final Paint sPaint = new Paint();
-        private static final Rect sBounds = new Rect();
-        private static final Rect sOldBounds = new Rect();
-        private static Canvas sCanvas = new Canvas();
-
-        static {
-            sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
-                    Paint.FILTER_BITMAP_FLAG));
-        }
-
-        /**
-         * Returns a Bitmap representing the thumbnail of the specified Bitmap.
-         * The size of the thumbnail is defined by the dimension
-         * android.R.dimen.launcher_application_icon_size. This method is not
-         * thread-safe and should be invoked on the UI thread only.
-         * 
-         * @param bitmap The bitmap to get a thumbnail of.
-         * @param context The application's context.
-         * @return A thumbnail for the specified bitmap or the bitmap itself if
-         *         the thumbnail could not be created.
-         * @deprecated use {@link Bitmap#createScaledBitmap} instead.
-         */
-        @Deprecated
-        static Bitmap createBitmapThumbnail(Bitmap bitmap, Context context, int size) {
-            int width = size;
-            int height = size;
-
-            final int bitmapWidth = bitmap.getWidth();
-            final int bitmapHeight = bitmap.getHeight();
-
-            if (width > 0 && height > 0 && (width < bitmapWidth || height < bitmapHeight)) {
-                final float ratio = (float)bitmapWidth / bitmapHeight;
-
-                if (bitmapWidth > bitmapHeight) {
-                    height = (int)(width / ratio);
-                } else if (bitmapHeight > bitmapWidth) {
-                    width = (int)(height * ratio);
-                }
-
-                final Bitmap.Config c = (width == size && height == size) ? bitmap.getConfig()
-                        : Bitmap.Config.ARGB_8888;
-                final Bitmap thumb = Bitmap.createBitmap(size, size, c);
-                final Canvas canvas = sCanvas;
-                final Paint paint = sPaint;
-                canvas.setBitmap(thumb);
-                paint.setDither(false);
-                paint.setFilterBitmap(true);
-                sBounds.set((size - width) / 2, (size - height) / 2, width, height);
-                sOldBounds.set(0, 0, bitmapWidth, bitmapHeight);
-                canvas.drawBitmap(bitmap, sOldBounds, sBounds, paint);
-                return thumb;
-            }
-
-            return bitmap;
-        }
-    }
-}
diff --git a/src/com/android/contacts/model/EntitySet.java b/src/com/android/contacts/model/EntitySet.java
index 18afd2b..75c9dc3 100644
--- a/src/com/android/contacts/model/EntitySet.java
+++ b/src/com/android/contacts/model/EntitySet.java
@@ -160,7 +160,7 @@
      * existing {@link RawContacts#_ID} value. Usually used when creating
      * {@link AggregationExceptions} during an update.
      */
-    protected long findRawContactId() {
+    public long findRawContactId() {
         for (EntityDelta delta : this) {
             final Long rawContactId = delta.getValues().getAsLong(RawContacts._ID);
             if (rawContactId != null && rawContactId >= 0) {
diff --git a/src/com/android/contacts/model/HardCodedSources.java b/src/com/android/contacts/model/HardCodedSources.java
index b2c0c00..503eed8 100644
--- a/src/com/android/contacts/model/HardCodedSources.java
+++ b/src/com/android/contacts/model/HardCodedSources.java
@@ -16,19 +16,18 @@
 
 package com.android.contacts.model;
 
-import com.android.contacts.R;
-import com.android.contacts.model.ContactsSource.DataKind;
-import com.android.contacts.model.ContactsSource.EditField;
-import com.android.contacts.model.ContactsSource.EditType;
-import com.android.contacts.model.ContactsSource.StringInflater;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.google.android.collect.Lists;
-
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.OperationApplicationException;
 import android.database.Cursor;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
 import android.provider.ContactsContract.Groups;
+import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
 import android.provider.ContactsContract.CommonDataKinds.Im;
@@ -43,6 +42,17 @@
 import android.provider.ContactsContract.Contacts.Data;
 import android.view.inputmethod.EditorInfo;
 
+import com.google.android.collect.Lists;
+
+import com.android.contacts.R;
+import com.android.contacts.model.ContactsSource.DataKind;
+import com.android.contacts.model.ContactsSource.EditField;
+import com.android.contacts.model.ContactsSource.EditType;
+import com.android.contacts.model.ContactsSource.StringInflater;
+import com.android.contacts.model.EntityDelta.ValuesDelta;
+
+import java.util.ArrayList;
+
 /**
  * Hard-coded definition of some {@link ContactsSource} constraints, since the
  * XML language hasn't been finalized.
@@ -465,18 +475,90 @@
     private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts";
 
     public static final void attemptMyContactsMembership(EntityDelta state, Context context) {
-        // TODO: create group when it doesnt exist (syncadapter will fold in)
+        attemptMyContactsMembership(state, context, true);
+    }
+
+    /**
+     *
+     * @param allowRecur If the group is created between querying/about to create, we recur.  But
+     *     to prevent excess recursion, we provide a flag to make sure we only do the recursion loop
+     *     once
+     */
+    private static final void attemptMyContactsMembership(EntityDelta state, Context context,
+            boolean allowRecur) {
         final ContentResolver resolver = context.getContentResolver();
-        final Cursor cursor = resolver.query(Groups.CONTENT_URI, new String[] { Groups.SOURCE_ID },
-                Groups.TITLE + "=?", new String[] { GOOGLE_MY_CONTACTS_GROUP }, null);
-        try {
-            if (cursor.moveToFirst()) {
-                final ContentValues values = new ContentValues();
-                final String sourceId = cursor.getString(0);
-                values.put(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE);
-                values.put(GroupMembership.GROUP_SOURCE_ID, sourceId);
-                state.addEntry(ValuesDelta.fromAfter(values));
+        final ValuesDelta stateValues = state.getValues();
+        final String accountName = stateValues.getAsString(RawContacts.ACCOUNT_NAME);
+        final String accountType = stateValues.getAsString(RawContacts.ACCOUNT_TYPE);
+
+        Cursor cursor = resolver.query(Groups.CONTENT_URI,
+                new String[] {Groups.TITLE, Groups.SOURCE_ID, Groups.SHOULD_SYNC},
+                Groups.ACCOUNT_NAME + " =? AND " + Groups.ACCOUNT_TYPE + " =?",
+                new String[] {accountName, accountType}, null);
+
+        boolean myContactsExists = false;
+        long assignToGroupSourceId = -1;
+        while (cursor.moveToNext()) {
+            if (GOOGLE_MY_CONTACTS_GROUP.equals(cursor.getString(0))) {
+                myContactsExists = true;
             }
+            if (assignToGroupSourceId == -1 && cursor.getInt(2) != 0) {
+                assignToGroupSourceId = cursor.getInt(1);
+            }
+
+            if (myContactsExists && assignToGroupSourceId != -1) {
+                break;
+            }
+        }
+
+        try {
+            final ContentValues values = new ContentValues();
+            values.put(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE);
+
+            if (!myContactsExists) {
+                // create the group if it doesn't exist
+                final ContentValues newGroup = new ContentValues();
+                newGroup.put(Groups.TITLE, GOOGLE_MY_CONTACTS_GROUP);
+
+                newGroup.put(Groups.ACCOUNT_NAME, accountName);
+                newGroup.put(Groups.ACCOUNT_TYPE, accountType);
+                newGroup.put(Groups.GROUP_VISIBLE, "1");
+
+                ArrayList<ContentProviderOperation> operations =
+                    new ArrayList<ContentProviderOperation>();
+
+                operations.add(ContentProviderOperation
+                        .newAssertQuery(Groups.CONTENT_URI)
+                        .withSelection(Groups.TITLE + "=?",
+                                new String[] { GOOGLE_MY_CONTACTS_GROUP })
+                        .withExpectedCount(0).build());
+                operations.add(ContentProviderOperation
+
+                        .newInsert(Groups.CONTENT_URI)
+                        .withValues(newGroup)
+                        .build());
+                try {
+                    ContentProviderResult[] results = resolver.applyBatch(
+                            ContactsContract.AUTHORITY, operations);
+                    values.put(GroupMembership.GROUP_ROW_ID, ContentUris.parseId(results[1].uri));
+                } catch (RemoteException e) {
+                    throw new IllegalStateException("Problem querying for groups", e);
+                } catch (OperationApplicationException e) {
+                    // the group was created after the query but before we tried to create it
+                    if (allowRecur) {
+                        attemptMyContactsMembership(state, context, false);
+                    }
+                    return;
+                }
+            } else {
+                if (assignToGroupSourceId != -1) {
+                    values.put(GroupMembership.GROUP_SOURCE_ID, assignToGroupSourceId);
+                } else {
+                    // there are no Groups to add this contact to, so don't apply any membership
+                    // TODO: alert user that their contact will be dropped?
+                }
+            }
+            state.addEntry(ValuesDelta.fromAfter(values));
         } finally {
             cursor.close();
         }
diff --git a/src/com/android/contacts/ui/EditContactActivity.java b/src/com/android/contacts/ui/EditContactActivity.java
index d9ae717..843615a 100644
--- a/src/com/android/contacts/ui/EditContactActivity.java
+++ b/src/com/android/contacts/ui/EditContactActivity.java
@@ -16,31 +16,14 @@
 
 package com.android.contacts.ui;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.ScrollingTabWidget;
-import com.android.contacts.ViewContactActivity;
-import com.android.contacts.model.ContactsSource;
-import com.android.contacts.model.Editor;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.model.EntitySet;
-import com.android.contacts.model.HardCodedSources;
-import com.android.contacts.model.Sources;
-import com.android.contacts.model.Editor.EditorListener;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.ui.widget.ContactEditorView;
-import com.android.contacts.util.EmptyService;
-import com.android.contacts.util.WeakAsyncTask;
-import com.android.internal.widget.ContactHeaderWidget;
-import com.google.android.collect.Lists;
-
 import android.accounts.Account;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
+import android.app.ProgressDialog;
 import android.content.ActivityNotFoundException;
 import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -74,10 +57,27 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.google.android.collect.Lists;
+
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.ScrollingTabWidget;
+import com.android.contacts.model.ContactsSource;
+import com.android.contacts.model.Editor;
+import com.android.contacts.model.EntityDelta;
+import com.android.contacts.model.EntityModifier;
+import com.android.contacts.model.EntitySet;
+import com.android.contacts.model.HardCodedSources;
+import com.android.contacts.model.Sources;
+import com.android.contacts.model.Editor.EditorListener;
+import com.android.contacts.model.EntityDelta.ValuesDelta;
+import com.android.contacts.ui.widget.ContactEditorView;
+import com.android.contacts.util.EmptyService;
+import com.android.contacts.util.WeakAsyncTask;
+import com.android.internal.widget.ContactHeaderWidget;
+
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
 /**
  * Activity for editing or inserting a contact.
@@ -493,19 +493,6 @@
         return false;
     }
 
-
-
-
-
-
-
-
-
-
-
-
-
-
     /**
      * Background task for persisting edited contact data, using the changes
      * defined by a set of {@link EntityDelta}. This task starts
@@ -520,6 +507,10 @@
         private static final int RESULT_SUCCESS = 1;
         private static final int RESULT_FAILURE = 2;
 
+        private long mSavedId;
+
+        private WeakReference<ProgressDialog> progress;
+
         public PersistTask(EditContactActivity target) {
             super(target);
         }
@@ -527,6 +518,9 @@
         /** {@inheritDoc} */
         @Override
         protected void onPreExecute(EditContactActivity target) {
+            this.progress = new WeakReference<ProgressDialog>(ProgressDialog.show(target, null,
+                    target.getText(R.string.savingContact)));
+
             // Before starting this task, start an empty service to protect our
             // process from being reclaimed by the system.
             final Context context = target;
@@ -552,7 +546,21 @@
                 try {
                     // Build operations and try applying
                     final ArrayList<ContentProviderOperation> diff = state.buildDiff();
-                    resolver.applyBatch(ContactsContract.AUTHORITY, diff);
+                    ContentProviderResult[] results;
+                    if (!diff.isEmpty()) {
+                         results = resolver.applyBatch(ContactsContract.AUTHORITY, diff);
+                         Intent intent = new Intent();
+                         final long rawContactId = getRawContactId(state, diff, results);
+                         final Uri rawContactUri = ContentUris.withAppendedId(
+                                 RawContacts.CONTENT_URI, rawContactId);
+
+                         // convert the raw contact URI to a contact URI
+                         final Uri contactLookupUri = RawContacts.getContactLookupUri(resolver,
+                                 rawContactUri);
+                         intent.setData(contactLookupUri);
+                         target.setResult(RESULT_OK, intent);
+                         target.finish();
+                    }
                     result = (diff.size() > 0) ? RESULT_SUCCESS : RESULT_UNCHANGED;
                     break;
 
@@ -574,6 +582,27 @@
             return result;
         }
 
+        private long getRawContactId(EntitySet state,
+                final ArrayList<ContentProviderOperation> diff,
+                final ContentProviderResult[] results) {
+            long rawContactId = state.findRawContactId();
+            if (rawContactId != -1) {
+                return rawContactId;
+            }
+
+            // we gotta do some searching for the id
+            final int diffSize = diff.size();
+            for (int i = 0; i < diffSize; i++) {
+                ContentProviderOperation operation = diff.get(i);
+                if (operation.getType() == ContentProviderOperation.TYPE_INSERT
+                        && operation.getUri().getEncodedPath().contains(
+                                RawContacts.CONTENT_URI.getEncodedPath())) {
+                    return ContentUris.parseId(results[i].uri);
+                }
+            }
+            return -1;
+        }
+
         /** {@inheritDoc} */
         @Override
         protected void onPostExecute(EditContactActivity target, Integer result) {
@@ -585,48 +614,23 @@
                 Toast.makeText(context, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show();
             }
 
+            progress.get().dismiss();
+            target.finish();
             // Stop the service that was protecting us
             context.stopService(new Intent(context, EmptyService.class));
         }
     }
 
     /**
-     * Timeout for a {@link PersistTask} running on a background thread. This is
-     * just shorter than the ANR timeout, so that we hold off user interaction
-     * as long as possible.
-     */
-    private static final long TIMEOUT_PERSIST = 4000;
-
-    /**
      * Saves or creates the contact based on the mode, and if successful
      * finishes the activity.
      */
     private boolean doSaveAction() {
         if (!hasValidState()) return false;
 
-        // Pass back last-selected contact
-        final Long rawContactId = this.getSelectedRawContactId();
-        if (rawContactId != null) {
-            final Intent intent = new Intent();
-            intent.putExtra(ViewContactActivity.RAW_CONTACT_ID_EXTRA, (long)rawContactId);
-            setResult(RESULT_OK, intent);
-        }
+        final PersistTask task = new PersistTask(this);
+        task.execute(mState);
 
-        try {
-            final PersistTask task = new PersistTask(this);
-            task.execute(mState);
-            task.get(TIMEOUT_PERSIST, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            // Ignore when someone cancels the operation
-        } catch (TimeoutException e) {
-            // Ignore when task is taking too long
-        } catch (ExecutionException e) {
-            // Important exceptions are handled on remote thread
-        }
-
-        // Persisting finished, or we timed out waiting on it. Either way,
-        // finish this activity, the background task will keep running.
-        this.finish();
         return true;
     }
 
diff --git a/src/com/android/contacts/ui/FastTrackWindow.java b/src/com/android/contacts/ui/FastTrackWindow.java
index ba0d912..630ecc4 100644
--- a/src/com/android/contacts/ui/FastTrackWindow.java
+++ b/src/com/android/contacts/ui/FastTrackWindow.java
@@ -251,7 +251,6 @@
 
         setHeaderText(R.id.name, R.string.fasttrack_missing_name);
         setHeaderText(R.id.status, null);
-        setHeaderText(R.id.published, null);
         setHeaderImage(R.id.presence, null);
 
         mHasValidSocial = false;
@@ -481,14 +480,10 @@
         if (cursor == null || !cursor.moveToNext()) return;
 
         final String status = cursor.getString(SocialQuery.TITLE);
-        final long published = cursor.getLong(SocialQuery.PUBLISHED);
-        final CharSequence relativePublished = DateUtils.getRelativeTimeSpanString(published,
-                System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS);
 
         mHasValidSocial = !TextUtils.isEmpty(status);
 
         setHeaderText(R.id.status, status);
-        setHeaderText(R.id.published, relativePublished);
     }
 
     /**