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.dialer.app.settings; 18 19 import android.content.Context; 20 import android.media.RingtoneManager; 21 import android.os.Build; 22 import android.os.Bundle; 23 import android.os.Handler; 24 import android.os.Message; 25 import android.os.Vibrator; 26 import android.preference.ListPreference; 27 import android.preference.Preference; 28 import android.preference.PreferenceFragment; 29 import android.preference.PreferenceScreen; 30 import android.preference.SwitchPreference; 31 import android.provider.Settings; 32 import android.telephony.CarrierConfigManager; 33 import android.telephony.TelephonyManager; 34 import android.widget.Toast; 35 import com.android.dialer.app.R; 36 import com.android.dialer.compat.SdkVersionOverride; 37 import com.android.dialer.util.SettingsUtil; 38 39 public class SoundSettingsFragment extends PreferenceFragment 40 implements Preference.OnPreferenceChangeListener { 41 42 private static final int NO_DTMF_TONE = 0; 43 private static final int PLAY_DTMF_TONE = 1; 44 45 private static final int NO_VIBRATION_FOR_CALLS = 0; 46 private static final int DO_VIBRATION_FOR_CALLS = 1; 47 48 private static final int DTMF_TONE_TYPE_NORMAL = 0; 49 50 private static final int MSG_UPDATE_RINGTONE_SUMMARY = 1; 51 52 private Preference mRingtonePreference; 53 private final Handler mRingtoneLookupComplete = 54 new Handler() { 55 @Override 56 public void handleMessage(Message msg) { 57 switch (msg.what) { 58 case MSG_UPDATE_RINGTONE_SUMMARY: 59 mRingtonePreference.setSummary((CharSequence) msg.obj); 60 break; 61 } 62 } 63 }; 64 private final Runnable mRingtoneLookupRunnable = 65 new Runnable() { 66 @Override 67 public void run() { 68 updateRingtonePreferenceSummary(); 69 } 70 }; 71 private SwitchPreference mVibrateWhenRinging; 72 private SwitchPreference mPlayDtmfTone; 73 private ListPreference mDtmfToneLength; 74 75 @Override getContext()76 public Context getContext() { 77 return getActivity(); 78 } 79 80 @Override onCreate(Bundle savedInstanceState)81 public void onCreate(Bundle savedInstanceState) { 82 super.onCreate(savedInstanceState); 83 84 addPreferencesFromResource(R.xml.sound_settings); 85 86 Context context = getActivity(); 87 88 mRingtonePreference = findPreference(context.getString(R.string.ringtone_preference_key)); 89 mVibrateWhenRinging = 90 (SwitchPreference) findPreference(context.getString(R.string.vibrate_on_preference_key)); 91 mPlayDtmfTone = 92 (SwitchPreference) findPreference(context.getString(R.string.play_dtmf_preference_key)); 93 mDtmfToneLength = 94 (ListPreference) 95 findPreference(context.getString(R.string.dtmf_tone_length_preference_key)); 96 97 if (hasVibrator()) { 98 mVibrateWhenRinging.setOnPreferenceChangeListener(this); 99 } else { 100 getPreferenceScreen().removePreference(mVibrateWhenRinging); 101 mVibrateWhenRinging = null; 102 } 103 104 mPlayDtmfTone.setOnPreferenceChangeListener(this); 105 mPlayDtmfTone.setChecked(shouldPlayDtmfTone()); 106 107 TelephonyManager telephonyManager = 108 (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); 109 if (SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.M) >= Build.VERSION_CODES.M 110 && telephonyManager.canChangeDtmfToneLength() 111 && (telephonyManager.isWorldPhone() || !shouldHideCarrierSettings())) { 112 mDtmfToneLength.setOnPreferenceChangeListener(this); 113 mDtmfToneLength.setValueIndex( 114 Settings.System.getInt( 115 context.getContentResolver(), 116 Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 117 DTMF_TONE_TYPE_NORMAL)); 118 } else { 119 getPreferenceScreen().removePreference(mDtmfToneLength); 120 mDtmfToneLength = null; 121 } 122 } 123 124 @Override onResume()125 public void onResume() { 126 super.onResume(); 127 128 if (!Settings.System.canWrite(getContext())) { 129 // If the user launches this setting fragment, then toggles the WRITE_SYSTEM_SETTINGS 130 // AppOp, then close the fragment since there is nothing useful to do. 131 getActivity().onBackPressed(); 132 return; 133 } 134 135 if (mVibrateWhenRinging != null) { 136 mVibrateWhenRinging.setChecked(shouldVibrateWhenRinging()); 137 } 138 139 // Lookup the ringtone name asynchronously. 140 new Thread(mRingtoneLookupRunnable).start(); 141 } 142 143 /** 144 * Supports onPreferenceChangeListener to look for preference changes. 145 * 146 * @param preference The preference to be changed 147 * @param objValue The value of the selection, NOT its localized display value. 148 */ 149 @Override onPreferenceChange(Preference preference, Object objValue)150 public boolean onPreferenceChange(Preference preference, Object objValue) { 151 if (!Settings.System.canWrite(getContext())) { 152 // A user shouldn't be able to get here, but this protects against monkey crashes. 153 Toast.makeText( 154 getContext(), 155 getResources().getString(R.string.toast_cannot_write_system_settings), 156 Toast.LENGTH_SHORT) 157 .show(); 158 return true; 159 } 160 if (preference == mVibrateWhenRinging) { 161 boolean doVibrate = (Boolean) objValue; 162 Settings.System.putInt( 163 getActivity().getContentResolver(), 164 Settings.System.VIBRATE_WHEN_RINGING, 165 doVibrate ? DO_VIBRATION_FOR_CALLS : NO_VIBRATION_FOR_CALLS); 166 } else if (preference == mDtmfToneLength) { 167 int index = mDtmfToneLength.findIndexOfValue((String) objValue); 168 Settings.System.putInt( 169 getActivity().getContentResolver(), Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, index); 170 } 171 return true; 172 } 173 174 /** Click listener for toggle events. */ 175 @Override onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)176 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 177 if (!Settings.System.canWrite(getContext())) { 178 Toast.makeText( 179 getContext(), 180 getResources().getString(R.string.toast_cannot_write_system_settings), 181 Toast.LENGTH_SHORT) 182 .show(); 183 return true; 184 } 185 if (preference == mPlayDtmfTone) { 186 Settings.System.putInt( 187 getActivity().getContentResolver(), 188 Settings.System.DTMF_TONE_WHEN_DIALING, 189 mPlayDtmfTone.isChecked() ? PLAY_DTMF_TONE : NO_DTMF_TONE); 190 } 191 return true; 192 } 193 194 /** Updates the summary text on the ringtone preference with the name of the ringtone. */ updateRingtonePreferenceSummary()195 private void updateRingtonePreferenceSummary() { 196 SettingsUtil.updateRingtoneName( 197 getActivity(), 198 mRingtoneLookupComplete, 199 RingtoneManager.TYPE_RINGTONE, 200 mRingtonePreference.getKey(), 201 MSG_UPDATE_RINGTONE_SUMMARY); 202 } 203 204 /** 205 * Obtain the value for "vibrate when ringing" setting. The default value is false. 206 * 207 * <p>Watch out: if the setting is missing in the device, this will try obtaining the old "vibrate 208 * on ring" setting from AudioManager, and save the previous setting to the new one. 209 */ shouldVibrateWhenRinging()210 private boolean shouldVibrateWhenRinging() { 211 int vibrateWhenRingingSetting = 212 Settings.System.getInt( 213 getActivity().getContentResolver(), 214 Settings.System.VIBRATE_WHEN_RINGING, 215 NO_VIBRATION_FOR_CALLS); 216 return hasVibrator() && (vibrateWhenRingingSetting == DO_VIBRATION_FOR_CALLS); 217 } 218 219 /** Obtains the value for dialpad/DTMF tones. The default value is true. */ shouldPlayDtmfTone()220 private boolean shouldPlayDtmfTone() { 221 int dtmfToneSetting = 222 Settings.System.getInt( 223 getActivity().getContentResolver(), 224 Settings.System.DTMF_TONE_WHEN_DIALING, 225 PLAY_DTMF_TONE); 226 return dtmfToneSetting == PLAY_DTMF_TONE; 227 } 228 229 /** Whether the device hardware has a vibrator. */ hasVibrator()230 private boolean hasVibrator() { 231 Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE); 232 return vibrator != null && vibrator.hasVibrator(); 233 } 234 shouldHideCarrierSettings()235 private boolean shouldHideCarrierSettings() { 236 CarrierConfigManager configManager = 237 (CarrierConfigManager) getActivity().getSystemService(Context.CARRIER_CONFIG_SERVICE); 238 return configManager 239 .getConfig() 240 .getBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL); 241 } 242 } 243