1/* 2 * Copyright (C) 2014 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 17package com.android.settings.notification; 18 19import android.content.ContentResolver; 20import android.content.Context; 21import android.content.res.Resources; 22import android.database.ContentObserver; 23import android.media.AudioManager; 24import android.net.Uri; 25import android.os.AsyncTask; 26import android.os.Bundle; 27import android.os.Handler; 28import android.os.SystemProperties; 29import android.os.Vibrator; 30import android.provider.SearchIndexableResource; 31import android.provider.Settings.Global; 32import android.provider.Settings.System; 33import android.support.v14.preference.SwitchPreference; 34import android.support.v7.preference.Preference; 35import android.telephony.TelephonyManager; 36 37import com.android.internal.logging.MetricsProto.MetricsEvent; 38import com.android.settings.R; 39import com.android.settings.SettingsPreferenceFragment; 40import com.android.settings.Utils; 41import com.android.settings.search.BaseSearchIndexProvider; 42import com.android.settings.search.Indexable; 43 44import java.util.ArrayList; 45import java.util.Arrays; 46import java.util.List; 47 48import static com.android.settings.notification.SettingPref.TYPE_GLOBAL; 49import static com.android.settings.notification.SettingPref.TYPE_SYSTEM; 50 51public class OtherSoundSettings extends SettingsPreferenceFragment implements Indexable { 52 private static final String TAG = "OtherSoundSettings"; 53 54 private static final int DEFAULT_ON = 1; 55 56 private static final int EMERGENCY_TONE_SILENT = 0; 57 private static final int EMERGENCY_TONE_ALERT = 1; 58 private static final int EMERGENCY_TONE_VIBRATE = 2; 59 private static final int DEFAULT_EMERGENCY_TONE = EMERGENCY_TONE_SILENT; 60 61 private static final int DOCK_AUDIO_MEDIA_DISABLED = 0; 62 private static final int DOCK_AUDIO_MEDIA_ENABLED = 1; 63 private static final int DEFAULT_DOCK_AUDIO_MEDIA = DOCK_AUDIO_MEDIA_DISABLED; 64 65 private static final String KEY_DIAL_PAD_TONES = "dial_pad_tones"; 66 private static final String KEY_SCREEN_LOCKING_SOUNDS = "screen_locking_sounds"; 67 private static final String KEY_CHARGING_SOUNDS = "charging_sounds"; 68 private static final String KEY_DOCKING_SOUNDS = "docking_sounds"; 69 private static final String KEY_TOUCH_SOUNDS = "touch_sounds"; 70 private static final String KEY_VIBRATE_ON_TOUCH = "vibrate_on_touch"; 71 private static final String KEY_DOCK_AUDIO_MEDIA = "dock_audio_media"; 72 private static final String KEY_EMERGENCY_TONE = "emergency_tone"; 73 74 // Boot Sounds needs to be a system property so it can be accessed during boot. 75 private static final String KEY_BOOT_SOUNDS = "boot_sounds"; 76 private static final String PROPERTY_BOOT_SOUNDS = "persist.sys.bootanim.play_sound"; 77 78 private static final SettingPref PREF_DIAL_PAD_TONES = new SettingPref( 79 TYPE_SYSTEM, KEY_DIAL_PAD_TONES, System.DTMF_TONE_WHEN_DIALING, DEFAULT_ON) { 80 @Override 81 public boolean isApplicable(Context context) { 82 return Utils.isVoiceCapable(context); 83 } 84 }; 85 86 private static final SettingPref PREF_SCREEN_LOCKING_SOUNDS = new SettingPref( 87 TYPE_SYSTEM, KEY_SCREEN_LOCKING_SOUNDS, System.LOCKSCREEN_SOUNDS_ENABLED, DEFAULT_ON); 88 89 private static final SettingPref PREF_CHARGING_SOUNDS = new SettingPref( 90 TYPE_GLOBAL, KEY_CHARGING_SOUNDS, Global.CHARGING_SOUNDS_ENABLED, DEFAULT_ON); 91 92 private static final SettingPref PREF_DOCKING_SOUNDS = new SettingPref( 93 TYPE_GLOBAL, KEY_DOCKING_SOUNDS, Global.DOCK_SOUNDS_ENABLED, DEFAULT_ON) { 94 @Override 95 public boolean isApplicable(Context context) { 96 return hasDockSettings(context); 97 } 98 }; 99 100 private static final SettingPref PREF_TOUCH_SOUNDS = new SettingPref( 101 TYPE_SYSTEM, KEY_TOUCH_SOUNDS, System.SOUND_EFFECTS_ENABLED, DEFAULT_ON) { 102 @Override 103 protected boolean setSetting(final Context context, final int value) { 104 AsyncTask.execute(new Runnable() { 105 @Override 106 public void run() { 107 final AudioManager am = 108 (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 109 if (value != 0) { 110 am.loadSoundEffects(); 111 } else { 112 am.unloadSoundEffects(); 113 } 114 } 115 }); 116 return super.setSetting(context, value); 117 } 118 }; 119 120 private static final SettingPref PREF_VIBRATE_ON_TOUCH = new SettingPref( 121 TYPE_SYSTEM, KEY_VIBRATE_ON_TOUCH, System.HAPTIC_FEEDBACK_ENABLED, DEFAULT_ON) { 122 @Override 123 public boolean isApplicable(Context context) { 124 return hasHaptic(context); 125 } 126 }; 127 128 private static final SettingPref PREF_DOCK_AUDIO_MEDIA = new SettingPref( 129 TYPE_GLOBAL, KEY_DOCK_AUDIO_MEDIA, Global.DOCK_AUDIO_MEDIA_ENABLED, 130 DEFAULT_DOCK_AUDIO_MEDIA, DOCK_AUDIO_MEDIA_DISABLED, DOCK_AUDIO_MEDIA_ENABLED) { 131 @Override 132 public boolean isApplicable(Context context) { 133 return hasDockSettings(context); 134 } 135 136 @Override 137 protected String getCaption(Resources res, int value) { 138 switch(value) { 139 case DOCK_AUDIO_MEDIA_DISABLED: 140 return res.getString(R.string.dock_audio_media_disabled); 141 case DOCK_AUDIO_MEDIA_ENABLED: 142 return res.getString(R.string.dock_audio_media_enabled); 143 default: 144 throw new IllegalArgumentException(); 145 } 146 } 147 }; 148 149 private static final SettingPref PREF_EMERGENCY_TONE = new SettingPref( 150 TYPE_GLOBAL, KEY_EMERGENCY_TONE, Global.EMERGENCY_TONE, DEFAULT_EMERGENCY_TONE, 151 EMERGENCY_TONE_ALERT, EMERGENCY_TONE_VIBRATE, EMERGENCY_TONE_SILENT) { 152 @Override 153 public boolean isApplicable(Context context) { 154 final int activePhoneType = TelephonyManager.getDefault().getCurrentPhoneType(); 155 return activePhoneType == TelephonyManager.PHONE_TYPE_CDMA; 156 } 157 158 @Override 159 protected String getCaption(Resources res, int value) { 160 switch(value) { 161 case EMERGENCY_TONE_SILENT: 162 return res.getString(R.string.emergency_tone_silent); 163 case EMERGENCY_TONE_ALERT: 164 return res.getString(R.string.emergency_tone_alert); 165 case EMERGENCY_TONE_VIBRATE: 166 return res.getString(R.string.emergency_tone_vibrate); 167 default: 168 throw new IllegalArgumentException(); 169 } 170 } 171 }; 172 173 private static final SettingPref[] PREFS = { 174 PREF_DIAL_PAD_TONES, 175 PREF_SCREEN_LOCKING_SOUNDS, 176 PREF_CHARGING_SOUNDS, 177 PREF_DOCKING_SOUNDS, 178 PREF_TOUCH_SOUNDS, 179 PREF_VIBRATE_ON_TOUCH, 180 PREF_DOCK_AUDIO_MEDIA, 181 PREF_EMERGENCY_TONE, 182 }; 183 184 private SwitchPreference mBootSounds; 185 186 private final SettingsObserver mSettingsObserver = new SettingsObserver(); 187 188 private Context mContext; 189 190 @Override 191 protected int getMetricsCategory() { 192 return MetricsEvent.NOTIFICATION_OTHER_SOUND; 193 } 194 195 @Override 196 protected int getHelpResource() { 197 return R.string.help_uri_other_sounds; 198 } 199 200 @Override 201 public void onCreate(Bundle savedInstanceState) { 202 super.onCreate(savedInstanceState); 203 204 addPreferencesFromResource(R.xml.other_sound_settings); 205 206 mContext = getActivity(); 207 208 for (SettingPref pref : PREFS) { 209 pref.init(this); 210 } 211 212 if (mContext.getResources().getBoolean(R.bool.has_boot_sounds)) { 213 mBootSounds = (SwitchPreference) findPreference(KEY_BOOT_SOUNDS); 214 mBootSounds.setChecked(SystemProperties.getBoolean(PROPERTY_BOOT_SOUNDS, true)); 215 } else { 216 removePreference(KEY_BOOT_SOUNDS); 217 } 218 } 219 220 @Override 221 public void onResume() { 222 super.onResume(); 223 mSettingsObserver.register(true); 224 } 225 226 @Override 227 public void onPause() { 228 super.onPause(); 229 mSettingsObserver.register(false); 230 } 231 232 @Override 233 public boolean onPreferenceTreeClick(Preference preference) { 234 if (mBootSounds != null && preference == mBootSounds) { 235 SystemProperties.set(PROPERTY_BOOT_SOUNDS, mBootSounds.isChecked() ? "1" : "0"); 236 return false; 237 } else { 238 return super.onPreferenceTreeClick(preference); 239 } 240 } 241 242 private static boolean hasDockSettings(Context context) { 243 return context.getResources().getBoolean(R.bool.has_dock_settings); 244 } 245 246 private static boolean hasHaptic(Context context) { 247 final Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 248 return vibrator != null && vibrator.hasVibrator(); 249 } 250 251 // === Callbacks === 252 253 private final class SettingsObserver extends ContentObserver { 254 public SettingsObserver() { 255 super(new Handler()); 256 } 257 258 public void register(boolean register) { 259 final ContentResolver cr = getContentResolver(); 260 if (register) { 261 for (SettingPref pref : PREFS) { 262 cr.registerContentObserver(pref.getUri(), false, this); 263 } 264 } else { 265 cr.unregisterContentObserver(this); 266 } 267 } 268 269 @Override 270 public void onChange(boolean selfChange, Uri uri) { 271 super.onChange(selfChange, uri); 272 for (SettingPref pref : PREFS) { 273 if (pref.getUri().equals(uri)) { 274 pref.update(mContext); 275 return; 276 } 277 } 278 } 279 } 280 281 // === Indexing === 282 283 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 284 new BaseSearchIndexProvider() { 285 286 public List<SearchIndexableResource> getXmlResourcesToIndex( 287 Context context, boolean enabled) { 288 final SearchIndexableResource sir = new SearchIndexableResource(context); 289 sir.xmlResId = R.xml.other_sound_settings; 290 return Arrays.asList(sir); 291 } 292 293 public List<String> getNonIndexableKeys(Context context) { 294 final ArrayList<String> rt = new ArrayList<String>(); 295 for (SettingPref pref : PREFS) { 296 if (!pref.isApplicable(context)) { 297 rt.add(pref.getKey()); 298 } 299 } 300 return rt; 301 } 302 }; 303} 304