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