2 * Copyright (C) 2014 The Android Open Source Project
3 * Copyright (C) 2016 The CyanogenMod Project
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package com.android.settings.notification;
20 import android.app.NotificationManager;
21 import android.app.admin.DevicePolicyManager;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ServiceInfo;
30 import android.database.ContentObserver;
31 import android.database.Cursor;
32 import android.database.sqlite.SQLiteException;
33 import android.media.AudioManager;
34 import android.media.RingtoneManager;
35 import android.net.Uri;
36 import android.os.AsyncTask;
37 import android.os.Bundle;
38 import android.os.Handler;
39 import android.os.Looper;
40 import android.os.Message;
41 import android.os.UserManager;
42 import android.os.Vibrator;
43 import android.preference.Preference;
44 import android.preference.Preference.OnPreferenceChangeListener;
45 import android.preference.PreferenceCategory;
46 import android.preference.PreferenceScreen;
47 import android.preference.SeekBarVolumizer;
48 import android.preference.SwitchPreference;
49 import android.preference.TwoStatePreference;
50 import android.provider.MediaStore;
51 import android.provider.OpenableColumns;
52 import android.provider.SearchIndexableResource;
53 import android.provider.Settings;
54 import android.telephony.SubscriptionManager;
55 import android.telephony.TelephonyManager;
56 import android.util.Log;
58 import com.android.internal.logging.MetricsLogger;
59 import com.android.internal.widget.LockPatternUtils;
60 import com.android.settings.DefaultRingtonePreference;
61 import com.android.settings.DropDownPreference;
62 import com.android.settings.R;
63 import com.android.settings.SettingsPreferenceFragment;
64 import com.android.settings.Utils;
65 import com.android.settings.search.BaseSearchIndexProvider;
66 import com.android.settings.search.Indexable;
67 import cyanogenmod.hardware.CMHardwareManager;
68 import cyanogenmod.providers.CMSettings;
70 import java.util.ArrayList;
71 import java.util.Arrays;
72 import java.util.List;
73 import java.util.Objects;
75 public class SoundSettings extends SettingsPreferenceFragment implements Indexable {
76 private static final String TAG = SoundSettings.class.getSimpleName();
78 private static final String KEY_SOUND = "sounds";
79 private static final String KEY_VOLUMES = "volumes";
80 private static final String KEY_VIBRATE = "vibrate";
81 private static final String KEY_MEDIA_VOLUME = "media_volume";
82 private static final String KEY_ALARM_VOLUME = "alarm_volume";
83 private static final String KEY_RING_VOLUME = "ring_volume";
84 private static final String KEY_NOTIFICATION_VOLUME = "notification_volume";
85 private static final String KEY_PHONE_RINGTONE = "ringtone";
86 private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone";
87 private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
88 private static final String KEY_WIFI_DISPLAY = "wifi_display";
89 private static final String KEY_NOTIFICATION = "notification";
90 private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
91 private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access";
92 private static final String KEY_INCREASING_RING_VOLUME = "increasing_ring_volume";
93 private static final String KEY_VIBRATION_INTENSITY = "vibration_intensity";
94 private static final String KEY_VIBRATE_ON_TOUCH = "vibrate_on_touch";
95 private static final String KEY_ZEN_MODE = "zen_mode";
96 private static final String KEY_VOLUME_LINK_NOTIFICATION = "volume_link_notification";
98 private static final String[] RESTRICTED_KEYS = {
102 KEY_NOTIFICATION_VOLUME,
106 private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds
108 private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback();
109 private final IncreasingRingVolumePreference.Callback mIncreasingRingVolumeCallback =
110 new IncreasingRingVolumePreference.Callback() {
112 public void onStartingSample() {
113 mVolumeCallback.stopSample();
114 mHandler.removeMessages(H.STOP_SAMPLE);
115 mHandler.sendEmptyMessageDelayed(H.STOP_SAMPLE, SAMPLE_CUTOFF);
119 private final H mHandler = new H();
120 private final SettingsObserver mSettingsObserver = new SettingsObserver();
121 private final Receiver mReceiver = new Receiver();
122 private final ArrayList<VolumeSeekBarPreference> mVolumePrefs = new ArrayList<>();
124 private Context mContext;
125 private PackageManager mPM;
126 private boolean mVoiceCapable;
127 private Vibrator mVibrator;
128 private AudioManager mAudioManager;
129 private VolumeSeekBarPreference mRingPreference;
130 private VolumeSeekBarPreference mNotificationPreference;
132 private TwoStatePreference mIncreasingRing;
133 private IncreasingRingVolumePreference mIncreasingRingVolume;
134 private ArrayList<DefaultRingtonePreference> mPhoneRingtonePreferences;
135 private Preference mNotificationRingtonePreference;
136 private TwoStatePreference mVibrateWhenRinging;
137 private Preference mNotificationAccess;
138 private boolean mSecure;
139 private int mLockscreenSelectedValue;
140 private ComponentName mSuppressor;
141 private int mRingerMode = -1;
142 private SwitchPreference mVolumeLinkNotificationSwitch;
143 private UserManager mUserManager;
146 protected int getMetricsCategory() {
147 return MetricsLogger.NOTIFICATION;
151 public void onCreate(Bundle savedInstanceState) {
152 super.onCreate(savedInstanceState);
153 mContext = getActivity();
154 mPM = mContext.getPackageManager();
155 mUserManager = UserManager.get(getContext());
156 mVoiceCapable = Utils.isVoiceCapable(mContext);
158 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
159 mVibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
160 if (mVibrator != null && !mVibrator.hasVibrator()) {
164 addPreferencesFromResource(R.xml.sounds);
166 final PreferenceCategory volumes = (PreferenceCategory) findPreference(KEY_VOLUMES);
167 final PreferenceCategory sounds = (PreferenceCategory) findPreference(KEY_SOUND);
168 final PreferenceCategory vibrate = (PreferenceCategory) findPreference(KEY_VIBRATE);
169 initVolumePreference(KEY_MEDIA_VOLUME, AudioManager.STREAM_MUSIC,
170 com.android.internal.R.drawable.ic_audio_media_mute);
171 initVolumePreference(KEY_ALARM_VOLUME, AudioManager.STREAM_ALARM,
172 com.android.internal.R.drawable.ic_audio_alarm_mute);
175 initVolumePreference(KEY_RING_VOLUME, AudioManager.STREAM_RING,
176 com.android.internal.R.drawable.ic_audio_ring_notif_mute);
177 mVolumeLinkNotificationSwitch = (SwitchPreference)
178 volumes.findPreference(KEY_VOLUME_LINK_NOTIFICATION);
180 volumes.removePreference(volumes.findPreference(KEY_RING_VOLUME));
181 volumes.removePreference(volumes.findPreference(KEY_VOLUME_LINK_NOTIFICATION));
184 CMHardwareManager hardware = CMHardwareManager.getInstance(mContext);
185 if (!hardware.isSupported(CMHardwareManager.FEATURE_VIBRATOR)) {
186 vibrate.removePreference(vibrate.findPreference(KEY_VIBRATION_INTENSITY));
189 initRingtones(sounds);
190 initIncreasingRing(sounds);
191 initVibrateWhenRinging(vibrate);
193 mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS);
194 refreshNotificationListeners();
196 updateEffectsSuppressor();
200 public void onResume() {
202 refreshNotificationListeners();
203 lookupRingtoneNames();
204 updateNotificationPreferenceState();
205 mSettingsObserver.register(true);
206 mReceiver.register(true);
207 updateRingPreference();
208 updateEffectsSuppressor();
209 for (VolumeSeekBarPreference volumePref : mVolumePrefs) {
210 volumePref.onActivityResume();
212 if (mIncreasingRingVolume != null) {
213 mIncreasingRingVolume.onActivityResume();
215 boolean isRestricted = mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME);
216 for (String key : RESTRICTED_KEYS) {
217 Preference pref = findPreference(key);
219 pref.setEnabled(!isRestricted);
225 public void onPause() {
227 mVolumeCallback.stopSample();
228 if (mIncreasingRingVolume != null) {
229 mIncreasingRingVolume.stopSample();
231 mSettingsObserver.register(false);
232 mReceiver.register(false);
236 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
237 return super.onPreferenceTreeClick(preferenceScreen, preference);
242 private VolumeSeekBarPreference initVolumePreference(String key, int stream, int muteIcon) {
243 final VolumeSeekBarPreference volumePref = (VolumeSeekBarPreference) findPreference(key);
244 if (volumePref == null) return null;
245 volumePref.setCallback(mVolumeCallback);
246 volumePref.setStream(stream);
247 mVolumePrefs.add(volumePref);
248 volumePref.setMuteIcon(muteIcon);
252 private void updateNotificationPreferenceState() {
253 if (mNotificationPreference == null) {
254 mNotificationPreference = initVolumePreference(KEY_NOTIFICATION_VOLUME,
255 AudioManager.STREAM_NOTIFICATION,
256 com.android.internal.R.drawable.ic_audio_ring_notif_mute);
260 final boolean enabled = Settings.Secure.getInt(getContentResolver(),
261 Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1;
262 if (mVolumeLinkNotificationSwitch != null) {
263 mVolumeLinkNotificationSwitch.setChecked(enabled);
268 private void updateRingPreference() {
269 if (mRingPreference != null) {
270 mRingPreference.showIcon(mSuppressor != null
271 ? com.android.internal.R.drawable.ic_audio_ring_notif_mute
272 : mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate()
273 ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate
274 : R.drawable.ic_audio_ring);
278 private boolean wasRingerModeVibrate() {
279 return mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_SILENT
280 && mAudioManager.getLastAudibleStreamVolume(AudioManager.STREAM_RING) == 0;
283 private void updateRingerMode() {
284 final int ringerMode = mAudioManager.getRingerModeInternal();
285 if (mRingerMode == ringerMode) return;
286 mRingerMode = ringerMode;
287 updateRingPreference();
290 private void updateEffectsSuppressor() {
291 final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor();
292 if (Objects.equals(suppressor, mSuppressor)) return;
293 mSuppressor = suppressor;
294 if (mRingPreference != null) {
295 final String text = suppressor != null ?
296 mContext.getString(com.android.internal.R.string.muted_by,
297 getSuppressorCaption(suppressor)) : null;
298 mRingPreference.setSuppressionText(text);
300 updateRingPreference();
303 private String getSuppressorCaption(ComponentName suppressor) {
304 final PackageManager pm = mContext.getPackageManager();
306 final ServiceInfo info = pm.getServiceInfo(suppressor, 0);
308 final CharSequence seq = info.loadLabel(pm);
310 final String str = seq.toString().trim();
311 if (str.length() > 0) {
316 } catch (Throwable e) {
317 Log.w(TAG, "Error loading suppressor caption", e);
319 return suppressor.getPackageName();
322 private final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback {
323 private SeekBarVolumizer mCurrent;
326 public void onSampleStarting(SeekBarVolumizer sbv) {
327 if (mCurrent != null && mCurrent != sbv) {
328 mCurrent.stopSample();
330 if (mIncreasingRingVolume != null) {
331 mIncreasingRingVolume.stopSample();
334 if (mCurrent != null) {
335 mHandler.removeMessages(H.STOP_SAMPLE);
336 mHandler.sendEmptyMessageDelayed(H.STOP_SAMPLE, SAMPLE_CUTOFF);
341 public void onStreamValueChanged(int stream, int progress) {
345 public void stopSample() {
346 if (mCurrent != null) {
347 mCurrent.stopSample();
353 // === Phone & notification ringtone ===
355 private void initRingtones(PreferenceCategory root) {
356 DefaultRingtonePreference phoneRingtonePreference =
357 (DefaultRingtonePreference) root.findPreference(KEY_PHONE_RINGTONE);
358 if (mPhoneRingtonePreferences != null && !mVoiceCapable || !Utils.isUserOwner()) {
359 root.removePreference(phoneRingtonePreference);
360 mPhoneRingtonePreferences = null;
362 mPhoneRingtonePreferences = new ArrayList<DefaultRingtonePreference>();
363 TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
364 Context.TELEPHONY_SERVICE);
365 if (telephonyManager.isMultiSimEnabled()){
366 root.removePreference(phoneRingtonePreference);
367 PreferenceCategory soundCategory = (PreferenceCategory) findPreference(KEY_SOUND);
368 for (int i = 0; i < TelephonyManager.getDefault().getSimCount(); i++) {
369 DefaultRingtonePreference ringtonePreference =
370 new DefaultRingtonePreference(mContext, null);
371 String title = getString(R.string.sim_ringtone_title, i + 1);
372 ringtonePreference.setTitle(title);
373 ringtonePreference.setSubId(i);
374 ringtonePreference.setOrder(0);
375 ringtonePreference.setRingtoneType(RingtoneManager.TYPE_RINGTONE);
376 soundCategory.addPreference(ringtonePreference);
377 mPhoneRingtonePreferences.add(ringtonePreference);
380 mPhoneRingtonePreferences.add(phoneRingtonePreference);
383 mNotificationRingtonePreference = root.findPreference(KEY_NOTIFICATION_RINGTONE);
386 private void lookupRingtoneNames() {
387 AsyncTask.execute(mLookupRingtoneNames);
390 private final Runnable mLookupRingtoneNames = new Runnable() {
393 if (mPhoneRingtonePreferences != null) {
394 ArrayList<CharSequence> summaries = new ArrayList<CharSequence>();
395 for (DefaultRingtonePreference preference : mPhoneRingtonePreferences) {
396 CharSequence summary = updateRingtoneName(
397 mContext, RingtoneManager.TYPE_RINGTONE, preference.getSubId());
398 summaries.add(summary);
400 if (!summaries.isEmpty()) {
401 mHandler.obtainMessage(H.UPDATE_PHONE_RINGTONE, summaries).sendToTarget();
404 if (mNotificationRingtonePreference != null) {
405 final CharSequence summary = updateRingtoneName(
406 mContext, RingtoneManager.TYPE_NOTIFICATION, -1);
407 if (summary != null) {
408 mHandler.obtainMessage(H.UPDATE_NOTIFICATION_RINGTONE, summary).sendToTarget();
414 private static CharSequence updateRingtoneName(Context context, int type, int subId) {
415 if (context == null) {
416 Log.e(TAG, "Unable to update ringtone name, no context provided");
420 if (type != RingtoneManager.TYPE_RINGTONE || subId <= 0) {
421 ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
423 ringtoneUri = RingtoneManager.getActualRingtoneUriBySubId(context, subId);
425 CharSequence summary = context.getString(com.android.internal.R.string.ringtone_unknown);
426 // Is it a silent ringtone?
427 if (ringtoneUri == null) {
428 summary = context.getString(com.android.internal.R.string.ringtone_silent);
430 Cursor cursor = null;
432 if (MediaStore.AUTHORITY.equals(ringtoneUri.getAuthority())) {
433 // Fetch the ringtone title from the media provider
434 cursor = context.getContentResolver().query(ringtoneUri,
435 new String[] { MediaStore.Audio.Media.TITLE }, null, null, null);
436 } else if (ContentResolver.SCHEME_CONTENT.equals(ringtoneUri.getScheme())) {
437 cursor = context.getContentResolver().query(ringtoneUri,
438 new String[] { OpenableColumns.DISPLAY_NAME }, null, null, null);
440 if (cursor != null) {
441 if (cursor.moveToFirst()) {
442 summary = cursor.getString(0);
445 } catch (SQLiteException sqle) {
446 // Unknown title for the ringtone
447 } catch (IllegalArgumentException iae) {
448 // Some other error retrieving the column from the provider
450 if (cursor != null) {
458 // === Increasing ringtone ===
460 private void initIncreasingRing(PreferenceCategory root) {
461 mIncreasingRing = (TwoStatePreference)
462 root.findPreference(CMSettings.System.INCREASING_RING);
463 mIncreasingRingVolume = (IncreasingRingVolumePreference)
464 root.findPreference(KEY_INCREASING_RING_VOLUME);
466 if (!mVoiceCapable) {
467 if (mIncreasingRing != null) {
468 root.removePreference(mIncreasingRing);
469 mIncreasingRing = null;
471 if (mIncreasingRingVolume != null) {
472 root.removePreference(mIncreasingRingVolume);
473 mIncreasingRingVolume = null;
476 if (mIncreasingRingVolume != null) {
477 mIncreasingRingVolume.setCallback(mIncreasingRingVolumeCallback);
482 // === Vibrate when ringing ===
484 private void initVibrateWhenRinging(PreferenceCategory root) {
485 mVibrateWhenRinging = (TwoStatePreference) root.findPreference(KEY_VIBRATE_WHEN_RINGING);
486 if (mVibrateWhenRinging == null) {
487 Log.i(TAG, "Preference not found: " + KEY_VIBRATE_WHEN_RINGING);
490 if (!mVoiceCapable || !Utils.isUserOwner()) {
491 root.removePreference(mVibrateWhenRinging);
492 mVibrateWhenRinging = null;
495 mVibrateWhenRinging.setPersistent(false);
496 updateVibrateWhenRinging();
497 mVibrateWhenRinging.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
499 public boolean onPreferenceChange(Preference preference, Object newValue) {
500 final boolean val = (Boolean) newValue;
501 return Settings.System.putInt(getContentResolver(),
502 Settings.System.VIBRATE_WHEN_RINGING,
508 private void updateVibrateWhenRinging() {
509 if (mVibrateWhenRinging == null) return;
510 mVibrateWhenRinging.setChecked(Settings.System.getInt(getContentResolver(),
511 Settings.System.VIBRATE_WHEN_RINGING, 0) != 0);
514 private boolean isSecureNotificationsDisabled() {
515 final DevicePolicyManager dpm =
516 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
517 return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
518 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0;
521 private boolean isUnredactedNotificationsDisabled() {
522 final DevicePolicyManager dpm =
523 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
524 return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
525 & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0;
528 // === Notification listeners ===
530 private void refreshNotificationListeners() {
531 if (mNotificationAccess != null) {
532 final int n = NotificationAccessSettings.getEnabledListenersCount(mContext);
534 mNotificationAccess.setSummary(getResources().getString(
535 R.string.manage_notification_access_summary_zero));
537 mNotificationAccess.setSummary(String.format(getResources().getQuantityString(
538 R.plurals.manage_notification_access_summary_nonzero,
546 private final class SettingsObserver extends ContentObserver {
547 private final Uri VIBRATE_WHEN_RINGING_URI =
548 Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING);
549 private final Uri NOTIFICATION_LIGHT_PULSE_URI =
550 Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
551 private final Uri LOCK_SCREEN_PRIVATE_URI =
552 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
553 private final Uri LOCK_SCREEN_SHOW_URI =
554 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
555 private final Uri VOLUME_LINK_NOTIFICATION_URI =
556 Settings.Secure.getUriFor(Settings.Secure.VOLUME_LINK_NOTIFICATION);
558 public SettingsObserver() {
562 public void register(boolean register) {
563 final ContentResolver cr = getContentResolver();
565 cr.registerContentObserver(VIBRATE_WHEN_RINGING_URI, false, this);
566 cr.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this);
567 cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this);
568 cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this);
569 cr.registerContentObserver(VOLUME_LINK_NOTIFICATION_URI, false, this);
571 cr.unregisterContentObserver(this);
576 public void onChange(boolean selfChange, Uri uri) {
577 super.onChange(selfChange, uri);
578 if (VIBRATE_WHEN_RINGING_URI.equals(uri)) {
579 updateVibrateWhenRinging();
581 if (VOLUME_LINK_NOTIFICATION_URI.equals(uri)) {
582 updateNotificationPreferenceState();
587 private final class H extends Handler {
588 private static final int UPDATE_PHONE_RINGTONE = 1;
589 private static final int UPDATE_NOTIFICATION_RINGTONE = 2;
590 private static final int STOP_SAMPLE = 3;
591 private static final int UPDATE_EFFECTS_SUPPRESSOR = 4;
592 private static final int UPDATE_RINGER_MODE = 5;
595 super(Looper.getMainLooper());
599 public void handleMessage(Message msg) {
601 case UPDATE_PHONE_RINGTONE:
602 ArrayList<CharSequence> summaries = (ArrayList<CharSequence>) msg.obj;
603 for (int i = 0; i < summaries.size(); i++) {
604 Preference preference = mPhoneRingtonePreferences.get(i);
605 preference.setSummary(summaries.get(i));
608 case UPDATE_NOTIFICATION_RINGTONE:
609 mNotificationRingtonePreference.setSummary((CharSequence) msg.obj);
612 mVolumeCallback.stopSample();
613 if (mIncreasingRingVolume != null) {
614 mIncreasingRingVolume.stopSample();
617 case UPDATE_EFFECTS_SUPPRESSOR:
618 updateEffectsSuppressor();
620 case UPDATE_RINGER_MODE:
627 private class Receiver extends BroadcastReceiver {
628 private boolean mRegistered;
630 public void register(boolean register) {
631 if (mRegistered == register) return;
633 final IntentFilter filter = new IntentFilter();
634 filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
635 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
636 mContext.registerReceiver(this, filter);
638 mContext.unregisterReceiver(this);
640 mRegistered = register;
644 public void onReceive(Context context, Intent intent) {
645 final String action = intent.getAction();
646 if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(action)) {
647 mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR);
648 } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
649 mHandler.sendEmptyMessage(H.UPDATE_RINGER_MODE);
656 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
657 new BaseSearchIndexProvider() {
658 private boolean mHasVibratorIntensity;
661 public void prepare() {
665 public List<SearchIndexableResource> getXmlResourcesToIndex(
666 Context context, boolean enabled) {
667 final SearchIndexableResource sir = new SearchIndexableResource(context);
668 sir.xmlResId = R.xml.sounds;
669 return Arrays.asList(sir);
672 public List<String> getNonIndexableKeys(Context context) {
673 final ArrayList<String> rt = new ArrayList<String>();
674 if (Utils.isVoiceCapable(context)) {
675 rt.add(KEY_NOTIFICATION_VOLUME);
677 rt.add(KEY_RING_VOLUME);
678 rt.add(KEY_PHONE_RINGTONE);
679 rt.add(KEY_WIFI_DISPLAY);
680 rt.add(KEY_VIBRATE_WHEN_RINGING);
682 Vibrator vib = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
683 if (vib == null || !vib.hasVibrator()) {
686 CMHardwareManager hardware = CMHardwareManager.getInstance(context);
687 if (!hardware.isSupported(CMHardwareManager.FEATURE_VIBRATOR)) {
688 rt.add(KEY_VIBRATION_INTENSITY);