Support new vibrate/silent behavior.

The updated settings tree looks like this:

	[ ] Silent mode (unchanged)
	[ ] Allow vibration in silent mode (new)
		Phone vibrate: (changed from boolean)
		( ) Always
		( ) Only in silent mode
		( ) Never

See change I14cf91b0 for explanation & framework support.

Change-Id: I22ba7bcfa5ddf4e545800083c6e80fb655f211e5
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index ff68cc7..0aa604d 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -368,4 +368,17 @@
         <item>auto</item>
     </string-array>
 
+    <!-- New incoming call vibrate options. -->
+    <string-array name="vibrate_entries">
+        <item>Always</item>
+        <item>Only when silent</item>
+        <item>Never</item>
+    </string-array>
+
+    <!-- Corresponds to AudioManager.VIBRATE_SETTING_*. Do not translate. -->
+    <string-array name="vibrate_values" translatable="false">
+        <item>1</item>
+        <item>2</item>
+        <item>0</item>
+    </string-array>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4808a69..67196e9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -954,6 +954,10 @@
     <!-- Sound settings screen, setting option summary text -->
     <string name="ring_volume_summary">""</string>
     <!-- Sound settings screen, setting option name checkbox -->
+    <string name="vibrate_in_silent_title">Vibrate when silent</string>
+    <!-- Sound settings screen, setting option summary text -->
+    <string name="vibrate_in_silent_summary">Allow vibration feedback in silent mode</string>
+    <!-- Sound settings screen, setting option name checkbox -->
     <string name="vibrate_title">Phone vibrate</string>
     <!-- Sound settings screen, setting option summary text -->
     <string name="vibrate_summary">Vibrate phone for incoming calls</string>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index e4d80e6..8632871 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -27,6 +27,13 @@
                 android:order="1"
                 android:disableDependentsState="true" />
 
+        <CheckBoxPreference
+                android:key="vibrate_in_silent"
+                android:title="@string/vibrate_in_silent_title"
+                android:summary="@string/vibrate_in_silent_summary"
+                android:order="2"
+                android:persistent="false" />
+
         <com.android.settings.RingerVolumePreference
                 android:key="ring_volume"
                 android:title="@string/all_volume_title"
@@ -34,7 +41,7 @@
                 android:dialogTitle="@string/all_volume_title"
                 android:persistent="false"
                 android:dependency="silent"
-                android:order="2"
+                android:order="3"
                 android:streamType="ring" />
 
         <com.android.settings.DefaultRingtonePreference
@@ -47,12 +54,13 @@
                 android:order="5"
                 android:ringtoneType="ringtone" />
 
-        <CheckBoxPreference
+        <ListPreference
                 android:key="vibrate"
+                android:order="6"
                 android:title="@string/vibrate_title"
                 android:summary="@string/vibrate_summary"
-                android:order="6"
-                android:persistent="false" />
+                android:entries="@array/vibrate_entries"
+                android:entryValues="@array/vibrate_values" />
 
         <com.android.settings.DefaultRingtonePreference
                 android:key="notification_sound"
diff --git a/src/com/android/settings/SoundSettings.java b/src/com/android/settings/SoundSettings.java
index 2070519..c7bfe71 100644
--- a/src/com/android/settings/SoundSettings.java
+++ b/src/com/android/settings/SoundSettings.java
@@ -49,6 +49,7 @@
 
     private static final String KEY_SILENT = "silent";
     private static final String KEY_VIBRATE = "vibrate";
+    private static final String KEY_VIBRATE_IN_SILENT = "vibrate_in_silent";
     private static final String KEY_DTMF_TONE = "dtmf_tone";
     private static final String KEY_SOUND_EFFECTS = "sound_effects";
     private static final String KEY_HAPTIC_FEEDBACK = "haptic_feedback";
@@ -66,7 +67,8 @@
      * Otherwise, it will adjust the normal ringer mode's ring or ring+vibrate
      * setting.
      */
-    private CheckBoxPreference mVibrate;
+    private ListPreference mPhoneVibrate;
+    private CheckBoxPreference mVibrateInSilent;
     private CheckBoxPreference mDtmfTone;
     private CheckBoxPreference mSoundEffects;
     private CheckBoxPreference mHapticFeedback;
@@ -103,7 +105,8 @@
 
         mSilent = (CheckBoxPreference) findPreference(KEY_SILENT);
 
-        mVibrate = (CheckBoxPreference) findPreference(KEY_VIBRATE);
+        mPhoneVibrate = (ListPreference) findPreference(KEY_VIBRATE);
+        mVibrateInSilent = (CheckBoxPreference) findPreference(KEY_VIBRATE_IN_SILENT);
         mDtmfTone = (CheckBoxPreference) findPreference(KEY_DTMF_TONE);
         mDtmfTone.setPersistent(false);
         mDtmfTone.setChecked(Settings.System.getInt(resolver,
@@ -164,8 +167,13 @@
         unregisterReceiver(mReceiver);
     }
 
+    // updateState in fact updates the UI to reflect the system state
     private void updateState(boolean force) {
         final int ringerMode = mAudioManager.getRingerMode();
+
+        // NB: in the UI we now simply call this "silent mode". A separate
+        // setting controls whether we're in RINGER_MODE_SILENT or
+        // RINGER_MODE_VIBRATE.
         final boolean silentOrVibrateMode =
                 ringerMode != AudioManager.RINGER_MODE_NORMAL;
 
@@ -173,15 +181,18 @@
             mSilent.setChecked(silentOrVibrateMode);
         }
 
-        boolean vibrateSetting;
-        if (silentOrVibrateMode) {
-            vibrateSetting = ringerMode == AudioManager.RINGER_MODE_VIBRATE;
-        } else {
-            vibrateSetting = mAudioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER)
-                    == AudioManager.VIBRATE_SETTING_ON;
-        }
-        if (vibrateSetting != mVibrate.isChecked() || force) {
-            mVibrate.setChecked(vibrateSetting);
+        mVibrateInSilent.setEnabled(silentOrVibrateMode);
+        mVibrateInSilent.setChecked(Settings.System.getInt(
+            getContentResolver(),
+            Settings.System.VIBRATE_IN_SILENT,
+            1) == 1);
+
+        // Control phone vibe independent of silent mode
+        String phoneVibrateSetting = String.valueOf(
+            mAudioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER));
+
+        if (! phoneVibrateSetting.equals(mPhoneVibrate.getValue()) || force) {
+            mPhoneVibrate.setValue(phoneVibrateSetting);
         }
 
         int silentModeStreams = Settings.System.getInt(getContentResolver(),
@@ -193,23 +204,41 @@
 
     }
 
-    private void setRingerMode(boolean silent, boolean vibrate) {
-        if (silent) {
-            mAudioManager.setRingerMode(vibrate ? AudioManager.RINGER_MODE_VIBRATE :
-                AudioManager.RINGER_MODE_SILENT);
-        } else {
-            mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-            mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,
-                    vibrate ? AudioManager.VIBRATE_SETTING_ON
-                            : AudioManager.VIBRATE_SETTING_OFF);
-        }
-    }
-
     @Override
     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
-        if (preference == mSilent || preference == mVibrate) {
-            setRingerMode(mSilent.isChecked(), mVibrate.isChecked());
-            if (preference == mSilent) updateState(false);
+        if (preference == mSilent) {
+            if (mSilent.isChecked()) {
+                boolean vibeInSilent = mVibrateInSilent.isChecked();
+                mAudioManager.setRingerMode(
+                    vibeInSilent ? AudioManager.RINGER_MODE_VIBRATE
+                                 : AudioManager.RINGER_MODE_SILENT);
+            } else {
+                mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+            }
+            updateState(false);
+        } else if (preference == mPhoneVibrate) {
+            int vibeSetting = new Integer(mPhoneVibrate.getValue()).intValue();
+            switch (vibeSetting) {
+                case AudioManager.VIBRATE_SETTING_ON:
+                case AudioManager.VIBRATE_SETTING_OFF:
+                case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
+                    mAudioManager.setVibrateSetting(
+                            AudioManager.VIBRATE_TYPE_RINGER,
+                            vibeSetting);
+                    updateState(false);
+                    break;
+            }
+        } else if (preference == mVibrateInSilent) {
+            boolean vibeInSilent = mVibrateInSilent.isChecked();
+            Settings.System.putInt(getContentResolver(),
+                Settings.System.VIBRATE_IN_SILENT,
+                vibeInSilent ? 1 : 0);
+            int ringerMode = mAudioManager.getRingerMode();
+            if (ringerMode != AudioManager.RINGER_MODE_NORMAL) {
+                mAudioManager.setRingerMode(vibeInSilent
+                    ? AudioManager.RINGER_MODE_VIBRATE
+                    : AudioManager.RINGER_MODE_SILENT);
+            }
         } else if (preference == mDtmfTone) {
             Settings.System.putInt(getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING,
                     mDtmfTone.isChecked() ? 1 : 0);