2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings;
19 import android.content.BroadcastReceiver;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.media.AudioManager;
25 import android.os.Bundle;
26 import android.os.Vibrator;
27 import android.preference.CheckBoxPreference;
28 import android.preference.ListPreference;
29 import android.preference.Preference;
30 import android.preference.PreferenceGroup;
31 import android.preference.PreferenceScreen;
32 import android.provider.Settings;
33 import android.provider.Settings.SettingNotFoundException;
34 import android.telephony.TelephonyManager;
35 import android.util.Log;
37 public class SoundSettings extends SettingsPreferenceFragment implements
38 Preference.OnPreferenceChangeListener {
39 private static final String TAG = "SoundAndDisplaysSettings";
41 /** If there is no setting in the provider, use this. */
42 private static final int FALLBACK_EMERGENCY_TONE_VALUE = 0;
44 private static final String KEY_SILENT = "silent";
45 private static final String KEY_VIBRATE = "vibrate";
46 private static final String KEY_RING_VOLUME = "ring_volume";
47 private static final String KEY_DTMF_TONE = "dtmf_tone";
48 private static final String KEY_SOUND_EFFECTS = "sound_effects";
49 private static final String KEY_HAPTIC_FEEDBACK = "haptic_feedback";
50 private static final String KEY_EMERGENCY_TONE = "emergency_tone";
51 private static final String KEY_SOUND_SETTINGS = "sound_settings";
52 private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
53 private static final String KEY_LOCK_SOUNDS = "lock_sounds";
54 private static final String KEY_RINGTONE = "ringtone";
55 private static final String KEY_NOTIFICATION_SOUND = "notification_sound";
56 private static final String KEY_CATEGORY_CALLS = "category_calls";
57 private static final String KEY_CATEGORY_NOTIFICATION = "category_notification";
59 private static final String VALUE_VIBRATE_NEVER = "never";
60 private static final String VALUE_VIBRATE_ALWAYS = "always";
61 private static final String VALUE_VIBRATE_ONLY_SILENT = "silent";
62 private static final String VALUE_VIBRATE_UNLESS_SILENT = "notsilent";
64 private static final String[] NEED_VOICE_CAPABILITY = {
65 KEY_RINGTONE, KEY_DTMF_TONE, KEY_CATEGORY_CALLS,
69 private CheckBoxPreference mSilent;
72 * If we are currently in one of the silent modes (the ringer mode is set to either
73 * "silent mode" or "vibrate mode"), then toggling the "Phone vibrate"
74 * preference will switch between "silent mode" and "vibrate mode".
75 * Otherwise, it will adjust the normal ringer mode's ring or ring+vibrate
78 private ListPreference mVibrate;
79 private CheckBoxPreference mDtmfTone;
80 private CheckBoxPreference mSoundEffects;
81 private CheckBoxPreference mHapticFeedback;
82 private CheckBoxPreference mNotificationPulse;
83 private CheckBoxPreference mLockSounds;
85 private AudioManager mAudioManager;
87 private BroadcastReceiver mReceiver = new BroadcastReceiver() {
89 public void onReceive(Context context, Intent intent) {
90 if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
96 private PreferenceGroup mSoundSettings;
99 public void onCreate(Bundle savedInstanceState) {
100 super.onCreate(savedInstanceState);
101 ContentResolver resolver = getContentResolver();
102 int activePhoneType = TelephonyManager.getDefault().getCurrentPhoneType();
104 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
106 addPreferencesFromResource(R.xml.sound_settings);
108 if (TelephonyManager.PHONE_TYPE_CDMA != activePhoneType) {
109 // device is not CDMA, do not display CDMA emergency_tone
110 getPreferenceScreen().removePreference(findPreference(KEY_EMERGENCY_TONE));
113 mSilent = (CheckBoxPreference) findPreference(KEY_SILENT);
114 if (!getResources().getBoolean(R.bool.has_silent_mode)) {
115 getPreferenceScreen().removePreference(mSilent);
116 findPreference(KEY_RING_VOLUME).setDependency(null);
119 mVibrate = (ListPreference) findPreference(KEY_VIBRATE);
120 mVibrate.setOnPreferenceChangeListener(this);
122 mDtmfTone = (CheckBoxPreference) findPreference(KEY_DTMF_TONE);
123 mDtmfTone.setPersistent(false);
124 mDtmfTone.setChecked(Settings.System.getInt(resolver,
125 Settings.System.DTMF_TONE_WHEN_DIALING, 1) != 0);
126 mSoundEffects = (CheckBoxPreference) findPreference(KEY_SOUND_EFFECTS);
127 mSoundEffects.setPersistent(false);
128 mSoundEffects.setChecked(Settings.System.getInt(resolver,
129 Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0);
130 mHapticFeedback = (CheckBoxPreference) findPreference(KEY_HAPTIC_FEEDBACK);
131 mHapticFeedback.setPersistent(false);
132 mHapticFeedback.setChecked(Settings.System.getInt(resolver,
133 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) != 0);
134 mLockSounds = (CheckBoxPreference) findPreference(KEY_LOCK_SOUNDS);
135 mLockSounds.setPersistent(false);
136 mLockSounds.setChecked(Settings.System.getInt(resolver,
137 Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) != 0);
139 if (!((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
140 getPreferenceScreen().removePreference(mVibrate);
141 getPreferenceScreen().removePreference(mHapticFeedback);
144 if (TelephonyManager.PHONE_TYPE_CDMA == activePhoneType) {
145 ListPreference emergencyTonePreference =
146 (ListPreference) findPreference(KEY_EMERGENCY_TONE);
147 emergencyTonePreference.setValue(String.valueOf(Settings.System.getInt(
148 resolver, Settings.System.EMERGENCY_TONE, FALLBACK_EMERGENCY_TONE_VALUE)));
149 emergencyTonePreference.setOnPreferenceChangeListener(this);
152 mSoundSettings = (PreferenceGroup) findPreference(KEY_SOUND_SETTINGS);
153 mNotificationPulse = (CheckBoxPreference)
154 mSoundSettings.findPreference(KEY_NOTIFICATION_PULSE);
155 if (mNotificationPulse != null
156 && getResources().getBoolean(R.bool.has_intrusive_led) == false) {
157 mSoundSettings.removePreference(mNotificationPulse);
160 mNotificationPulse.setChecked(Settings.System.getInt(resolver,
161 Settings.System.NOTIFICATION_LIGHT_PULSE) == 1);
162 mNotificationPulse.setOnPreferenceChangeListener(this);
163 } catch (SettingNotFoundException snfe) {
164 Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
168 if (!Utils.isVoiceCapable(getActivity())) {
169 for (String prefKey : NEED_VOICE_CAPABILITY) {
170 Preference pref = findPreference(prefKey);
172 getPreferenceScreen().removePreference(pref);
179 public void onResume() {
184 IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
185 getActivity().registerReceiver(mReceiver, filter);
189 public void onPause() {
192 getActivity().unregisterReceiver(mReceiver);
195 private String getPhoneVibrateSettingValue() {
196 boolean vibeInSilent = (Settings.System.getInt(
197 getContentResolver(),
198 Settings.System.VIBRATE_IN_SILENT,
201 // Control phone vibe independent of silent mode
202 int callsVibrateSetting =
203 mAudioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
206 if (callsVibrateSetting == AudioManager.VIBRATE_SETTING_OFF) {
207 // this state does not make sense; fix it up for the user
208 mAudioManager.setVibrateSetting(
209 AudioManager.VIBRATE_TYPE_RINGER,
210 AudioManager.VIBRATE_SETTING_ONLY_SILENT);
212 if (callsVibrateSetting == AudioManager.VIBRATE_SETTING_ON) {
213 return VALUE_VIBRATE_ALWAYS;
215 return VALUE_VIBRATE_ONLY_SILENT;
218 if (callsVibrateSetting == AudioManager.VIBRATE_SETTING_ONLY_SILENT) {
219 // this state does not make sense; fix it up
220 mAudioManager.setVibrateSetting(
221 AudioManager.VIBRATE_TYPE_RINGER,
222 AudioManager.VIBRATE_SETTING_OFF);
224 if (callsVibrateSetting == AudioManager.VIBRATE_SETTING_ON) {
225 return VALUE_VIBRATE_UNLESS_SILENT;
227 return VALUE_VIBRATE_NEVER;
232 private void setPhoneVibrateSettingValue(String value) {
233 boolean vibeInSilent;
234 int callsVibrateSetting;
236 if (value.equals(VALUE_VIBRATE_UNLESS_SILENT)) {
237 callsVibrateSetting = AudioManager.VIBRATE_SETTING_ON;
238 vibeInSilent = false;
239 } else if (value.equals(VALUE_VIBRATE_NEVER)) {
240 callsVibrateSetting = AudioManager.VIBRATE_SETTING_OFF;
241 vibeInSilent = false;
242 } else if (value.equals(VALUE_VIBRATE_ONLY_SILENT)) {
243 callsVibrateSetting = AudioManager.VIBRATE_SETTING_ONLY_SILENT;
245 } else { //VALUE_VIBRATE_ALWAYS
246 callsVibrateSetting = AudioManager.VIBRATE_SETTING_ON;
250 Settings.System.putInt(getContentResolver(),
251 Settings.System.VIBRATE_IN_SILENT,
252 vibeInSilent ? 1 : 0);
254 // might need to switch the ringer mode from one kind of "silent" to
256 if (mSilent.isChecked()) {
257 mAudioManager.setRingerMode(
258 vibeInSilent ? AudioManager.RINGER_MODE_VIBRATE
259 : AudioManager.RINGER_MODE_SILENT);
262 mAudioManager.setVibrateSetting(
263 AudioManager.VIBRATE_TYPE_RINGER,
264 callsVibrateSetting);
267 // updateState in fact updates the UI to reflect the system state
268 private void updateState(boolean force) {
269 if (getActivity() == null) return;
271 final int ringerMode = mAudioManager.getRingerMode();
273 // NB: in the UI we now simply call this "silent mode". A separate
274 // setting controls whether we're in RINGER_MODE_SILENT or
275 // RINGER_MODE_VIBRATE.
276 final boolean silentOrVibrateMode =
277 ringerMode != AudioManager.RINGER_MODE_NORMAL;
279 if (silentOrVibrateMode != mSilent.isChecked() || force) {
280 mSilent.setChecked(silentOrVibrateMode);
283 String phoneVibrateSetting = getPhoneVibrateSettingValue();
285 if (! phoneVibrateSetting.equals(mVibrate.getValue()) || force) {
286 mVibrate.setValue(phoneVibrateSetting);
288 mVibrate.setSummary(mVibrate.getEntry());
290 int silentModeStreams = Settings.System.getInt(getContentResolver(),
291 Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
292 boolean isAlarmInclSilentMode = (silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0;
293 mSilent.setSummary(isAlarmInclSilentMode ?
294 R.string.silent_mode_incl_alarm_summary :
295 R.string.silent_mode_summary);
299 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
300 if (preference == mSilent) {
301 if (mSilent.isChecked()) {
302 boolean vibeInSilent = (1 == Settings.System.getInt(
303 getContentResolver(),
304 Settings.System.VIBRATE_IN_SILENT,
306 mAudioManager.setRingerMode(
307 vibeInSilent ? AudioManager.RINGER_MODE_VIBRATE
308 : AudioManager.RINGER_MODE_SILENT);
310 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
313 } else if (preference == mDtmfTone) {
314 Settings.System.putInt(getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING,
315 mDtmfTone.isChecked() ? 1 : 0);
317 } else if (preference == mSoundEffects) {
318 if (mSoundEffects.isChecked()) {
319 mAudioManager.loadSoundEffects();
321 mAudioManager.unloadSoundEffects();
323 Settings.System.putInt(getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED,
324 mSoundEffects.isChecked() ? 1 : 0);
326 } else if (preference == mHapticFeedback) {
327 Settings.System.putInt(getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED,
328 mHapticFeedback.isChecked() ? 1 : 0);
330 } else if (preference == mLockSounds) {
331 Settings.System.putInt(getContentResolver(), Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
332 mLockSounds.isChecked() ? 1 : 0);
334 } else if (preference == mNotificationPulse) {
335 boolean value = mNotificationPulse.isChecked();
336 Settings.System.putInt(getContentResolver(),
337 Settings.System.NOTIFICATION_LIGHT_PULSE, value ? 1 : 0);
343 public boolean onPreferenceChange(Preference preference, Object objValue) {
344 final String key = preference.getKey();
345 if (KEY_EMERGENCY_TONE.equals(key)) {
347 int value = Integer.parseInt((String) objValue);
348 Settings.System.putInt(getContentResolver(),
349 Settings.System.EMERGENCY_TONE, value);
350 } catch (NumberFormatException e) {
351 Log.e(TAG, "could not persist emergency tone setting", e);
353 } else if (preference == mVibrate) {
354 setPhoneVibrateSettingValue(objValue.toString());