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