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