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