auto import from //branches/cupcake/...@131421
diff --git a/src/com/android/contacts/EditContactActivity.java b/src/com/android/contacts/EditContactActivity.java
index d34713d..c12074e 100644
--- a/src/com/android/contacts/EditContactActivity.java
+++ b/src/com/android/contacts/EditContactActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts;
 
-import com.google.android.collect.Lists;
-
 import static com.android.contacts.ContactEntryAdapter.CONTACT_CUSTOM_RINGTONE_COLUMN;
 import static com.android.contacts.ContactEntryAdapter.CONTACT_NAME_COLUMN;
 import static com.android.contacts.ContactEntryAdapter.CONTACT_NOTES_COLUMN;
@@ -57,6 +55,7 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Bitmap;
@@ -77,11 +76,10 @@
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
-import android.text.method.DialerKeyListener;
 import android.text.method.TextKeyListener;
 import android.text.method.TextKeyListener.Capitalize;
 import android.util.Log;
-import android.view.ContextThemeWrapper;
+import android.util.SparseBooleanArray;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -92,27 +90,21 @@
 import android.view.inputmethod.EditorInfo;
 import android.widget.Button;
 import android.widget.CheckBox;
-import android.widget.CompoundButton;
 import android.widget.EditText;
-import android.widget.ExpandableListView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.SimpleExpandableListAdapter;
 import android.widget.TextView;
 import android.widget.Toast;
 
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 
 /**
  * Activity for editing or inserting a contact. Note that if the contact data changes in the
  * background while this activity is running, the updates will be overwritten.
  */
 public final class EditContactActivity extends Activity implements View.OnClickListener,
-        ExpandableListView.OnChildClickListener, TextWatcher, CheckBox.OnCheckedChangeListener {
+        TextWatcher, View.OnFocusChangeListener {
     private static final String TAG = "EditContactActivity";
 
     private static final int STATE_UNKNOWN = 0;
@@ -127,26 +119,25 @@
     /** The launch code when picking a ringtone */
     private static final int RINGTONE_PICKED = 3023;
     
-    // Label picker position info
-    final static int LABEL_PICKER_PHONES_POSITION = 0;
-    final static int LABEL_PICKER_EMAIL_POSITION = 1;
-    final static int LABEL_PICKER_IM_POSITION = 2;
-    final static int LABEL_PICKER_POSTAL_POSITION = 3;
-    final static int LABEL_PICKER_OTHER_POSITION = 4;
-
     // These correspond to the string array in resources for picker "other" items
     final static int OTHER_ORGANIZATION = 0;
     final static int OTHER_NOTE = 1;
     
     // Dialog IDs
-    final static int LABEL_PICKER_ALL_TYPES_DIALOG = 1;
     final static int DELETE_CONFIRMATION_DIALOG = 2;
+    
+    // Section IDs
+    final static int SECTION_PHONES = 3;
+    final static int SECTION_EMAIL = 4;
+    final static int SECTION_IM = 5;
+    final static int SECTION_POSTAL = 6;
+    final static int SECTION_ORG = 7;
+    final static int SECTION_NOTE = 8;
 
     // Menu item IDs
     public static final int MENU_ITEM_SAVE = 1;
     public static final int MENU_ITEM_DONT_SAVE = 2;
     public static final int MENU_ITEM_DELETE = 3;
-    public static final int MENU_ITEM_ADD = 5;
     public static final int MENU_ITEM_PHOTO = 6;
     
     /** Used to represent an invalid type for a contact entry */
@@ -170,7 +161,6 @@
     
     private EditText mNameView;
     private ImageView mPhotoImageView;
-    private CheckBox mSendToVoicemailCheckBox;
     private LinearLayout mLayout;
     private LayoutInflater mInflater;
     private MenuItem mPhotoMenuItem;
@@ -186,25 +176,62 @@
     /* package */ ArrayList<EditEntry> mEmailEntries = new ArrayList<EditEntry>();
     /* package */ ArrayList<EditEntry> mImEntries = new ArrayList<EditEntry>();
     /* package */ ArrayList<EditEntry> mPostalEntries = new ArrayList<EditEntry>();
+    /* package */ ArrayList<EditEntry> mOrgEntries = new ArrayList<EditEntry>();
+    /* package */ ArrayList<EditEntry> mNoteEntries = new ArrayList<EditEntry>();
     /* package */ ArrayList<EditEntry> mOtherEntries = new ArrayList<EditEntry>();
     /* package */ ArrayList<ArrayList<EditEntry>> mSections = new ArrayList<ArrayList<EditEntry>>();
-
+    
     /* package */ static final int MSG_DELETE = 1;
     /* package */ static final int MSG_CHANGE_LABEL = 2;
     /* package */ static final int MSG_ADD_PHONE = 3;
     /* package */ static final int MSG_ADD_EMAIL = 4;
     /* package */ static final int MSG_ADD_POSTAL = 5;
 
+    private static final int[] TYPE_PRECEDENCE_PHONES = new int[] {
+            Phones.TYPE_MOBILE, Phones.TYPE_HOME, Phones.TYPE_WORK, Phones.TYPE_OTHER
+    };
+    private static final int[] TYPE_PRECEDENCE_METHODS = new int[] {
+            ContactMethods.TYPE_HOME, ContactMethods.TYPE_WORK, ContactMethods.TYPE_OTHER
+    };
+    private static final int[] TYPE_PRECEDENCE_IM = new int[] {
+            ContactMethods.PROTOCOL_GOOGLE_TALK, ContactMethods.PROTOCOL_AIM,
+            ContactMethods.PROTOCOL_MSN, ContactMethods.PROTOCOL_YAHOO,
+            ContactMethods.PROTOCOL_JABBER
+    };
+    private static final int[] TYPE_PRECEDENCE_ORG = new int[] {
+            Organizations.TYPE_WORK, Organizations.TYPE_OTHER
+    };
+
     public void onClick(View v) {
         switch (v.getId()) {
             case R.id.photoImage: {
                 doPickPhotoAction();
                 break;
             }
-
-            case R.id.addMore:
-                doAddAction();
+            
+            case R.id.checkable: {
+                CheckBox checkBox = (CheckBox) v.findViewById(R.id.checkbox);
+                checkBox.toggle();
+                
+                EditEntry entry = findEntryForView(v);
+                entry.data = checkBox.isChecked() ? "1" : "0";
+                
+                mContactChanged = true;
                 break;
+            }
+            
+            case R.id.entry_ringtone: {
+                EditEntry entry = findEntryForView(v);
+                doPickRingtone(entry);
+                break;
+            }
+            
+            case R.id.separator: {
+                // Someone clicked on a section header, so handle add action
+                int sectionType = (Integer) v.getTag();
+                doAddAction(sectionType);
+                break;
+            }
 
             case R.id.saveButton:
                 doSaveAction();
@@ -214,8 +241,7 @@
                 doRevertAction();
                 break;
 
-            case R.id.delete:
-            case R.id.delete2: {
+            case R.id.delete: {
                 EditEntry entry = findEntryForView(v);
                 if (entry != null) {
                     // Clear the text and hide the view so it gets saved properly
@@ -223,6 +249,9 @@
                     entry.view.setVisibility(View.GONE);
                     entry.isDeleted = true;
                 }
+                
+                // Force rebuild of views because section headers might need to change
+                buildViews();
                 break;
             }
 
@@ -238,14 +267,6 @@
                 }
                 break;
             }
-                
-            case R.id.data: {
-                EditEntry entry = findEntryForView(v);
-                if (isRingtoneEntry(entry)) {
-                    doPickRingtone(entry);
-                }
-                break;
-            }
         }
     }
 
@@ -318,13 +339,10 @@
         mNameView = (EditText) findViewById(R.id.name);
         mPhotoImageView = (ImageView) findViewById(R.id.photoImage);
         mPhotoImageView.setOnClickListener(this);
-        mSendToVoicemailCheckBox = (CheckBox) findViewById(R.id.send_to_voicemail);
         mPhoneticNameView = (EditText) findViewById(R.id.phonetic_name);
-
+        
         // Setup the bottom buttons
-        View view = findViewById(R.id.addMore);
-        view.setOnClickListener(this);
-        view = findViewById(R.id.saveButton);
+        View view = findViewById(R.id.saveButton);
         view.setOnClickListener(this);
         view = findViewById(R.id.discardButton);
         view.setOnClickListener(this);
@@ -375,6 +393,8 @@
         mSections.add(mEmailEntries);
         mSections.add(mImEntries);
         mSections.add(mPostalEntries);
+        mSections.add(mOrgEntries);
+        mSections.add(mNoteEntries);
         mSections.add(mOtherEntries);
     }
     
@@ -384,6 +404,8 @@
         outState.putParcelableArrayList("emailEntries", mEmailEntries);
         outState.putParcelableArrayList("imEntries", mImEntries);
         outState.putParcelableArrayList("postalEntries", mPostalEntries);
+        outState.putParcelableArrayList("orgEntries", mOrgEntries);
+        outState.putParcelableArrayList("noteEntries", mNoteEntries);
         outState.putParcelableArrayList("otherEntries", mOtherEntries);
         outState.putInt("state", mState);
         outState.putBoolean("insert", mInsert);
@@ -391,7 +413,6 @@
         outState.putString("name", mNameView.getText().toString());
         outState.putParcelable("photo", mPhoto);
         outState.putBoolean("photoChanged", mPhotoChanged);
-        outState.putBoolean("sendToVoicemail", mSendToVoicemailCheckBox.isChecked());
         outState.putString("phoneticName", mPhoneticNameView.getText().toString());
         outState.putBoolean("contactChanged", mContactChanged);
     }
@@ -402,6 +423,8 @@
         mEmailEntries = inState.getParcelableArrayList("emailEntries");
         mImEntries = inState.getParcelableArrayList("imEntries");
         mPostalEntries = inState.getParcelableArrayList("postalEntries");
+        mOrgEntries = inState.getParcelableArrayList("orgEntries");
+        mNoteEntries = inState.getParcelableArrayList("noteEntries");
         mOtherEntries = inState.getParcelableArrayList("otherEntries");
         setupSections();
 
@@ -418,7 +441,6 @@
             setPhotoPresent(false);
         }
         mPhotoChanged = inState.getBoolean("photoChanged");
-        mSendToVoicemailCheckBox.setChecked(inState.getBoolean("sendToVoicemail"));
         mPhoneticNameView.setText(inState.getString("phoneticName"));
         mContactChanged = inState.getBoolean("contactChanged");
 
@@ -479,10 +501,6 @@
                     .setIcon(android.R.drawable.ic_menu_delete);
         }
 
-        menu.add(0, MENU_ITEM_ADD, 0, R.string.menu_addItem)
-                .setIcon(android.R.drawable.ic_menu_add)
-                .setAlphabeticShortcut('n');
-
         mPhotoMenuItem = menu.add(0, MENU_ITEM_PHOTO, 0, null);
         // Updates the state of the menu item
         setPhotoPresent(mPhotoPresent);
@@ -506,10 +524,6 @@
                 showDialog(DELETE_CONFIRMATION_DIALOG);
                 return true;
     
-            case MENU_ITEM_ADD:
-                doAddAction();
-                return true;
-
             case MENU_ITEM_PHOTO:
                 if (!mPhotoPresent) {
                     doPickPhotoAction();
@@ -521,9 +535,98 @@
 
         return false;
     }
+    
+    /**
+     * Try guessing the next-best type of {@link EditEntry} to insert into the
+     * given list. We walk down the precedence list until we find a type that
+     * doesn't exist yet, or default to the lowest ranking type.
+     */
+    private int guessNextType(ArrayList<EditEntry> entries, int[] precedenceList) {
+        // Keep track of the types we've seen already
+        SparseBooleanArray existAlready = new SparseBooleanArray(entries.size());
+        for (int i = entries.size() - 1; i >= 0; i--) {
+            EditEntry entry = entries.get(i);
+            if (!entry.isDeleted) {
+                existAlready.put(entry.type, true);
+            }
+        }
+        
+        // Pick the first item we haven't seen
+        for (int type : precedenceList) {
+            if (!existAlready.get(type, false)) {
+                return type;
+            }
+        }
+        
+        // Otherwise default to last item
+        return precedenceList[precedenceList.length - 1];
+    }
 
-    private void doAddAction() {
-        showDialog(LABEL_PICKER_ALL_TYPES_DIALOG);
+    private void doAddAction(int sectionType) {
+        EditEntry entry = null;
+        switch (sectionType) {
+            case SECTION_PHONES: {
+                // Try figuring out which type to insert next
+                int nextType = guessNextType(mPhoneEntries, TYPE_PRECEDENCE_PHONES);
+                entry = EditEntry.newPhoneEntry(EditContactActivity.this,
+                        Uri.withAppendedPath(mUri, People.Phones.CONTENT_DIRECTORY),
+                        nextType);
+                mPhoneEntries.add(entry);
+                break;
+            }
+            case SECTION_EMAIL: {
+                // Try figuring out which type to insert next
+                int nextType = guessNextType(mEmailEntries, TYPE_PRECEDENCE_METHODS);
+                entry = EditEntry.newEmailEntry(EditContactActivity.this,
+                        Uri.withAppendedPath(mUri, People.ContactMethods.CONTENT_DIRECTORY),
+                        nextType);
+                mEmailEntries.add(entry);
+                break;
+            }
+            case SECTION_IM: {
+                // Try figuring out which type to insert next
+                int nextType = guessNextType(mImEntries, TYPE_PRECEDENCE_IM);
+                entry = EditEntry.newImEntry(EditContactActivity.this,
+                        Uri.withAppendedPath(mUri, People.ContactMethods.CONTENT_DIRECTORY),
+                        nextType);
+                mImEntries.add(entry);
+                break;
+            }
+            case SECTION_POSTAL: {
+                int nextType = guessNextType(mPostalEntries, TYPE_PRECEDENCE_METHODS);
+                entry = EditEntry.newPostalEntry(EditContactActivity.this,
+                        Uri.withAppendedPath(mUri, People.ContactMethods.CONTENT_DIRECTORY),
+                        nextType);
+                mPostalEntries.add(entry);
+                break;
+            }
+            case SECTION_ORG: {
+                int nextType = guessNextType(mOrgEntries, TYPE_PRECEDENCE_ORG);
+                entry = EditEntry.newOrganizationEntry(EditContactActivity.this,
+                        Uri.withAppendedPath(mUri, Organizations.CONTENT_DIRECTORY),
+                        nextType);
+                mOrgEntries.add(entry);
+                break;
+            }
+            case SECTION_NOTE: {
+                entry = EditEntry.newNotesEntry(EditContactActivity.this, null, mUri);
+                mNoteEntries.add(entry);
+                break;
+            }
+        }
+        
+        // Rebuild the views if needed
+        if (entry != null) {
+            buildViews();
+            mContactChanged = true;
+
+            View dataView = entry.view.findViewById(R.id.data);
+            if (dataView == null) {
+                entry.view.requestFocus();
+            } else {
+                dataView.requestFocus();
+            }
+        }
     }
 
     private void doRevertAction() {
@@ -581,7 +684,7 @@
     }
     
     private void handleRingtonePicked(Uri pickedUri) {
-        EditEntry entry = getRingtoneEntry();
+        EditEntry entry = getOtherEntry(People.CUSTOM_RINGTONE);
         if (entry == null) {
             Log.w(TAG, "Ringtone picked but could not find ringtone entry");
             return;
@@ -610,9 +713,7 @@
             ringtoneName = ringtone.getTitle(this);
         }
         
-        // Build actual "Ringtone: Default" string that is assigned to spinner.
-        String text = getString(R.string.ringtone_spinner, ringtoneName);
-        updateDataView(entry, text);
+        updateDataView(entry, ringtoneName);
     }
     
     private void updateDataView(EditEntry entry, String text) {
@@ -623,9 +724,6 @@
     @Override
     protected Dialog onCreateDialog(int id) {
         switch (id) {
-            case LABEL_PICKER_ALL_TYPES_DIALOG:
-                return createAllTypesPicker();
-
             case DELETE_CONFIRMATION_DIALOG:
                 return new AlertDialog.Builder(EditContactActivity.this)
                         .setTitle(R.string.deleteConfirmation_title)
@@ -668,230 +766,21 @@
             return labelPosition + 1;
         }
     }
-
-    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
-            int childPosition, long id) {
-        EditEntry entry = null;
-
-        // Make the dialog go away
-        dismissDialog(LABEL_PICKER_ALL_TYPES_DIALOG);
-
-        // Create the new entry
-        switch (groupPosition) {
-            case LABEL_PICKER_PHONES_POSITION: {
-                String[] labels = getLabelsForKind(this, Contacts.KIND_PHONE);
-                final int type = getTypeFromLabelPosition(labels, childPosition);
-                entry = EditEntry.newPhoneEntry(EditContactActivity.this,
-                        labels[childPosition], type,
-                        null, Uri.withAppendedPath(mUri, People.Phones.CONTENT_DIRECTORY), 0);
-                if (type == Phones.TYPE_CUSTOM) {
-                    createCustomPicker(entry, mPhoneEntries);
-                    return true;
-                } else {
-                    mPhoneEntries.add(entry);
-                }
-                break;
-            }
-
-            case LABEL_PICKER_EMAIL_POSITION: {
-                String[] labels = getLabelsForKind(this, Contacts.KIND_EMAIL);
-                final int type = getTypeFromLabelPosition(labels, childPosition);
-                entry = EditEntry.newEmailEntry(EditContactActivity.this,
-                        labels[childPosition], type, null,
-                        Uri.withAppendedPath(mUri, People.ContactMethods.CONTENT_DIRECTORY), 0);
-                if (type == ContactMethods.TYPE_CUSTOM) {
-                    createCustomPicker(entry, mEmailEntries);
-                    return true;
-                } else {
-                    mEmailEntries.add(entry);
-                }
-                break;
-            }
-            
-            case LABEL_PICKER_IM_POSITION: {
-                String[] labels = getLabelsForKind(this, Contacts.KIND_IM);
-                entry = EditEntry.newImEntry(EditContactActivity.this,
-                        labels[childPosition], childPosition, null,
-                        Uri.withAppendedPath(mUri, People.ContactMethods.CONTENT_DIRECTORY), 0);
-                mImEntries.add(entry);
-                break;
-            }
-
-            case LABEL_PICKER_POSTAL_POSITION: {
-                String[] labels = getLabelsForKind(this, Contacts.KIND_POSTAL);
-                final int type = getTypeFromLabelPosition(labels, childPosition);
-                entry = EditEntry.newPostalEntry(EditContactActivity.this,
-                        labels[childPosition], type, null,
-                        Uri.withAppendedPath(mUri, People.ContactMethods.CONTENT_DIRECTORY), 0);
-                if (type == ContactMethods.TYPE_CUSTOM) {
-                    createCustomPicker(entry, mPostalEntries);
-                    return true;
-                } else {
-                    mPostalEntries.add(entry);
-                }
-                break;
-            }
-            
-            case LABEL_PICKER_OTHER_POSITION: {
-                switch (childPosition) {
-                    case OTHER_ORGANIZATION:
-                        entry = EditEntry.newOrganizationEntry(EditContactActivity.this,
-                                Uri.withAppendedPath(mUri, Organizations.CONTENT_DIRECTORY),
-                                Organizations.TYPE_WORK);
-                        mOtherEntries.add(entry);
-                        break;
-
-                    case OTHER_NOTE:
-                        entry = EditEntry.newNotesEntry(EditContactActivity.this, null, mUri);
-                        mOtherEntries.add(entry);
-                        break;
-                        
-                    default:
-                        entry = null;
-                }
-                break;
-            }
-
-            default:
-                entry = null;
-        }
-
-        // Rebuild the views if needed
-        if (entry != null) {
-            buildViews();
-            mContactChanged = true;
-
-            View dataView = entry.view.findViewById(R.id.data);
-            if (dataView == null) {
-                entry.view.requestFocus();
-            } else {
-                dataView.requestFocus();
-            }
-        }
-        return true;
-    }
-
-    private EditEntry getRingtoneEntry() {
+    
+    private EditEntry getOtherEntry(String column) {
         for (int i = mOtherEntries.size() - 1; i >= 0; i--) {
             EditEntry entry = mOtherEntries.get(i);
-            if (isRingtoneEntry(entry)) {
+            if (isOtherEntry(entry, column)) {
                 return entry;
             }
         }
         return null;
     }
     
-    private static boolean isRingtoneEntry(EditEntry entry) {
-        return entry != null && entry.column != null && entry.column.equals(People.CUSTOM_RINGTONE);
+    private static boolean isOtherEntry(EditEntry entry, String column) {
+        return entry != null && entry.column != null && entry.column.equals(column);
     }
     
-    private Dialog createAllTypesPicker() {
-        // Setup the adapter
-        List<Map<String, ?>> groupData = Lists.newArrayList();
-        List<List<Map<String, ?>>> childData = Lists.newArrayList();
-        List<Map<String, ?>> children;
-        HashMap<String, CharSequence> curGroupMap;
-        CharSequence[] labels;
-        int labelsSize;
-
-        // Phones
-        curGroupMap = new HashMap<String, CharSequence>();
-        groupData.add(curGroupMap);
-        curGroupMap.put("data", getText(R.string.phoneLabelsGroup));
-
-        labels = getLabelsForKind(this, Contacts.KIND_PHONE);
-        labelsSize = labels.length;
-        children = Lists.newArrayList();
-        for (int i = 0; i < labelsSize; i++) {
-            HashMap<String, CharSequence> curChildMap = new HashMap<String, CharSequence>();
-            children.add(curChildMap);
-            curChildMap.put("data", labels[i]);
-        }
-        childData.add(LABEL_PICKER_PHONES_POSITION, children);
-
-        // Email
-        curGroupMap = new HashMap<String, CharSequence>();
-        groupData.add(curGroupMap);
-        curGroupMap.put("data", getText(R.string.emailLabelsGroup));
-
-        labels = getLabelsForKind(this, Contacts.KIND_EMAIL);
-        labelsSize = labels.length;
-        children = Lists.newArrayList();
-        for (int i = 0; i < labelsSize; i++) {
-            HashMap<String, CharSequence> curChildMap = new HashMap<String, CharSequence>();
-            children.add(curChildMap);
-            curChildMap.put("data", labels[i]);
-        }
-        childData.add(LABEL_PICKER_EMAIL_POSITION, children);
-
-        // IM
-        curGroupMap = new HashMap<String, CharSequence>();
-        groupData.add(curGroupMap);
-        curGroupMap.put("data", getText(R.string.imLabelsGroup));
-
-        labels = getLabelsForKind(this, Contacts.KIND_IM);
-        labelsSize = labels.length;
-        children = Lists.newArrayList();
-        for (int i = 0; i < labelsSize; i++) {
-            HashMap<String, CharSequence> curChildMap = new HashMap<String, CharSequence>();
-            children.add(curChildMap);
-            curChildMap.put("data", labels[i]);
-        }
-        childData.add(LABEL_PICKER_IM_POSITION, children);
-        
-        // Postal
-        curGroupMap = new HashMap<String, CharSequence>();
-        groupData.add(curGroupMap);
-        curGroupMap.put("data", getText(R.string.postalLabelsGroup));
-
-        labels = getLabelsForKind(this, Contacts.KIND_POSTAL);
-        labelsSize = labels.length;
-        children = Lists.newArrayList();
-        for (int i = 0; i < labelsSize; i++) {
-            HashMap<String, CharSequence> curChildMap = new HashMap<String, CharSequence>();
-            children.add(curChildMap);
-            curChildMap.put("data", labels[i]);
-        }
-        childData.add(LABEL_PICKER_POSTAL_POSITION, children);
-
-        // Other
-        curGroupMap = new HashMap<String, CharSequence>();
-        groupData.add(curGroupMap);
-        curGroupMap.put("data", getText(R.string.otherLabelsGroup));
-
-        labels = getLabelsForKind(this, EditEntry.KIND_CONTACT);
-        labelsSize = labels.length;
-        children = Lists.newArrayList();
-        for (int i = 0; i < labelsSize; i++) {
-            HashMap<String, CharSequence> curChildMap = new HashMap<String, CharSequence>();
-            children.add(curChildMap);
-            curChildMap.put("data", labels[i]);
-        }
-        childData.add(LABEL_PICKER_OTHER_POSITION, children);
-
-        // Create the expandable list view
-        ExpandableListView list = new ExpandableListView(new ContextThemeWrapper(this,
-                android.R.style.Theme_Light));
-        list.setOnChildClickListener(this);
-        list.setAdapter(new SimpleExpandableListAdapter(
-                new ContextThemeWrapper(this, android.R.style.Theme_Light),
-                groupData,
-                android.R.layout.simple_expandable_list_item_1,
-                new String[] { "data" },
-                new int[] { android.R.id.text1 },
-                childData,
-                android.R.layout.simple_expandable_list_item_1,
-                new String[] { "data" },
-                new int[] { android.R.id.text1 }
-                ));
-        // This list shouldn't have a color hint since the dialog may be transparent
-        list.setCacheColorHint(0);
-
-        // Create the dialog
-        return new AlertDialog.Builder(this).setView(list).setInverseBackgroundForced(true)
-                .setTitle(R.string.selectLabel).create();
-    }
-
     private void createCustomPicker(final EditEntry entry, final ArrayList<EditEntry> addTo) {
         final EditText label = new EditText(this);
         label.setKeyListener(TextKeyListener.getInstance(false, Capitalize.WORDS));
@@ -952,7 +841,6 @@
         }
         values.put(People.NAME, name);
         values.put(People.PHONETIC_NAME, mPhoneticNameView.getText().toString());
-        values.put(People.SEND_TO_VOICEMAIL, mSendToVoicemailCheckBox.isChecked() ? 1 : 0);
         mResolver.update(mUri, values, null, null);
 
         if (mPhotoChanged) {
@@ -1030,7 +918,6 @@
         }
         values.put(People.NAME, name);
         values.put(People.PHONETIC_NAME, mPhoneticNameView.getText().toString());
-        values.put(People.SEND_TO_VOICEMAIL, mSendToVoicemailCheckBox.isChecked() ? 1 : 0);
 
         // Add the contact to the My Contacts group
         Uri contactUri = People.createPersonInMyContactsGroup(mResolver, values);
@@ -1130,13 +1017,7 @@
             setPhotoPresent(true);
             mPhotoImageView.setImageBitmap(mPhoto);
         }
-
-        // Send to voicemail
-        mSendToVoicemailCheckBox
-                .setChecked(personCursor.getInt(CONTACT_SEND_TO_VOICEMAIL_COLUMN) == 1);
-        mSendToVoicemailCheckBox
-                .setOnCheckedChangeListener(this);
-
+        
         // Organizations
         Uri organizationsUri = Uri.withAppendedPath(mUri, Organizations.CONTENT_DIRECTORY);
         Cursor organizationsCursor = mResolver.query(organizationsUri, ORGANIZATIONS_PROJECTION,
@@ -1154,7 +1035,7 @@
                 // Add an organization entry
                 entry = EditEntry.newOrganizationEntry(this, label, type, company, title, uri, id);
                 entry.isPrimary = organizationsCursor.getLong(ORGANIZATIONS_ISPRIMARY_COLUMN) != 0;
-                mOtherEntries.add(entry);
+                mOrgEntries.add(entry);
             }
             organizationsCursor.close();
         }
@@ -1163,13 +1044,18 @@
         if (!personCursor.isNull(CONTACT_NOTES_COLUMN)) {
             entry = EditEntry.newNotesEntry(this, personCursor.getString(CONTACT_NOTES_COLUMN),
                     mUri);
-            mOtherEntries.add(entry);
+            mNoteEntries.add(entry);
         }
 
         // Ringtone
         entry = EditEntry.newRingtoneEntry(this,
                 personCursor.getString(CONTACT_CUSTOM_RINGTONE_COLUMN), mUri);
         mOtherEntries.add(entry);
+        
+        // Send to voicemail
+        entry = EditEntry.newSendToVoicemailEntry(this,
+                personCursor.getString(CONTACT_SEND_TO_VOICEMAIL_COLUMN), mUri);
+        mOtherEntries.add(entry);
 
         // Phonetic name
         mPhoneticNameView.setText(personCursor.getString(CONTACT_PHONETIC_NAME_COLUMN));
@@ -1327,6 +1213,10 @@
         // Ringtone
         entry = EditEntry.newRingtoneEntry(this, null, mUri);
         mOtherEntries.add(entry);
+        
+        // Send to voicemail
+        entry = EditEntry.newSendToVoicemailEntry(this, "0", mUri);
+        mOtherEntries.add(entry);
     }
 
     private void addFromExtras(Bundle extras, Uri phonesUri, Uri methodsUri) {
@@ -1464,12 +1354,21 @@
         // Remove existing views
         final LinearLayout layout = mLayout;
         layout.removeAllViews();
-
-        buildViewsForSection(layout, mPhoneEntries, R.string.listSeparatorCallNumber_edit);
-        buildViewsForSection(layout, mEmailEntries, R.string.listSeparatorSendEmail_edit);
-        buildViewsForSection(layout, mImEntries, R.string.listSeparatorSendIm_edit);
-        buildViewsForSection(layout, mPostalEntries, R.string.listSeparatorMapAddress_edit);
-        buildViewsForSection(layout, mOtherEntries, R.string.listSeparatorOtherInformation_edit);
+        
+        buildViewsForSection(layout, mPhoneEntries,
+                R.string.listSeparatorCallNumber_edit, SECTION_PHONES);
+        buildViewsForSection(layout, mEmailEntries,
+                R.string.listSeparatorSendEmail_edit, SECTION_EMAIL);
+        buildViewsForSection(layout, mImEntries,
+                R.string.listSeparatorSendIm_edit, SECTION_IM);
+        buildViewsForSection(layout, mPostalEntries,
+                R.string.listSeparatorMapAddress_edit, SECTION_POSTAL);
+        buildViewsForSection(layout, mOrgEntries,
+                R.string.listSeparatorOrganizations, SECTION_ORG);
+        buildViewsForSection(layout, mNoteEntries,
+                R.string.label_notes, SECTION_NOTE);
+        
+        buildOtherViews(layout, mOtherEntries);
     }
 
 
@@ -1480,25 +1379,74 @@
      * @param section the section to build the views for
      */
     private void buildViewsForSection(final LinearLayout layout, ArrayList<EditEntry> section,
-            int separatorResource) {
-        // Build the separator if the section isn't empty
-        if (section.size() > 0) {
-            View separator = mInflater.inflate(R.layout.edit_separator, layout, false);
-            TextView text = (TextView) separator.findViewById(R.id.text);
-            text.setText(getText(separatorResource));
-            layout.addView(separator);
+            int separatorResource, int sectionType) {
+        
+        View divider = mInflater.inflate(R.layout.edit_divider, layout, false);
+        layout.addView(divider);
+        
+        // Count up undeleted children
+        int activeChildren = 0;
+        for (int i = section.size() - 1; i >= 0; i--) {
+            EditEntry entry = section.get(i);
+            if (!entry.isDeleted) {
+                activeChildren++;
+            }
+        }
+        
+        // Build the correct group header based on undeleted children
+        ViewGroup header;
+        if (activeChildren == 0) {
+            header = (ViewGroup) mInflater.inflate(R.layout.edit_separator_alone, layout, false);
+        } else {
+            header = (ViewGroup) mInflater.inflate(R.layout.edit_separator, layout, false);
         }
 
+        // Because we're emulating a ListView, we need to handle focus changes
+        // with some additional logic.
+        header.setOnFocusChangeListener(this);
+        
+        TextView text = (TextView) header.findViewById(R.id.text);
+        text.setText(getText(separatorResource));
+        
+        // Force TextView to always default color if we have children.  This makes sure
+        // we don't change color when parent is pressed.
+        if (activeChildren > 0) {
+            ColorStateList stateList = text.getTextColors();
+            text.setTextColor(stateList.getDefaultColor());
+        }
+
+        View addView = header.findViewById(R.id.separator);
+        addView.setTag(Integer.valueOf(sectionType));
+        addView.setOnClickListener(this);
+        
         // Build views for the current section
         for (EditEntry entry : section) {
             entry.activity = this; // this could be null from when the state is restored
             if (!entry.isDeleted) {
                 View view = buildViewForEntry(entry);
-                layout.addView(view);
+                header.addView(view);
             }
         }
+        
+        layout.addView(header);
     }
+    
+    private void buildOtherViews(final LinearLayout layout, ArrayList<EditEntry> section) {
+        // Build views for the current section, putting a divider between each one
+        for (EditEntry entry : section) {
+            View divider = mInflater.inflate(R.layout.edit_divider, layout, false);
+            layout.addView(divider);
 
+            entry.activity = this; // this could be null from when the state is restored
+            View view = buildViewForEntry(entry);
+            view.setOnClickListener(this);
+            layout.addView(view);
+        }
+        
+        View divider = mInflater.inflate(R.layout.edit_divider, layout, false);
+        layout.addView(divider);
+    }
+    
     /**
      * Builds a view to display an EditEntry.
      * 
@@ -1519,10 +1467,16 @@
         final ViewGroup parent = mLayout;
         View view;
 
+        // Because we're emulating a ListView, we might need to handle focus changes
+        // with some additional logic.
         if (entry.kind == Contacts.KIND_ORGANIZATION) {
             view = mInflater.inflate(R.layout.edit_contact_entry_org, parent, false);
-        } else if (isRingtoneEntry(entry)) {
+        } else if (isOtherEntry(entry, People.CUSTOM_RINGTONE)) {
             view = mInflater.inflate(R.layout.edit_contact_entry_ringtone, parent, false);
+            view.setOnFocusChangeListener(this);
+        } else if (isOtherEntry(entry, People.SEND_TO_VOICEMAIL)) {
+            view = mInflater.inflate(R.layout.edit_contact_entry_voicemail, parent, false);
+            view.setOnFocusChangeListener(this);
         } else if (!entry.isStaticLabel) {
             view = mInflater.inflate(R.layout.edit_contact_entry, parent, false);
         } else {
@@ -1591,15 +1545,20 @@
         // Hook up the delete button
         View delete = view.findViewById(R.id.delete);
         if (delete != null) delete.setOnClickListener(this);
-        View delete2 = view.findViewById(R.id.delete2);
-        if (delete2 != null) delete2.setOnClickListener(this);
         
         return view;
     }
 
     private void fillViewData(final EditEntry entry) {
-        if (isRingtoneEntry(entry)) {
+        if (isOtherEntry(entry, People.CUSTOM_RINGTONE)) {
             updateRingtoneView(entry);
+        } else if (isOtherEntry(entry, People.SEND_TO_VOICEMAIL)) {
+            CheckBox checkBox = (CheckBox) entry.view.findViewById(R.id.checkbox);
+            boolean sendToVoicemail = false;
+            if (entry.data != null) {
+                sendToVoicemail = (Integer.valueOf(entry.data) == 1);
+            }
+            checkBox.setChecked(sendToVoicemail);
         }
     }
     
@@ -1962,6 +1921,23 @@
         }
 
         /**
+         * Create a new send-to-voicemail entry with the given data.
+         */
+        public static final EditEntry newSendToVoicemailEntry(EditContactActivity activity,
+                String data, Uri uri) {
+            EditEntry entry = new EditEntry(activity);
+            entry.label = activity.getString(R.string.actionIncomingCall);
+            entry.data = data;
+            entry.uri = uri;
+            entry.column = People.SEND_TO_VOICEMAIL;
+            entry.kind = KIND_CONTACT;
+            entry.isStaticLabel = true;
+            entry.syncDataWithView = false;
+            entry.lines = -1;
+            return entry;
+        }
+
+        /**
          * Create a new empty email entry
          */
         public static final EditEntry newPhoneEntry(EditContactActivity activity,
@@ -2043,7 +2019,15 @@
         }
 
         /**
-         * Create a new postal address entry with the given data.
+         * Create a new IM address entry
+         */
+        public static final EditEntry newImEntry(EditContactActivity activity,
+                Uri uri, int type) {
+            return newImEntry(activity, null, type, null, uri, 0);
+        }
+
+        /**
+         * Create a new IM address entry with the given data.
          *
          * @param label label for the item, from the db not the display label
          * @param protocol the type used
@@ -2065,7 +2049,7 @@
     }
 
     public void afterTextChanged(Editable s) {
-        // Someone edited a text field, so assume this contact is dirty.
+        // Someone edited a text field, so assume this contact is changed
         mContactChanged = true;
     }
 
@@ -2076,9 +2060,10 @@
     public void onTextChanged(CharSequence s, int start, int before, int count) {
         // Do nothing; editing handled by afterTextChanged()
     }
-
-    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-        // Someone changed a checkbox, so assume this contact is dirty.
-        mContactChanged = true;
+    
+    public void onFocusChange(View v, boolean hasFocus) {
+        // Because we're emulating a ListView, we need to setSelected() for
+        // views as they are focused.
+        v.setSelected(hasFocus);
     }
 }
diff --git a/src/com/android/contacts/TwelveKeyDialer.java b/src/com/android/contacts/TwelveKeyDialer.java
index 1a06026..c80e67b 100644
--- a/src/com/android/contacts/TwelveKeyDialer.java
+++ b/src/com/android/contacts/TwelveKeyDialer.java
@@ -206,7 +206,7 @@
         synchronized (mToneGeneratorLock) {
             if (mToneGenerator == null) {
                 try {
-                    mToneGenerator = new ToneGenerator(AudioManager.STREAM_RING, 
+                    mToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, 
                             TONE_RELATIVE_VOLUME);
                 } catch (RuntimeException e) {
                     Log.w(TAG, "Exception caught while creating local tone generator: " + e);
@@ -379,7 +379,7 @@
         synchronized(mToneGeneratorLock) {
             if (mToneGenerator == null) {
                 try {
-                    mToneGenerator = new ToneGenerator(AudioManager.STREAM_RING, 
+                    mToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, 
                             TONE_RELATIVE_VOLUME);
                 } catch (RuntimeException e) {
                     Log.w(TAG, "Exception caught while creating local tone generator: " + e);