Merge "Options Menu layout changes"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6856452..4c5b19f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -532,16 +532,6 @@
             android:name=".ContactSaveService"
             android:exported="false" />
 
-        <!-- 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" />
-            </intent-filter>
-        </activity>
-
         <!-- Attaches a photo to a contact. Started from external applications -->
         <activity android:name=".activities.AttachPhotoActivity"
             android:label="@string/attach_photo_dialog_title"
diff --git a/res/layout/contact_options.xml b/res/layout/contact_options.xml
deleted file mode 100644
index 5bd8836..0000000
--- a/res/layout/contact_options.xml
+++ /dev/null
@@ -1,31 +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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
->
-
-    <include layout="@layout/preference_with_more_button" android:id="@+id/ringtone" />
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="1dip"
-        android:background="?android:attr/listDivider"
-    />
-    <include layout="@layout/edit_contact_entry_voicemail" android:id="@+id/voicemail"/>
-
-</LinearLayout>
diff --git a/res/menu-sw580dp-w720dp/actions.xml b/res/menu-sw580dp-w720dp/actions.xml
index 604813e..534332c 100644
--- a/res/menu-sw580dp-w720dp/actions.xml
+++ b/res/menu-sw580dp-w720dp/actions.xml
@@ -35,21 +35,25 @@
     <item
         android:id="@+id/menu_contacts_filter"
         android:icon="@drawable/ic_menu_settings_holo_light"
+        android:orderInCategory="1"
         android:title="@string/menu_contacts_filter" />
 
     <item
         android:id="@+id/menu_settings"
         android:icon="@drawable/ic_menu_settings_holo_light"
+        android:orderInCategory="2"
         android:title="@string/menu_settings" />
 
     <item
-        android:id="@+id/menu_accounts"
-        android:icon="@drawable/ic_menu_accounts_holo_light"
-        android:title="@string/menu_accounts" />
-
-    <item
         android:id="@+id/menu_import_export"
         android:icon="@drawable/ic_menu_import_export_holo_light"
+        android:orderInCategory="3"
         android:title="@string/menu_import_export" />
 
+    <item
+        android:id="@+id/menu_accounts"
+        android:icon="@drawable/ic_menu_accounts_holo_light"
+        android:orderInCategory="4"
+        android:title="@string/menu_accounts" />
+
 </menu>
diff --git a/res/menu-sw580dp-w720dp/view_contact.xml b/res/menu-sw580dp-w720dp/view_contact.xml
index 733ab25..0fc918b 100644
--- a/res/menu-sw580dp-w720dp/view_contact.xml
+++ b/res/menu-sw580dp-w720dp/view_contact.xml
@@ -23,18 +23,14 @@
         android:showAsAction="always" />
 
     <item
+        android:id="@+id/menu_delete"
+        android:icon="@drawable/ic_menu_trash_holo_light"
+        android:title="@string/menu_deleteContact" />
+
+    <item
         android:id="@+id/menu_share"
         android:icon="@drawable/ic_menu_share_holo_light"
         android:title="@string/menu_share"
         android:alphabeticShortcut="s" />
 
-    <item
-        android:id="@+id/menu_options"
-        android:icon="@drawable/ic_menu_mark"
-        android:title="@string/menu_contactOptions" />
-
-    <item
-        android:id="@+id/menu_delete"
-        android:icon="@drawable/ic_menu_trash_holo_light"
-        android:title="@string/menu_deleteContact" />
 </menu>
diff --git a/res/menu-sw580dp/actions.xml b/res/menu-sw580dp/actions.xml
index ebe4193..593d693 100644
--- a/res/menu-sw580dp/actions.xml
+++ b/res/menu-sw580dp/actions.xml
@@ -32,24 +32,33 @@
         android:title="@string/menu_new_group_action_bar"
         android:showAsAction="withText" />
 
+    <!-- Added orderInCategory to keep the following buttons at the end of the menu
+         Buttons will be added in the order added/inflated. Ordered buttons will be added
+         at the end according to the orderInCategory. This setup insures that the buttons below
+         will be the last buttons in the menu regardless of how many buttons are added
+    -->
     <item
         android:id="@+id/menu_contacts_filter"
         android:icon="@drawable/ic_menu_settings_holo_light"
+        android:orderInCategory="1"
         android:title="@string/menu_contacts_filter" />
 
     <item
         android:id="@+id/menu_settings"
         android:icon="@drawable/ic_menu_settings_holo_light"
+        android:orderInCategory="2"
         android:title="@string/menu_settings" />
 
     <item
-        android:id="@+id/menu_accounts"
-        android:icon="@drawable/ic_menu_accounts_holo_light"
-        android:title="@string/menu_accounts" />
-
-    <item
         android:id="@+id/menu_import_export"
         android:icon="@drawable/ic_menu_import_export_holo_light"
+        android:orderInCategory="3"
         android:title="@string/menu_import_export" />
 
+    <item
+        android:id="@+id/menu_accounts"
+        android:icon="@drawable/ic_menu_accounts_holo_light"
+        android:orderInCategory="4"
+        android:title="@string/menu_accounts" />
+
 </menu>
diff --git a/res/menu-sw580dp/view_contact.xml b/res/menu-sw580dp/view_contact.xml
index 542cfe3..e4b4b37 100644
--- a/res/menu-sw580dp/view_contact.xml
+++ b/res/menu-sw580dp/view_contact.xml
@@ -22,18 +22,14 @@
         android:alphabeticShortcut="e" />
 
     <item
+        android:id="@+id/menu_delete"
+        android:icon="@drawable/ic_menu_trash_holo_light"
+        android:title="@string/menu_deleteContact" />
+
+    <item
         android:id="@+id/menu_share"
         android:icon="@drawable/ic_menu_share_holo_light"
         android:title="@string/menu_share"
         android:alphabeticShortcut="s" />
 
-    <item
-        android:id="@+id/menu_options"
-        android:icon="@drawable/ic_menu_mark"
-        android:title="@string/menu_contactOptions" />
-
-    <item
-        android:id="@+id/menu_delete"
-        android:icon="@drawable/ic_menu_trash_holo_light"
-        android:title="@string/menu_deleteContact" />
 </menu>
diff --git a/res/menu/actions.xml b/res/menu/actions.xml
index fd2b967..346875b 100644
--- a/res/menu/actions.xml
+++ b/res/menu/actions.xml
@@ -43,13 +43,13 @@
         android:title="@string/menu_settings" />
 
     <item
-        android:id="@+id/menu_accounts"
-        android:icon="@drawable/ic_menu_accounts_holo_light"
-        android:title="@string/menu_accounts" />
-
-    <item
         android:id="@+id/menu_import_export"
         android:icon="@drawable/ic_menu_import_export_holo_light"
         android:title="@string/menu_import_export" />
 
+    <item
+        android:id="@+id/menu_accounts"
+        android:icon="@drawable/ic_menu_accounts_holo_light"
+        android:title="@string/menu_accounts" />
+
 </menu>
diff --git a/res/menu/view_contact.xml b/res/menu/view_contact.xml
index 7cf17d6..17ed7c6 100644
--- a/res/menu/view_contact.xml
+++ b/res/menu/view_contact.xml
@@ -28,12 +28,17 @@
         android:alphabeticShortcut="s" />
 
     <item
-        android:id="@+id/menu_options"
-        android:icon="@drawable/ic_menu_mark"
-        android:title="@string/menu_contactOptions" />
-
-    <item
         android:id="@+id/menu_delete"
         android:icon="@drawable/ic_menu_trash_holo_light"
         android:title="@string/menu_deleteContact" />
+
+    <item
+        android:id="@+id/menu_set_ringtone"
+        android:icon="@drawable/ic_menu_mark"
+        android:title="@string/menu_set_ring_tone" />
+
+    <item
+        android:id="@+id/menu_send_to_voicemail"
+        android:checkable="true"
+        android:title="@string/menu_redirect_calls_to_vm" />
 </menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ee55f88..0fbc6bf 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -176,15 +176,18 @@
     <!-- Toast shown after two contacts have been joined by a user action -->
     <string name="contactsJoinedMessage">Contacts joined</string>
 
-    <!-- Menu item that opens the Options activity for a given contact -->
-    <string name="menu_contactOptions">Options</string>
-
     <!-- Title for the Options activity for a given contact -->
     <string name="contactOptionsTitle">Options</string>
 
     <!-- Confirmation dialog title after users selects to delete a contact. -->
     <string name="deleteConfirmation_title">Delete</string>
 
+    <!-- Menu item that opens the Options activity for a given contact [CHAR LIMIT=15] -->
+    <string name="menu_set_ring_tone">Set ringtone</string>
+
+    <!-- Menu item that opens the Options activity for a given contact [CHAR LIMIT=30] -->
+    <string name="menu_redirect_calls_to_vm">Redirect calls to voicemail</string>
+
     <!-- Warning dialog contents after users selects to delete a ReadOnly contact. -->
     <string name="readOnlyContactWarning">You cannot delete contacts from read-only accounts, but you can hide them in your contacts lists.</string>
 
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index 3463d3c..f2a9d13 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -126,6 +126,8 @@
 
         private boolean mLoadingPhoto;
         private byte[] mPhotoBinaryData;
+        private boolean mSendToVoicemail;
+        private String mCustomRingtone;
 
         /**
          * Constructor for case "no contact found". This must only be used for the
@@ -150,6 +152,8 @@
             mStarred = false;
             mPresence = null;
             mInvitableAccountTypes = null;
+            mSendToVoicemail = false;
+            mCustomRingtone = null;
         }
 
         /**
@@ -158,7 +162,7 @@
         private Result(Uri uri, Uri lookupUri, long directoryId, String lookupKey, long id,
                 long nameRawContactId, int displayNameSource, long photoId, String photoUri,
                 String displayName, String altDisplayName, String phoneticName, boolean starred,
-                Integer presence) {
+                Integer presence, boolean sendToVoicemail, String customRingtone) {
             mLookupUri = lookupUri;
             mUri = uri;
             mDirectoryId = directoryId;
@@ -177,6 +181,8 @@
             mStarred = starred;
             mPresence = presence;
             mInvitableAccountTypes = Lists.newArrayList();
+            mSendToVoicemail = sendToVoicemail;
+            mCustomRingtone = customRingtone;
         }
 
         private Result(Result from) {
@@ -209,6 +215,8 @@
 
             mLoadingPhoto = from.mLoadingPhoto;
             mPhotoBinaryData = from.mPhotoBinaryData;
+            mSendToVoicemail = from.mSendToVoicemail;
+            mCustomRingtone = from.mCustomRingtone;
         }
 
         /**
@@ -378,6 +386,14 @@
         public List<GroupMetaData> getGroupMetaData() {
             return mGroups;
         }
+
+        public boolean isSendToVoicemail() {
+            return mSendToVoicemail;
+        }
+
+        public String getCustomRingtone() {
+            return mCustomRingtone;
+        }
     }
 
     /**
@@ -451,6 +467,8 @@
                 Data.STATUS_TIMESTAMP,
 
                 Contacts.PHOTO_URI,
+                Contacts.SEND_TO_VOICEMAIL,
+                Contacts.CUSTOM_RINGTONE,
         };
 
         public final static int NAME_RAW_CONTACT_ID = 0;
@@ -518,6 +536,8 @@
         public final static int STATUS_TIMESTAMP = 58;
 
         public final static int PHOTO_URI = 59;
+        public final static int SEND_TO_VOICEMAIL = 60;
+        public final static int CUSTOM_RINGTONE = 61;
     }
 
     /**
@@ -778,6 +798,8 @@
             final Integer presence = cursor.isNull(ContactQuery.CONTACT_PRESENCE)
                     ? null
                     : cursor.getInt(ContactQuery.CONTACT_PRESENCE);
+            final boolean sendToVoicemail = cursor.getInt(ContactQuery.SEND_TO_VOICEMAIL) == 1;
+            final String customRingtone = cursor.getString(ContactQuery.CUSTOM_RINGTONE);
 
             Uri lookupUri;
             if (directoryId == Directory.DEFAULT || directoryId == Directory.LOCAL_INVISIBLE) {
@@ -789,7 +811,8 @@
 
             return new Result(contactUri, lookupUri, directoryId, lookupKey, contactId,
                     nameRawContactId, displayNameSource, photoId, photoUri, displayName,
-                    altDisplayName, phoneticName, starred, presence);
+                    altDisplayName, phoneticName, starred, presence, sendToVoicemail,
+                    customRingtone);
         }
 
         /**
diff --git a/src/com/android/contacts/ContactOptionsActivity.java b/src/com/android/contacts/ContactOptionsActivity.java
deleted file mode 100644
index dd7387f..0000000
--- a/src/com/android/contacts/ContactOptionsActivity.java
+++ /dev/null
@@ -1,238 +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.activities.PeopleActivity;
-
-import android.app.ActionBar;
-import android.app.Activity;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.database.Cursor;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
-import android.util.Log;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.TextView;
-
-/**
- * An activity for selecting options for a given contact: custom ringtone and send-to-voicemail.
- */
-public class ContactOptionsActivity extends Activity implements View.OnClickListener {
-
-    private static final String TAG = "ContactOptionsActivity";
-
-    private static final String[] AGGREGATES_PROJECTION = new String[] {
-            Contacts.CUSTOM_RINGTONE, Contacts.SEND_TO_VOICEMAIL
-    };
-
-    private static final int COL_CUSTOM_RINGTONE = 0;
-    private static final int COL_SEND_TO_VOICEMAIL = 1;
-
-    /** The launch code when picking a ringtone */
-    private static final int RINGTONE_PICKED = 3023;
-
-    private String mCustomRingtone;
-    private boolean mSendToVoicemail;
-    private TextView mRingtoneTitle;
-    private CheckBox mSendToVoicemailCheckbox;
-
-    private Uri mLookupUri;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mLookupUri = getIntent().getData();
-
-        setContentView(R.layout.contact_options);
-
-        View ringtoneLayout = findViewById(R.id.ringtone);
-        ringtoneLayout.setFocusable(true);
-        ringtoneLayout.setOnClickListener(this);
-        TextView label = (TextView)findViewById(R.id.label);
-        label.setText(getString(R.string.label_ringtone));
-
-        mRingtoneTitle = (TextView)ringtoneLayout.findViewById(R.id.data);
-
-        View sendToVoicemailLayout = findViewById(R.id.voicemail);
-        sendToVoicemailLayout.setOnClickListener(this);
-        label = (TextView)sendToVoicemailLayout.findViewById(R.id.label);
-        label.setText(getString(R.string.actionIncomingCall));
-
-        ActionBar actionBar =  getActionBar();
-        if (actionBar != null) {
-            actionBar.setDisplayHomeAsUpEnabled(true);
-        }
-
-        mSendToVoicemailCheckbox = (CheckBox)sendToVoicemailLayout.findViewById(R.id.checkbox);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        if (!loadData()) {
-            finish();
-        }
-
-        updateView();
-    }
-
-    private void updateView() {
-        if (mCustomRingtone == null) {
-            mRingtoneTitle.setText(getString(R.string.default_ringtone));
-        } else {
-            Uri ringtoneUri = Uri.parse(mCustomRingtone);
-            Ringtone ringtone = RingtoneManager.getRingtone(this, ringtoneUri);
-            if (ringtone == null) {
-                Log.w(TAG, "ringtone's URI doesn't resolve to a Ringtone");
-                return;
-            }
-            mRingtoneTitle.setText(ringtone.getTitle(this));
-        }
-
-        mSendToVoicemailCheckbox.setChecked(mSendToVoicemail);
-    }
-
-    public void onClick(View v) {
-        switch (v.getId()) {
-            case R.id.ringtone: {
-                doPickRingtone();
-                break;
-            }
-            case R.id.voicemail: {
-                doToggleSendToVoicemail();
-                break;
-            }
-        }
-    }
-
-    private void doPickRingtone() {
-
-        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
-        // Allow user to pick 'Default'
-        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
-        // Show only ringtones
-        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);
-        // Don't show 'Silent'
-        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
-
-        Uri ringtoneUri;
-        if (mCustomRingtone != null) {
-            ringtoneUri = Uri.parse(mCustomRingtone);
-        } else {
-            // Otherwise pick default ringtone Uri so that something is selected.
-            ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
-        }
-
-        // Put checkmark next to the current ringtone for this contact
-        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri);
-
-        // Launch!
-        startActivityForResult(intent, RINGTONE_PICKED);
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (resultCode != RESULT_OK) {
-            return;
-        }
-
-        switch (requestCode) {
-            case RINGTONE_PICKED: {
-                Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
-                handleRingtonePicked(pickedUri);
-                break;
-            }
-        }
-    }
-
-    private void handleRingtonePicked(Uri pickedUri) {
-        if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) {
-            mCustomRingtone = null;
-        } else {
-            mCustomRingtone = pickedUri.toString();
-        }
-        saveData();
-        updateView();
-    }
-
-    private void doToggleSendToVoicemail() {
-        mSendToVoicemailCheckbox.toggle();
-        mSendToVoicemail = mSendToVoicemailCheckbox.isChecked();
-        saveData();
-        updateView();
-    }
-
-    private boolean loadData() {
-        Cursor c =
-                getContentResolver().query(mLookupUri, AGGREGATES_PROJECTION, null, null, null);
-        try {
-            if (!c.moveToFirst()) {
-                return false;
-            }
-
-            mCustomRingtone = c.getString(COL_CUSTOM_RINGTONE);
-            mSendToVoicemail = c.getInt(COL_SEND_TO_VOICEMAIL) != 0;
-
-        } finally {
-            c.close();
-        }
-        return true;
-    }
-
-    private void saveData() {
-        ContentValues values = new ContentValues(2);
-        values.put(Contacts.CUSTOM_RINGTONE, mCustomRingtone);
-        values.put(Contacts.SEND_TO_VOICEMAIL, mSendToVoicemail);
-        getContentResolver().update(mLookupUri, values, null, null);
-    }
-
-    @Override
-    public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
-            boolean globalSearch) {
-        if (globalSearch) {
-            super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
-        } else {
-            ContactsSearchManager.startSearch(this, initialQuery);
-        }
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-
-        switch (item.getItemId()) {
-            case android.R.id.home:
-                Intent intent = new Intent(this, PeopleActivity.class);
-                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                startActivity(intent);
-                finish();
-                return true;
-            default:
-                break;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-}
-
-
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index 775009e..e2ab6b0 100644
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -98,6 +98,12 @@
     public static final String EXTRA_CONTACT_ID2 = "contactId2";
     public static final String EXTRA_CONTACT_WRITABLE = "contactWritable";
 
+    public static final String ACTION_SET_SEND_TO_VOICEMAIL = "sendToVoicemail";
+    public static final String EXTRA_SEND_TO_VOICEMAIL_FLAG = "sendToVoicemailFlag";
+
+    public static final String ACTION_SET_RINGTONE = "setRingtone";
+    public static final String EXTRA_CUSTOM_RINGTONE = "customRingtone";
+
     private static final HashSet<String> ALLOWED_DATA_COLUMNS = Sets.newHashSet(
         Data.MIMETYPE,
         Data.IS_PRIMARY,
@@ -185,6 +191,10 @@
             deleteContact(intent);
         } else if (ACTION_JOIN_CONTACTS.equals(action)) {
             joinContacts(intent);
+        } else if (ACTION_SET_SEND_TO_VOICEMAIL.equals(action)) {
+            setSendToVoicemail(intent);
+        } else if (ACTION_SET_RINGTONE.equals(action)) {
+            setRingtone(intent);
         }
     }
 
@@ -382,6 +392,7 @@
      * @param callbackActivity is the activity to send the callback intent to
      * @param callbackAction is the intent action for the callback intent
      */
+
     public static Intent createNewGroupIntent(Context context, Account account,
             String label, long[] rawContactsToAdd, Class<?> callbackActivity,
             String callbackAction) {
@@ -657,6 +668,57 @@
     }
 
     /**
+     * Creates an intent that can be sent to this service to set the redirect to voicemail.
+     */
+    public static Intent createSetSendToVoicemail(Context context, Uri contactUri,
+            boolean value) {
+        Intent serviceIntent = new Intent(context, ContactSaveService.class);
+        serviceIntent.setAction(ContactSaveService.ACTION_SET_SEND_TO_VOICEMAIL);
+        serviceIntent.putExtra(ContactSaveService.EXTRA_CONTACT_URI, contactUri);
+        serviceIntent.putExtra(ContactSaveService.EXTRA_SEND_TO_VOICEMAIL_FLAG, value);
+
+        return serviceIntent;
+    }
+
+    private void setSendToVoicemail(Intent intent) {
+        Uri contactUri = intent.getParcelableExtra(EXTRA_CONTACT_URI);
+        boolean value = intent.getBooleanExtra(EXTRA_SEND_TO_VOICEMAIL_FLAG, false);
+        if (contactUri == null) {
+            Log.e(TAG, "Invalid arguments for setRedirectToVoicemail");
+            return;
+        }
+
+        final ContentValues values = new ContentValues(1);
+        values.put(Contacts.SEND_TO_VOICEMAIL, value);
+        getContentResolver().update(contactUri, values, null, null);
+    }
+
+    /**
+     * Creates an intent that can be sent to this service to save the contact's ringtone.
+     */
+    public static Intent createSetRingtone(Context context, Uri contactUri,
+            String value) {
+        Intent serviceIntent = new Intent(context, ContactSaveService.class);
+        serviceIntent.setAction(ContactSaveService.ACTION_SET_RINGTONE);
+        serviceIntent.putExtra(ContactSaveService.EXTRA_CONTACT_URI, contactUri);
+        serviceIntent.putExtra(ContactSaveService.EXTRA_CUSTOM_RINGTONE, value);
+
+        return serviceIntent;
+    }
+
+    private void setRingtone(Intent intent) {
+        Uri contactUri = intent.getParcelableExtra(EXTRA_CONTACT_URI);
+        String value = intent.getStringExtra(EXTRA_CUSTOM_RINGTONE);
+        if (contactUri == null) {
+            Log.e(TAG, "Invalid arguments for setRingtone");
+            return;
+        }
+        ContentValues values = new ContentValues(1);
+        values.put(Contacts.CUSTOM_RINGTONE, value);
+        getContentResolver().update(contactUri, values, null, null);
+    }
+
+    /**
      * Creates an intent that sets the selected data item as super primary (default)
      */
     public static Intent createSetSuperPrimaryIntent(Context context, long dataId) {
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index a1fd506..6a0d7ad 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -1283,14 +1283,18 @@
         if (mActionBarAdapter.isSearchMode()) {
             addContactMenu.setVisible(false);
             addGroupMenu.setVisible(false);
+            contactsFilterMenu.setVisible(false);
         } else {
             switch (mActionBarAdapter.getCurrentTab()) {
                 case FAVORITES:
-                    // TODO: Fall through until we determine what the menu items should be for
-                    // this tab
+                    addContactMenu.setVisible(false);
+                    addGroupMenu.setVisible(false);
+                    contactsFilterMenu.setVisible(false);
+                    break;
                 case ALL:
                     addContactMenu.setVisible(true);
                     addGroupMenu.setVisible(false);
+                    contactsFilterMenu.setVisible(true);
                     break;
                 case GROUPS:
                     // Do not display the "new group" button if no accounts are available
@@ -1300,6 +1304,7 @@
                         addGroupMenu.setVisible(false);
                     }
                     addContactMenu.setVisible(false);
+                    contactsFilterMenu.setVisible(false);
                     break;
             }
         }
@@ -1309,9 +1314,6 @@
             searchMenu.setVisible(!mActionBarAdapter.isSearchMode());
         }
 
-        if (contactsFilterMenu != null) {
-            contactsFilterMenu.setVisible(!mActionBarAdapter.isSearchMode());
-        }
 
         MenuItem settings = menu.findItem(R.id.menu_settings);
         if (settings != null) {
diff --git a/src/com/android/contacts/detail/ContactLoaderFragment.java b/src/com/android/contacts/detail/ContactLoaderFragment.java
index 9085670..8d3cd75 100644
--- a/src/com/android/contacts/detail/ContactLoaderFragment.java
+++ b/src/com/android/contacts/detail/ContactLoaderFragment.java
@@ -17,8 +17,9 @@
 package com.android.contacts.detail;
 
 import com.android.contacts.ContactLoader;
-import com.android.contacts.ContactOptionsActivity;
+import com.android.contacts.ContactSaveService;
 import com.android.contacts.R;
+import com.android.contacts.activities.ContactDetailActivity;
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
 import com.android.contacts.util.PhoneCapabilityTester;
 import com.android.internal.util.Objects;
@@ -28,9 +29,11 @@
 import android.app.LoaderManager;
 import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ActivityNotFoundException;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Loader;
+import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.ContactsContract.Contacts;
@@ -52,9 +55,15 @@
 
     private static final String TAG = ContactLoaderFragment.class.getSimpleName();
 
+    /** The launch code when picking a ringtone */
+    private static final int REQUEST_CODE_PICK_RINGTONE = 1;
+
+
     private boolean mOptionsMenuOptions;
     private boolean mOptionsMenuEditable;
     private boolean mOptionsMenuShareable;
+    private boolean mSendToVoicemailState;
+    private String mCustomRingtone;
 
     /**
      * This is a listener to the {@link ContactLoaderFragment} and will be notified when the
@@ -194,6 +203,8 @@
                     mListener.onDetailsLoaded(mContactData);
                 }
             }
+            // Make sure the options menu is setup correctly with the loaded data.
+            getActivity().invalidateOptionsMenu();
         }
 
         @Override
@@ -222,11 +233,22 @@
         mOptionsMenuOptions = isContactOptionsChangeEnabled();
         mOptionsMenuEditable = isContactEditable();
         mOptionsMenuShareable = isContactShareable();
+        if (mContactData != null) {
+            mSendToVoicemailState = mContactData.isSendToVoicemail();
+            mCustomRingtone = mContactData.getCustomRingtone();
+        }
 
-        // Options only shows telephony-related settings (ringtone, send to voicemail).
-        // ==> Hide if we don't have a telephone
-        final MenuItem optionsMenu = menu.findItem(R.id.menu_options);
-        optionsMenu.setVisible(mOptionsMenuOptions);
+        // Hide telephony-related settings (ringtone, send to voicemail)
+        // if we don't have a telephone
+        final MenuItem optionsSendToVoicemail = menu.findItem(R.id.menu_send_to_voicemail);
+        if (optionsSendToVoicemail != null) {
+            optionsSendToVoicemail.setChecked(mSendToVoicemailState);
+            optionsSendToVoicemail.setVisible(mOptionsMenuOptions);
+        }
+        final MenuItem optionsRingtone = menu.findItem(R.id.menu_set_ringtone);
+        if (optionsRingtone != null) {
+            optionsRingtone.setVisible(mOptionsMenuOptions);
+        }
 
         final MenuItem editMenu = menu.findItem(R.id.menu_edit);
         editMenu.setVisible(mOptionsMenuEditable);
@@ -262,11 +284,9 @@
                 if (mListener != null) mListener.onDeleteRequested(mLookupUri);
                 return true;
             }
-            case R.id.menu_options: {
+            case R.id.menu_set_ringtone: {
                 if (mContactData == null) return false;
-                final Intent intent = new Intent(mContext, ContactOptionsActivity.class);
-                intent.setData(mContactData.getLookupUri());
-                mContext.startActivity(intent);
+                doPickRingtone();
                 return true;
             }
             case R.id.menu_share: {
@@ -290,6 +310,15 @@
                 }
                 return true;
             }
+            case R.id.menu_send_to_voicemail: {
+                // Update state and save
+                mSendToVoicemailState = !mSendToVoicemailState;
+                item.setChecked(mSendToVoicemailState);
+                Intent intent = ContactSaveService.createSetSendToVoicemail(
+                        mContext, mLookupUri, mSendToVoicemailState);
+                mContext.startService(intent);
+                return true;
+            }
         }
         return false;
     }
@@ -304,4 +333,55 @@
         }
         return false;
     }
+
+    private void doPickRingtone() {
+
+        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
+        // Allow user to pick 'Default'
+        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
+        // Show only ringtones
+        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);
+        // Don't show 'Silent'
+        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
+
+        Uri ringtoneUri;
+        if (mCustomRingtone != null) {
+            ringtoneUri = Uri.parse(mCustomRingtone);
+        } else {
+            // Otherwise pick default ringtone Uri so that something is selected.
+            ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+        }
+
+        // Put checkmark next to the current ringtone for this contact
+        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri);
+
+        // Launch!
+        startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE);
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (resultCode != Activity.RESULT_OK) {
+            return;
+        }
+
+        switch (requestCode) {
+            case REQUEST_CODE_PICK_RINGTONE: {
+                Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
+                handleRingtonePicked(pickedUri);
+                break;
+            }
+        }
+    }
+
+    private void handleRingtonePicked(Uri pickedUri) {
+        if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) {
+            mCustomRingtone = null;
+        } else {
+            mCustomRingtone = pickedUri.toString();
+        }
+        Intent intent = ContactSaveService.createSetRingtone(
+                mContext, mLookupUri, mCustomRingtone);
+        mContext.startService(intent);
+    }
 }