1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings; 18 19 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; 20 21 import android.content.BroadcastReceiver; 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.media.AudioManager; 27 import android.os.Bundle; 28 import android.os.RemoteException; 29 import android.os.ServiceManager; 30 import android.preference.CheckBoxPreference; 31 import android.preference.ListPreference; 32 import android.preference.Preference; 33 import android.preference.PreferenceActivity; 34 import android.preference.PreferenceGroup; 35 import android.preference.PreferenceScreen; 36 import android.provider.Settings; 37 import android.provider.Settings.SettingNotFoundException; 38 import android.telephony.TelephonyManager; 39 import android.util.Log; 40 import android.view.IWindowManager; 41 42 public class SoundSettings extends PreferenceActivity implements 43 Preference.OnPreferenceChangeListener { 44 private static final String TAG = "SoundAndDisplaysSettings"; 45 46 /** If there is no setting in the provider, use this. */ 47 private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000; 48 private static final int FALLBACK_EMERGENCY_TONE_VALUE = 0; 49 50 private static final String KEY_SILENT = "silent"; 51 private static final String KEY_VIBRATE = "vibrate"; 52 private static final String KEY_DTMF_TONE = "dtmf_tone"; 53 private static final String KEY_SOUND_EFFECTS = "sound_effects"; 54 private static final String KEY_HAPTIC_FEEDBACK = "haptic_feedback"; 55 private static final String KEY_EMERGENCY_TONE = "emergency_tone"; 56 private static final String KEY_SOUND_SETTINGS = "sound_settings"; 57 private static final String KEY_NOTIFICATION_PULSE = "notification_pulse"; 58 private static final String KEY_LOCK_SOUNDS = "lock_sounds"; 59 60 private static final String VALUE_VIBRATE_NEVER = "never"; 61 private static final String VALUE_VIBRATE_ALWAYS = "always"; 62 private static final String VALUE_VIBRATE_ONLY_SILENT = "silent"; 63 private static final String VALUE_VIBRATE_UNLESS_SILENT = "notsilent"; 64 65 private CheckBoxPreference mSilent; 66 67 /* 68 * If we are currently in one of the silent modes (the ringer mode is set to either 69 * "silent mode" or "vibrate mode"), then toggling the "Phone vibrate" 70 * preference will switch between "silent mode" and "vibrate mode". 71 * Otherwise, it will adjust the normal ringer mode's ring or ring+vibrate 72 * setting. 73 */ 74 private ListPreference mVibrate; 75 private CheckBoxPreference mDtmfTone; 76 private CheckBoxPreference mSoundEffects; 77 private CheckBoxPreference mHapticFeedback; 78 private CheckBoxPreference mNotificationPulse; 79 private CheckBoxPreference mLockSounds; 80 81 private AudioManager mAudioManager; 82 83 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 84 @Override 85 public void onReceive(Context context, Intent intent) { 86 if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 87 updateState(false); 88 } 89 } 90 }; 91 92 private PreferenceGroup mSoundSettings; 93 94 @Override onCreate(Bundle savedInstanceState)95 protected void onCreate(Bundle savedInstanceState) { 96 super.onCreate(savedInstanceState); 97 ContentResolver resolver = getContentResolver(); 98 int activePhoneType = TelephonyManager.getDefault().getPhoneType(); 99 100 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 101 102 addPreferencesFromResource(R.xml.sound_settings); 103 104 if (TelephonyManager.PHONE_TYPE_CDMA != activePhoneType) { 105 // device is not CDMA, do not display CDMA emergency_tone 106 getPreferenceScreen().removePreference(findPreference(KEY_EMERGENCY_TONE)); 107 } 108 109 mSilent = (CheckBoxPreference) findPreference(KEY_SILENT); 110 111 mVibrate = (ListPreference) findPreference(KEY_VIBRATE); 112 mVibrate.setOnPreferenceChangeListener(this); 113 114 mDtmfTone = (CheckBoxPreference) findPreference(KEY_DTMF_TONE); 115 mDtmfTone.setPersistent(false); 116 mDtmfTone.setChecked(Settings.System.getInt(resolver, 117 Settings.System.DTMF_TONE_WHEN_DIALING, 1) != 0); 118 mSoundEffects = (CheckBoxPreference) findPreference(KEY_SOUND_EFFECTS); 119 mSoundEffects.setPersistent(false); 120 mSoundEffects.setChecked(Settings.System.getInt(resolver, 121 Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0); 122 mHapticFeedback = (CheckBoxPreference) findPreference(KEY_HAPTIC_FEEDBACK); 123 mHapticFeedback.setPersistent(false); 124 mHapticFeedback.setChecked(Settings.System.getInt(resolver, 125 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) != 0); 126 mLockSounds = (CheckBoxPreference) findPreference(KEY_LOCK_SOUNDS); 127 mLockSounds.setPersistent(false); 128 mLockSounds.setChecked(Settings.System.getInt(resolver, 129 Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) != 0); 130 131 if (TelephonyManager.PHONE_TYPE_CDMA == activePhoneType) { 132 ListPreference emergencyTonePreference = 133 (ListPreference) findPreference(KEY_EMERGENCY_TONE); 134 emergencyTonePreference.setValue(String.valueOf(Settings.System.getInt( 135 resolver, Settings.System.EMERGENCY_TONE, FALLBACK_EMERGENCY_TONE_VALUE))); 136 emergencyTonePreference.setOnPreferenceChangeListener(this); 137 } 138 139 mSoundSettings = (PreferenceGroup) findPreference(KEY_SOUND_SETTINGS); 140 mNotificationPulse = (CheckBoxPreference) 141 mSoundSettings.findPreference(KEY_NOTIFICATION_PULSE); 142 if (mNotificationPulse != null && 143 getResources().getBoolean(R.bool.has_intrusive_led) == false) { 144 mSoundSettings.removePreference(mNotificationPulse); 145 } else { 146 try { 147 mNotificationPulse.setChecked(Settings.System.getInt(resolver, 148 Settings.System.NOTIFICATION_LIGHT_PULSE) == 1); 149 mNotificationPulse.setOnPreferenceChangeListener(this); 150 } catch (SettingNotFoundException snfe) { 151 Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found"); 152 } 153 } 154 155 } 156 157 @Override onResume()158 protected void onResume() { 159 super.onResume(); 160 161 updateState(true); 162 163 IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); 164 registerReceiver(mReceiver, filter); 165 } 166 167 @Override onPause()168 protected void onPause() { 169 super.onPause(); 170 171 unregisterReceiver(mReceiver); 172 } 173 getPhoneVibrateSettingValue()174 private String getPhoneVibrateSettingValue() { 175 boolean vibeInSilent = (Settings.System.getInt( 176 getContentResolver(), 177 Settings.System.VIBRATE_IN_SILENT, 178 1) == 1); 179 180 // Control phone vibe independent of silent mode 181 int callsVibrateSetting = 182 mAudioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); 183 184 if (vibeInSilent) { 185 if (callsVibrateSetting == AudioManager.VIBRATE_SETTING_OFF) { 186 // this state does not make sense; fix it up for the user 187 mAudioManager.setVibrateSetting( 188 AudioManager.VIBRATE_TYPE_RINGER, 189 AudioManager.VIBRATE_SETTING_ONLY_SILENT); 190 } 191 if (callsVibrateSetting == AudioManager.VIBRATE_SETTING_ON) { 192 return VALUE_VIBRATE_ALWAYS; 193 } else { 194 return VALUE_VIBRATE_ONLY_SILENT; 195 } 196 } else { 197 if (callsVibrateSetting == AudioManager.VIBRATE_SETTING_ONLY_SILENT) { 198 // this state does not make sense; fix it up 199 mAudioManager.setVibrateSetting( 200 AudioManager.VIBRATE_TYPE_RINGER, 201 AudioManager.VIBRATE_SETTING_OFF); 202 } 203 if (callsVibrateSetting == AudioManager.VIBRATE_SETTING_ON) { 204 return VALUE_VIBRATE_UNLESS_SILENT; 205 } else { 206 return VALUE_VIBRATE_NEVER; 207 } 208 } 209 } 210 setPhoneVibrateSettingValue(String value)211 private void setPhoneVibrateSettingValue(String value) { 212 boolean vibeInSilent; 213 int callsVibrateSetting; 214 215 if (value.equals(VALUE_VIBRATE_UNLESS_SILENT)) { 216 callsVibrateSetting = AudioManager.VIBRATE_SETTING_ON; 217 vibeInSilent = false; 218 } else if (value.equals(VALUE_VIBRATE_NEVER)) { 219 callsVibrateSetting = AudioManager.VIBRATE_SETTING_OFF; 220 vibeInSilent = false; 221 } else if (value.equals(VALUE_VIBRATE_ONLY_SILENT)) { 222 callsVibrateSetting = AudioManager.VIBRATE_SETTING_ONLY_SILENT; 223 vibeInSilent = true; 224 } else { //VALUE_VIBRATE_ALWAYS 225 callsVibrateSetting = AudioManager.VIBRATE_SETTING_ON; 226 vibeInSilent = true; 227 } 228 229 Settings.System.putInt(getContentResolver(), 230 Settings.System.VIBRATE_IN_SILENT, 231 vibeInSilent ? 1 : 0); 232 233 // might need to switch the ringer mode from one kind of "silent" to 234 // another 235 if (mSilent.isChecked()) { 236 mAudioManager.setRingerMode( 237 vibeInSilent ? AudioManager.RINGER_MODE_VIBRATE 238 : AudioManager.RINGER_MODE_SILENT); 239 } 240 241 mAudioManager.setVibrateSetting( 242 AudioManager.VIBRATE_TYPE_RINGER, 243 callsVibrateSetting); 244 } 245 246 // updateState in fact updates the UI to reflect the system state updateState(boolean force)247 private void updateState(boolean force) { 248 final int ringerMode = mAudioManager.getRingerMode(); 249 250 // NB: in the UI we now simply call this "silent mode". A separate 251 // setting controls whether we're in RINGER_MODE_SILENT or 252 // RINGER_MODE_VIBRATE. 253 final boolean silentOrVibrateMode = 254 ringerMode != AudioManager.RINGER_MODE_NORMAL; 255 256 if (silentOrVibrateMode != mSilent.isChecked() || force) { 257 mSilent.setChecked(silentOrVibrateMode); 258 } 259 260 String phoneVibrateSetting = getPhoneVibrateSettingValue(); 261 262 if (! phoneVibrateSetting.equals(mVibrate.getValue()) || force) { 263 mVibrate.setValue(phoneVibrateSetting); 264 } 265 mVibrate.setSummary(mVibrate.getEntry()); 266 267 int silentModeStreams = Settings.System.getInt(getContentResolver(), 268 Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); 269 boolean isAlarmInclSilentMode = (silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0; 270 mSilent.setSummary(isAlarmInclSilentMode ? 271 R.string.silent_mode_incl_alarm_summary : 272 R.string.silent_mode_summary); 273 } 274 275 @Override onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)276 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 277 if (preference == mSilent) { 278 if (mSilent.isChecked()) { 279 boolean vibeInSilent = (1 == Settings.System.getInt( 280 getContentResolver(), 281 Settings.System.VIBRATE_IN_SILENT, 282 1)); 283 mAudioManager.setRingerMode( 284 vibeInSilent ? AudioManager.RINGER_MODE_VIBRATE 285 : AudioManager.RINGER_MODE_SILENT); 286 } else { 287 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); 288 } 289 updateState(false); 290 } else if (preference == mDtmfTone) { 291 Settings.System.putInt(getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING, 292 mDtmfTone.isChecked() ? 1 : 0); 293 294 } else if (preference == mSoundEffects) { 295 if (mSoundEffects.isChecked()) { 296 mAudioManager.loadSoundEffects(); 297 } else { 298 mAudioManager.unloadSoundEffects(); 299 } 300 Settings.System.putInt(getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, 301 mSoundEffects.isChecked() ? 1 : 0); 302 303 } else if (preference == mHapticFeedback) { 304 Settings.System.putInt(getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 305 mHapticFeedback.isChecked() ? 1 : 0); 306 307 } else if (preference == mLockSounds) { 308 Settings.System.putInt(getContentResolver(), Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 309 mLockSounds.isChecked() ? 1 : 0); 310 311 } else if (preference == mNotificationPulse) { 312 boolean value = mNotificationPulse.isChecked(); 313 Settings.System.putInt(getContentResolver(), 314 Settings.System.NOTIFICATION_LIGHT_PULSE, value ? 1 : 0); 315 } 316 317 return true; 318 } 319 onPreferenceChange(Preference preference, Object objValue)320 public boolean onPreferenceChange(Preference preference, Object objValue) { 321 final String key = preference.getKey(); 322 if (KEY_EMERGENCY_TONE.equals(key)) { 323 int value = Integer.parseInt((String) objValue); 324 try { 325 Settings.System.putInt(getContentResolver(), 326 Settings.System.EMERGENCY_TONE, value); 327 } catch (NumberFormatException e) { 328 Log.e(TAG, "could not persist emergency tone setting", e); 329 } 330 } else if (preference == mVibrate) { 331 setPhoneVibrateSettingValue(objValue.toString()); 332 updateState(false); 333 } 334 335 return true; 336 } 337 } 338