1 /* 2 * Copyright (C) 2015 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; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.os.Bundle; 26 import android.os.PersistableBundle; 27 import android.support.v7.preference.ListPreference; 28 import android.support.v7.preference.Preference; 29 import android.support.v7.preference.PreferenceScreen; 30 import android.telephony.CarrierConfigManager; 31 import android.telephony.PhoneStateListener; 32 import android.telephony.TelephonyManager; 33 import android.util.Log; 34 import android.widget.Switch; 35 import android.widget.TextView; 36 37 import com.android.ims.ImsConfig; 38 import com.android.ims.ImsManager; 39 import com.android.internal.logging.MetricsLogger; 40 import com.android.internal.logging.MetricsProto.MetricsEvent; 41 import com.android.internal.telephony.Phone; 42 import com.android.settings.widget.SwitchBar; 43 44 /** 45 * "Wi-Fi Calling settings" screen. This preference screen lets you 46 * enable/disable Wi-Fi Calling and change Wi-Fi Calling mode. 47 */ 48 public class WifiCallingSettings extends SettingsPreferenceFragment 49 implements SwitchBar.OnSwitchChangeListener, 50 Preference.OnPreferenceChangeListener { 51 52 private static final String TAG = "WifiCallingSettings"; 53 54 //String keys for preference lookup 55 private static final String BUTTON_WFC_MODE = "wifi_calling_mode"; 56 57 //UI objects 58 private SwitchBar mSwitchBar; 59 private Switch mSwitch; 60 private ListPreference mButtonWfcMode; 61 private TextView mEmptyView; 62 63 private boolean mValidListener = false; 64 private boolean mEditableWfcMode = true; 65 66 private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 67 /* 68 * Enable/disable controls when in/out of a call and depending on 69 * TTY mode and TTY support over VoLTE. 70 * @see android.telephony.PhoneStateListener#onCallStateChanged(int, 71 * java.lang.String) 72 */ 73 @Override 74 public void onCallStateChanged(int state, String incomingNumber) { 75 final SettingsActivity activity = (SettingsActivity) getActivity(); 76 boolean isNonTtyOrTtyOnVolteEnabled = ImsManager 77 .isNonTtyOrTtyOnVolteEnabled(activity); 78 final SwitchBar switchBar = activity.getSwitchBar(); 79 boolean isWfcEnabled = switchBar.getSwitch().isChecked() 80 && isNonTtyOrTtyOnVolteEnabled; 81 82 switchBar.setEnabled((state == TelephonyManager.CALL_STATE_IDLE) 83 && isNonTtyOrTtyOnVolteEnabled); 84 85 Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE); 86 if (pref != null) { 87 pref.setEnabled(isWfcEnabled 88 && (state == TelephonyManager.CALL_STATE_IDLE)); 89 } 90 } 91 }; 92 93 @Override onActivityCreated(Bundle savedInstanceState)94 public void onActivityCreated(Bundle savedInstanceState) { 95 super.onActivityCreated(savedInstanceState); 96 97 final SettingsActivity activity = (SettingsActivity) getActivity(); 98 99 mSwitchBar = activity.getSwitchBar(); 100 mSwitch = mSwitchBar.getSwitch(); 101 mSwitchBar.show(); 102 103 mEmptyView = (TextView) getView().findViewById(android.R.id.empty); 104 setEmptyView(mEmptyView); 105 mEmptyView.setText(R.string.wifi_calling_off_explanation); 106 } 107 108 @Override onDestroyView()109 public void onDestroyView() { 110 super.onDestroyView(); 111 mSwitchBar.hide(); 112 } 113 showAlert(Intent intent)114 private void showAlert(Intent intent) { 115 Context context = getActivity(); 116 117 CharSequence title = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_TITLE); 118 CharSequence message = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_MESSAGE); 119 120 AlertDialog.Builder builder = new AlertDialog.Builder(context); 121 builder.setMessage(message) 122 .setTitle(title) 123 .setIcon(android.R.drawable.ic_dialog_alert) 124 .setPositiveButton(android.R.string.ok, null); 125 AlertDialog dialog = builder.create(); 126 dialog.show(); 127 } 128 129 private IntentFilter mIntentFilter; 130 131 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 132 @Override 133 public void onReceive(Context context, Intent intent) { 134 String action = intent.getAction(); 135 if (action.equals(ImsManager.ACTION_IMS_REGISTRATION_ERROR)) { 136 // If this fragment is active then we are immediately 137 // showing alert on screen. There is no need to add 138 // notification in this case. 139 // 140 // In order to communicate to ImsPhone that it should 141 // not show notification, we are changing result code here. 142 setResultCode(Activity.RESULT_CANCELED); 143 144 // UX requirement is to disable WFC in case of "permanent" registration failures. 145 mSwitch.setChecked(false); 146 147 showAlert(intent); 148 } 149 } 150 }; 151 152 @Override getMetricsCategory()153 protected int getMetricsCategory() { 154 return MetricsEvent.WIFI_CALLING; 155 } 156 157 @Override onCreate(Bundle savedInstanceState)158 public void onCreate(Bundle savedInstanceState) { 159 super.onCreate(savedInstanceState); 160 161 addPreferencesFromResource(R.xml.wifi_calling_settings); 162 163 mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE); 164 mButtonWfcMode.setOnPreferenceChangeListener(this); 165 166 mIntentFilter = new IntentFilter(); 167 mIntentFilter.addAction(ImsManager.ACTION_IMS_REGISTRATION_ERROR); 168 169 CarrierConfigManager configManager = (CarrierConfigManager) 170 getSystemService(Context.CARRIER_CONFIG_SERVICE); 171 boolean isWifiOnlySupported = true; 172 if (configManager != null) { 173 PersistableBundle b = configManager.getConfig(); 174 if (b != null) { 175 mEditableWfcMode = b.getBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL); 176 isWifiOnlySupported = b.getBoolean( 177 CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, true); 178 } 179 } 180 181 if (!isWifiOnlySupported) { 182 mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only); 183 mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only); 184 } 185 } 186 187 @Override onResume()188 public void onResume() { 189 super.onResume(); 190 191 final Context context = getActivity(); 192 193 if (ImsManager.isWfcEnabledByPlatform(context)) { 194 TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 195 tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); 196 197 mSwitchBar.addOnSwitchChangeListener(this); 198 199 mValidListener = true; 200 } 201 202 // NOTE: Buttons will be enabled/disabled in mPhoneStateListener 203 boolean wfcEnabled = ImsManager.isWfcEnabledByUser(context) 204 && ImsManager.isNonTtyOrTtyOnVolteEnabled(context); 205 mSwitch.setChecked(wfcEnabled); 206 int wfcMode = ImsManager.getWfcMode(context); 207 mButtonWfcMode.setValue(Integer.toString(wfcMode)); 208 updateButtonWfcMode(context, wfcEnabled, wfcMode); 209 210 context.registerReceiver(mIntentReceiver, mIntentFilter); 211 212 Intent intent = getActivity().getIntent(); 213 if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) { 214 showAlert(intent); 215 } 216 } 217 218 @Override onPause()219 public void onPause() { 220 super.onPause(); 221 222 final Context context = getActivity(); 223 224 if (mValidListener) { 225 mValidListener = false; 226 227 TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 228 tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); 229 230 mSwitchBar.removeOnSwitchChangeListener(this); 231 } 232 233 context.unregisterReceiver(mIntentReceiver); 234 } 235 236 /** 237 * Listens to the state change of the switch. 238 */ 239 @Override onSwitchChanged(Switch switchView, boolean isChecked)240 public void onSwitchChanged(Switch switchView, boolean isChecked) { 241 final Context context = getActivity(); 242 243 ImsManager.setWfcSetting(context, isChecked); 244 245 int wfcMode = ImsManager.getWfcMode(context); 246 updateButtonWfcMode(context, isChecked, wfcMode); 247 if (isChecked) { 248 MetricsLogger.action(getActivity(), getMetricsCategory(), wfcMode); 249 } else { 250 MetricsLogger.action(getActivity(), getMetricsCategory(), -1); 251 } 252 } 253 updateButtonWfcMode(Context context, boolean wfcEnabled, int wfcMode)254 private void updateButtonWfcMode(Context context, boolean wfcEnabled, int wfcMode) { 255 mButtonWfcMode.setSummary(getWfcModeSummary(context, wfcMode)); 256 mButtonWfcMode.setEnabled(wfcEnabled); 257 258 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 259 if (wfcEnabled) { 260 preferenceScreen.addPreference(mButtonWfcMode); 261 } else { 262 preferenceScreen.removePreference(mButtonWfcMode); 263 } 264 preferenceScreen.setEnabled(mEditableWfcMode); 265 } 266 267 @Override onPreferenceChange(Preference preference, Object newValue)268 public boolean onPreferenceChange(Preference preference, Object newValue) { 269 final Context context = getActivity(); 270 if (preference == mButtonWfcMode) { 271 mButtonWfcMode.setValue((String) newValue); 272 int buttonMode = Integer.valueOf((String) newValue); 273 int currentMode = ImsManager.getWfcMode(context); 274 if (buttonMode != currentMode) { 275 ImsManager.setWfcMode(context, buttonMode); 276 mButtonWfcMode.setSummary(getWfcModeSummary(context, buttonMode)); 277 MetricsLogger.action(getActivity(), getMetricsCategory(), buttonMode); 278 } 279 } 280 return true; 281 } 282 getWfcModeSummary(Context context, int wfcMode)283 static int getWfcModeSummary(Context context, int wfcMode) { 284 int resId = com.android.internal.R.string.wifi_calling_off_summary; 285 if (ImsManager.isWfcEnabledByUser(context)) { 286 switch (wfcMode) { 287 case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY: 288 resId = com.android.internal.R.string.wfc_mode_wifi_only_summary; 289 break; 290 case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED: 291 resId = com.android.internal.R.string.wfc_mode_cellular_preferred_summary; 292 break; 293 case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED: 294 resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary; 295 break; 296 default: 297 Log.e(TAG, "Unexpected WFC mode value: " + wfcMode); 298 } 299 } 300 return resId; 301 } 302 } 303