1 /* 2 * Copyright (C) 2017 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.wifi.calling; 18 19 import android.app.Activity; 20 import android.app.settings.SettingsEnums; 21 import android.content.BroadcastReceiver; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.res.Resources; 27 import android.os.Bundle; 28 import android.os.PersistableBundle; 29 import android.telephony.CarrierConfigManager; 30 import android.telephony.PhoneStateListener; 31 import android.telephony.SubscriptionManager; 32 import android.telephony.TelephonyCallback; 33 import android.telephony.TelephonyManager; 34 import android.telephony.ims.ImsManager; 35 import android.telephony.ims.ImsMmTelManager; 36 import android.telephony.ims.ProvisioningManager; 37 import android.text.TextUtils; 38 import android.util.Log; 39 import android.view.LayoutInflater; 40 import android.view.View; 41 import android.view.ViewGroup; 42 import android.widget.Switch; 43 import android.widget.TextView; 44 45 import androidx.appcompat.app.AlertDialog; 46 import androidx.preference.Preference; 47 import androidx.preference.Preference.OnPreferenceClickListener; 48 import androidx.preference.PreferenceScreen; 49 50 import com.android.ims.ImsConfig; 51 import com.android.internal.annotations.VisibleForTesting; 52 import com.android.internal.telephony.Phone; 53 import com.android.settings.R; 54 import com.android.settings.SettingsActivity; 55 import com.android.settings.SettingsPreferenceFragment; 56 import com.android.settings.Utils; 57 import com.android.settings.core.SubSettingLauncher; 58 import com.android.settings.network.ims.WifiCallingQueryImsState; 59 import com.android.settings.widget.SettingsMainSwitchBar; 60 import com.android.settings.wifi.calling.LinkifyDescriptionPreference; 61 import com.android.settingslib.widget.OnMainSwitchChangeListener; 62 63 import java.util.List; 64 65 /** 66 * This is the inner class of {@link WifiCallingSettings} fragment. 67 * The preference screen lets you enable/disable Wi-Fi Calling and change Wi-Fi Calling mode. 68 */ 69 public class WifiCallingSettingsForSub extends SettingsPreferenceFragment 70 implements OnMainSwitchChangeListener, 71 Preference.OnPreferenceChangeListener { 72 private static final String TAG = "WifiCallingForSub"; 73 74 //String keys for preference lookup 75 private static final String BUTTON_WFC_MODE = "wifi_calling_mode"; 76 private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode"; 77 private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key"; 78 private static final String PREFERENCE_NO_OPTIONS_DESC = "no_options_description"; 79 80 @VisibleForTesting 81 static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1; 82 @VisibleForTesting 83 static final int REQUEST_CHECK_WFC_DISCLAIMER = 2; 84 85 public static final String EXTRA_LAUNCH_CARRIER_APP = "EXTRA_LAUNCH_CARRIER_APP"; 86 public static final String EXTRA_SUB_ID = "EXTRA_SUB_ID"; 87 88 protected static final String FRAGMENT_BUNDLE_SUBID = "subId"; 89 90 public static final int LAUCH_APP_ACTIVATE = 0; 91 public static final int LAUCH_APP_UPDATE = 1; 92 93 //UI objects 94 private SettingsMainSwitchBar mSwitchBar; 95 private ListWithEntrySummaryPreference mButtonWfcMode; 96 private ListWithEntrySummaryPreference mButtonWfcRoamingMode; 97 private Preference mUpdateAddress; 98 99 private boolean mValidListener = false; 100 private boolean mEditableWfcMode = true; 101 private boolean mEditableWfcRoamingMode = true; 102 private boolean mUseWfcHomeModeForRoaming = false; 103 104 private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 105 private ImsMmTelManager mImsMmTelManager; 106 private ProvisioningManager mProvisioningManager; 107 private TelephonyManager mTelephonyManager; 108 109 private final PhoneTelephonyCallback mTelephonyCallback = new PhoneTelephonyCallback(); 110 111 private class PhoneTelephonyCallback extends TelephonyCallback implements 112 TelephonyCallback.CallStateListener { 113 /* 114 * Enable/disable controls when in/out of a call and depending on 115 * TTY mode and TTY support over VoLTE. 116 * @see android.telephony.PhoneStateListener#onCallStateChanged(int, 117 * java.lang.String) 118 */ 119 @Override onCallStateChanged(int state)120 public void onCallStateChanged(int state) { 121 final SettingsActivity activity = (SettingsActivity) getActivity(); 122 final boolean isNonTtyOrTtyOnVolteEnabled = 123 queryImsState(WifiCallingSettingsForSub.this.mSubId).isAllowUserControl(); 124 final boolean isWfcEnabled = mSwitchBar.isChecked() 125 && isNonTtyOrTtyOnVolteEnabled; 126 boolean isCallStateIdle = getTelephonyManagerForSub( 127 WifiCallingSettingsForSub.this.mSubId).getCallState() 128 == TelephonyManager.CALL_STATE_IDLE; 129 mSwitchBar.setEnabled(isCallStateIdle 130 && isNonTtyOrTtyOnVolteEnabled); 131 132 boolean isWfcModeEditable = true; 133 boolean isWfcRoamingModeEditable = false; 134 final CarrierConfigManager configManager = (CarrierConfigManager) 135 activity.getSystemService(Context.CARRIER_CONFIG_SERVICE); 136 if (configManager != null) { 137 PersistableBundle b = 138 configManager.getConfigForSubId(WifiCallingSettingsForSub.this.mSubId); 139 if (b != null) { 140 isWfcModeEditable = b.getBoolean( 141 CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL); 142 isWfcRoamingModeEditable = b.getBoolean( 143 CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL); 144 } 145 } 146 147 final Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE); 148 if (pref != null) { 149 pref.setEnabled(isWfcEnabled && isWfcModeEditable 150 && isCallStateIdle); 151 } 152 final Preference pref_roam = 153 getPreferenceScreen().findPreference(BUTTON_WFC_ROAMING_MODE); 154 if (pref_roam != null) { 155 pref_roam.setEnabled(isWfcEnabled && isWfcRoamingModeEditable 156 && isCallStateIdle); 157 } 158 } 159 } 160 161 /* 162 * Launch carrier emergency address management activity 163 */ 164 private final OnPreferenceClickListener mUpdateAddressListener = 165 preference -> { 166 final Intent carrierAppIntent = getCarrierActivityIntent(); 167 if (carrierAppIntent != null) { 168 carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE); 169 startActivity(carrierAppIntent); 170 } 171 return true; 172 }; 173 174 private final ProvisioningManager.Callback mProvisioningCallback = 175 new ProvisioningManager.Callback() { 176 @Override 177 public void onProvisioningIntChanged(int item, int value) { 178 if (item == ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED 179 || item == ImsConfig.ConfigConstants.VLT_SETTING_ENABLED) { 180 // The provisioning policy might have changed. Update the body to make sure 181 // this change takes effect if needed. 182 updateBody(); 183 } 184 } 185 }; 186 187 @Override onActivityCreated(Bundle savedInstanceState)188 public void onActivityCreated(Bundle savedInstanceState) { 189 super.onActivityCreated(savedInstanceState); 190 191 mSwitchBar = getView().findViewById(R.id.switch_bar); 192 mSwitchBar.show(); 193 } 194 195 @Override onDestroyView()196 public void onDestroyView() { 197 super.onDestroyView(); 198 mSwitchBar.hide(); 199 } 200 201 @VisibleForTesting showAlert(Intent intent)202 void showAlert(Intent intent) { 203 final Context context = getActivity(); 204 205 final CharSequence title = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_TITLE); 206 final CharSequence message = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_MESSAGE); 207 208 final AlertDialog.Builder builder = new AlertDialog.Builder(context); 209 builder.setMessage(message) 210 .setTitle(title) 211 .setIcon(android.R.drawable.ic_dialog_alert) 212 .setPositiveButton(android.R.string.ok, null); 213 final AlertDialog dialog = builder.create(); 214 dialog.show(); 215 } 216 217 private IntentFilter mIntentFilter; 218 219 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 220 @Override 221 public void onReceive(Context context, Intent intent) { 222 final String action = intent.getAction(); 223 if (action.equals(ImsManager.ACTION_WFC_IMS_REGISTRATION_ERROR)) { 224 // If this fragment is active then we are immediately 225 // showing alert on screen. There is no need to add 226 // notification in this case. 227 // 228 // In order to communicate to ImsPhone that it should 229 // not show notification, we are changing result code here. 230 setResultCode(Activity.RESULT_CANCELED); 231 232 showAlert(intent); 233 } 234 } 235 }; 236 237 @Override getMetricsCategory()238 public int getMetricsCategory() { 239 return SettingsEnums.WIFI_CALLING_FOR_SUB; 240 } 241 242 @Override getHelpResource()243 public int getHelpResource() { 244 // Return 0 to suppress help icon. The help will be populated by parent page. 245 return 0; 246 } 247 248 @VisibleForTesting getTelephonyManagerForSub(int subId)249 TelephonyManager getTelephonyManagerForSub(int subId) { 250 if (mTelephonyManager == null) { 251 mTelephonyManager = getContext().getSystemService(TelephonyManager.class); 252 } 253 return mTelephonyManager.createForSubscriptionId(subId); 254 } 255 256 @VisibleForTesting queryImsState(int subId)257 WifiCallingQueryImsState queryImsState(int subId) { 258 return new WifiCallingQueryImsState(getContext(), subId); 259 } 260 261 @VisibleForTesting getImsProvisioningManager()262 ProvisioningManager getImsProvisioningManager() { 263 if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { 264 return null; 265 } 266 return ProvisioningManager.createForSubscriptionId(mSubId); 267 } 268 269 @VisibleForTesting getImsMmTelManager()270 ImsMmTelManager getImsMmTelManager() { 271 if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { 272 return null; 273 } 274 return ImsMmTelManager.createForSubscriptionId(mSubId); 275 } 276 277 @Override onCreate(Bundle savedInstanceState)278 public void onCreate(Bundle savedInstanceState) { 279 super.onCreate(savedInstanceState); 280 281 addPreferencesFromResource(R.xml.wifi_calling_settings); 282 283 // SubId should always be specified when creating this fragment. Either through 284 // fragment.setArguments() or through savedInstanceState. 285 if (getArguments() != null && getArguments().containsKey(FRAGMENT_BUNDLE_SUBID)) { 286 mSubId = getArguments().getInt(FRAGMENT_BUNDLE_SUBID); 287 } else if (savedInstanceState != null) { 288 mSubId = savedInstanceState.getInt( 289 FRAGMENT_BUNDLE_SUBID, SubscriptionManager.INVALID_SUBSCRIPTION_ID); 290 } 291 292 mProvisioningManager = getImsProvisioningManager(); 293 mImsMmTelManager = getImsMmTelManager(); 294 295 mButtonWfcMode = findPreference(BUTTON_WFC_MODE); 296 mButtonWfcMode.setOnPreferenceChangeListener(this); 297 298 mButtonWfcRoamingMode = findPreference(BUTTON_WFC_ROAMING_MODE); 299 mButtonWfcRoamingMode.setOnPreferenceChangeListener(this); 300 301 mUpdateAddress = findPreference(PREFERENCE_EMERGENCY_ADDRESS); 302 mUpdateAddress.setOnPreferenceClickListener(mUpdateAddressListener); 303 304 mIntentFilter = new IntentFilter(); 305 mIntentFilter.addAction(ImsManager.ACTION_WFC_IMS_REGISTRATION_ERROR); 306 307 updateDescriptionForOptions( 308 List.of(mButtonWfcMode, mButtonWfcRoamingMode, mUpdateAddress)); 309 } 310 311 @Override onSaveInstanceState(Bundle outState)312 public void onSaveInstanceState(Bundle outState) { 313 outState.putInt(FRAGMENT_BUNDLE_SUBID, mSubId); 314 super.onSaveInstanceState(outState); 315 } 316 317 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)318 public View onCreateView(LayoutInflater inflater, ViewGroup container, 319 Bundle savedInstanceState) { 320 321 final View view = inflater.inflate( 322 R.layout.wifi_calling_settings_preferences, container, false); 323 324 final ViewGroup prefs_container = view.findViewById(android.R.id.tabcontent); 325 Utils.prepareCustomPreferencesList(container, view, prefs_container, false); 326 final View prefs = super.onCreateView(inflater, prefs_container, savedInstanceState); 327 prefs_container.addView(prefs); 328 329 return view; 330 } 331 332 @VisibleForTesting isWfcProvisionedOnDevice()333 boolean isWfcProvisionedOnDevice() { 334 return queryImsState(mSubId).isWifiCallingProvisioned(); 335 } 336 updateBody()337 private void updateBody() { 338 if (!isWfcProvisionedOnDevice()) { 339 // This screen is not allowed to be shown due to provisioning policy and should 340 // therefore be closed. 341 finish(); 342 return; 343 } 344 345 final CarrierConfigManager configManager = (CarrierConfigManager) 346 getSystemService(Context.CARRIER_CONFIG_SERVICE); 347 boolean isWifiOnlySupported = true; 348 349 if (configManager != null) { 350 final PersistableBundle b = configManager.getConfigForSubId(mSubId); 351 if (b != null) { 352 mEditableWfcMode = b.getBoolean( 353 CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL); 354 mEditableWfcRoamingMode = b.getBoolean( 355 CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL); 356 mUseWfcHomeModeForRoaming = b.getBoolean( 357 CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, 358 false); 359 isWifiOnlySupported = b.getBoolean( 360 CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, true); 361 } 362 } 363 364 final Resources res = getResourcesForSubId(); 365 mButtonWfcMode.setTitle(res.getString(R.string.wifi_calling_mode_title)); 366 mButtonWfcMode.setDialogTitle(res.getString(R.string.wifi_calling_mode_dialog_title)); 367 mButtonWfcRoamingMode.setTitle(res.getString(R.string.wifi_calling_roaming_mode_title)); 368 mButtonWfcRoamingMode.setDialogTitle( 369 res.getString(R.string.wifi_calling_roaming_mode_dialog_title)); 370 371 if (isWifiOnlySupported) { 372 // Set string resources WITH option wifi only in mButtonWfcMode. 373 mButtonWfcMode.setEntries( 374 res.getStringArray(R.array.wifi_calling_mode_choices)); 375 mButtonWfcMode.setEntryValues(res.getStringArray(R.array.wifi_calling_mode_values)); 376 mButtonWfcMode.setEntrySummaries( 377 res.getStringArray(R.array.wifi_calling_mode_summaries)); 378 379 // Set string resources WITH option wifi only in mButtonWfcRoamingMode. 380 mButtonWfcRoamingMode.setEntries( 381 res.getStringArray(R.array.wifi_calling_mode_choices_v2)); 382 mButtonWfcRoamingMode.setEntryValues( 383 res.getStringArray(R.array.wifi_calling_mode_values)); 384 mButtonWfcRoamingMode.setEntrySummaries( 385 res.getStringArray(R.array.wifi_calling_mode_summaries)); 386 } else { 387 // Set string resources WITHOUT option wifi only in mButtonWfcMode. 388 mButtonWfcMode.setEntries( 389 res.getStringArray(R.array.wifi_calling_mode_choices_without_wifi_only)); 390 mButtonWfcMode.setEntryValues( 391 res.getStringArray(R.array.wifi_calling_mode_values_without_wifi_only)); 392 mButtonWfcMode.setEntrySummaries( 393 res.getStringArray(R.array.wifi_calling_mode_summaries_without_wifi_only)); 394 395 // Set string resources WITHOUT option wifi only in mButtonWfcRoamingMode. 396 mButtonWfcRoamingMode.setEntries( 397 res.getStringArray(R.array.wifi_calling_mode_choices_v2_without_wifi_only)); 398 mButtonWfcRoamingMode.setEntryValues( 399 res.getStringArray(R.array.wifi_calling_mode_values_without_wifi_only)); 400 mButtonWfcRoamingMode.setEntrySummaries( 401 res.getStringArray(R.array.wifi_calling_mode_summaries_without_wifi_only)); 402 } 403 404 // NOTE: Buttons will be enabled/disabled in mTelephonyCallback 405 final WifiCallingQueryImsState queryIms = queryImsState(mSubId); 406 final boolean wfcEnabled = queryIms.isEnabledByUser() 407 && queryIms.isAllowUserControl(); 408 mSwitchBar.setChecked(wfcEnabled); 409 final int wfcMode = mImsMmTelManager.getVoWiFiModeSetting(); 410 final int wfcRoamingMode = mImsMmTelManager.getVoWiFiRoamingModeSetting(); 411 mButtonWfcMode.setValue(Integer.toString(wfcMode)); 412 mButtonWfcRoamingMode.setValue(Integer.toString(wfcRoamingMode)); 413 updateButtonWfcMode(wfcEnabled, wfcMode, wfcRoamingMode); 414 } 415 416 @Override onResume()417 public void onResume() { 418 super.onResume(); 419 420 updateBody(); 421 422 final Context context = getActivity(); 423 if (queryImsState(mSubId).isWifiCallingSupported()) { 424 getTelephonyManagerForSub(mSubId).registerTelephonyCallback( 425 context.getMainExecutor(), mTelephonyCallback); 426 427 mSwitchBar.addOnSwitchChangeListener(this); 428 429 mValidListener = true; 430 } 431 432 context.registerReceiver(mIntentReceiver, mIntentFilter); 433 434 final Intent intent = getActivity().getIntent(); 435 if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) { 436 showAlert(intent); 437 } 438 439 // Register callback for provisioning changes. 440 registerProvisioningChangedCallback(); 441 } 442 443 @Override onPause()444 public void onPause() { 445 super.onPause(); 446 447 final Context context = getActivity(); 448 449 if (mValidListener) { 450 mValidListener = false; 451 452 getTelephonyManagerForSub(mSubId).unregisterTelephonyCallback(mTelephonyCallback); 453 454 mSwitchBar.removeOnSwitchChangeListener(this); 455 } 456 457 context.unregisterReceiver(mIntentReceiver); 458 459 // Remove callback for provisioning changes. 460 unregisterProvisioningChangedCallback(); 461 } 462 463 /** 464 * Listens to the state change of the switch. 465 */ 466 @Override onSwitchChanged(Switch switchView, boolean isChecked)467 public void onSwitchChanged(Switch switchView, boolean isChecked) { 468 Log.d(TAG, "onSwitchChanged(" + isChecked + ")"); 469 470 if (!isChecked) { 471 updateWfcMode(false); 472 return; 473 } 474 475 // Launch disclaimer fragment before turning on WFC 476 final Context context = getActivity(); 477 final Bundle args = new Bundle(); 478 args.putInt(EXTRA_SUB_ID, mSubId); 479 new SubSettingLauncher(context) 480 .setDestination(WifiCallingDisclaimerFragment.class.getName()) 481 .setArguments(args) 482 .setTitleRes(R.string.wifi_calling_settings_title) 483 .setSourceMetricsCategory(getMetricsCategory()) 484 .setResultListener(this, REQUEST_CHECK_WFC_DISCLAIMER) 485 .launch(); 486 } 487 488 /* 489 * Get the Intent to launch carrier emergency address management activity. 490 * Return null when no activity found. 491 */ getCarrierActivityIntent()492 private Intent getCarrierActivityIntent() { 493 // Retrive component name from carrier config 494 final CarrierConfigManager configManager = 495 getActivity().getSystemService(CarrierConfigManager.class); 496 if (configManager == null) return null; 497 498 final PersistableBundle bundle = configManager.getConfigForSubId(mSubId); 499 if (bundle == null) return null; 500 501 final String carrierApp = bundle.getString( 502 CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING); 503 if (TextUtils.isEmpty(carrierApp)) return null; 504 505 final ComponentName componentName = ComponentName.unflattenFromString(carrierApp); 506 if (componentName == null) return null; 507 508 // Build and return intent 509 final Intent intent = new Intent(); 510 intent.setComponent(componentName); 511 intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, mSubId); 512 return intent; 513 } 514 515 /* 516 * Turn on/off WFC mode with ImsManager and update UI accordingly 517 */ updateWfcMode(boolean wfcEnabled)518 private void updateWfcMode(boolean wfcEnabled) { 519 Log.i(TAG, "updateWfcMode(" + wfcEnabled + ")"); 520 mImsMmTelManager.setVoWiFiSettingEnabled(wfcEnabled); 521 522 final int wfcMode = mImsMmTelManager.getVoWiFiModeSetting(); 523 final int wfcRoamingMode = mImsMmTelManager.getVoWiFiRoamingModeSetting(); 524 updateButtonWfcMode(wfcEnabled, wfcMode, wfcRoamingMode); 525 if (wfcEnabled) { 526 mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), wfcMode); 527 } else { 528 mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), -1); 529 } 530 } 531 532 @Override onActivityResult(int requestCode, int resultCode, Intent data)533 public void onActivityResult(int requestCode, int resultCode, Intent data) { 534 super.onActivityResult(requestCode, resultCode, data); 535 536 Log.d(TAG, "WFC activity request = " + requestCode + " result = " + resultCode); 537 538 switch (requestCode) { 539 case REQUEST_CHECK_WFC_EMERGENCY_ADDRESS: 540 if (resultCode == Activity.RESULT_OK) { 541 updateWfcMode(true); 542 } 543 break; 544 case REQUEST_CHECK_WFC_DISCLAIMER: 545 if (resultCode == Activity.RESULT_OK) { 546 // Call address management activity before turning on WFC 547 final Intent carrierAppIntent = getCarrierActivityIntent(); 548 if (carrierAppIntent != null) { 549 carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE); 550 startActivityForResult(carrierAppIntent, 551 REQUEST_CHECK_WFC_EMERGENCY_ADDRESS); 552 } else { 553 updateWfcMode(true); 554 } 555 } 556 break; 557 default: 558 Log.e(TAG, "Unexpected request: " + requestCode); 559 break; 560 } 561 } 562 updateButtonWfcMode(boolean wfcEnabled, int wfcMode, int wfcRoamingMode)563 private void updateButtonWfcMode(boolean wfcEnabled, 564 int wfcMode, int wfcRoamingMode) { 565 mButtonWfcMode.setSummary(getWfcModeSummary(wfcMode)); 566 mButtonWfcMode.setEnabled(wfcEnabled && mEditableWfcMode); 567 // mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value. 568 mButtonWfcRoamingMode.setEnabled(wfcEnabled && mEditableWfcRoamingMode); 569 570 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 571 final boolean updateAddressEnabled = (getCarrierActivityIntent() != null); 572 if (wfcEnabled) { 573 // Don't show WFC (home) preference if it's not editable. 574 mButtonWfcMode.setVisible(mEditableWfcMode); 575 // Don't show WFC roaming preference if it's not editable. 576 mButtonWfcRoamingMode.setVisible( 577 mEditableWfcRoamingMode && !mUseWfcHomeModeForRoaming); 578 mUpdateAddress.setVisible(updateAddressEnabled); 579 } else { 580 mButtonWfcMode.setVisible(false); 581 mButtonWfcRoamingMode.setVisible(false); 582 mUpdateAddress.setVisible(false); 583 } 584 updateDescriptionForOptions( 585 List.of(mButtonWfcMode, mButtonWfcRoamingMode, mUpdateAddress)); 586 } 587 updateDescriptionForOptions(List<Preference> visibleOptions)588 private void updateDescriptionForOptions(List<Preference> visibleOptions) { 589 LinkifyDescriptionPreference pref = findPreference(PREFERENCE_NO_OPTIONS_DESC); 590 if (pref == null) { 591 return; 592 } 593 594 boolean optionsAvailable = visibleOptions.stream().anyMatch(Preference::isVisible); 595 if (!optionsAvailable) { 596 final Resources res = getResourcesForSubId(); 597 String emptyViewText = res.getString(R.string.wifi_calling_off_explanation, 598 res.getString(R.string.wifi_calling_off_explanation_2)); 599 pref.setSummary(emptyViewText); 600 } 601 pref.setVisible(!optionsAvailable); 602 } 603 604 @Override onPreferenceChange(Preference preference, Object newValue)605 public boolean onPreferenceChange(Preference preference, Object newValue) { 606 if (preference == mButtonWfcMode) { 607 Log.d(TAG, "onPreferenceChange mButtonWfcMode " + newValue); 608 mButtonWfcMode.setValue((String) newValue); 609 final int buttonMode = Integer.valueOf((String) newValue); 610 final int currentWfcMode = mImsMmTelManager.getVoWiFiModeSetting(); 611 if (buttonMode != currentWfcMode) { 612 mImsMmTelManager.setVoWiFiModeSetting(buttonMode); 613 mButtonWfcMode.setSummary(getWfcModeSummary(buttonMode)); 614 mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode); 615 616 if (mUseWfcHomeModeForRoaming) { 617 mImsMmTelManager.setVoWiFiRoamingModeSetting(buttonMode); 618 // mButtonWfcRoamingMode.setSummary is not needed; summary is selected value 619 } 620 } 621 } else if (preference == mButtonWfcRoamingMode) { 622 mButtonWfcRoamingMode.setValue((String) newValue); 623 final int buttonMode = Integer.valueOf((String) newValue); 624 final int currentMode = mImsMmTelManager.getVoWiFiRoamingModeSetting(); 625 if (buttonMode != currentMode) { 626 mImsMmTelManager.setVoWiFiRoamingModeSetting(buttonMode); 627 // mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value. 628 mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode); 629 } 630 } 631 return true; 632 } 633 getWfcModeSummary(int wfcMode)634 private CharSequence getWfcModeSummary(int wfcMode) { 635 int resId = com.android.internal.R.string.wifi_calling_off_summary; 636 if (queryImsState(mSubId).isEnabledByUser()) { 637 switch (wfcMode) { 638 case ImsMmTelManager.WIFI_MODE_WIFI_ONLY: 639 resId = com.android.internal.R.string.wfc_mode_wifi_only_summary; 640 break; 641 case ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED: 642 resId = com.android.internal.R.string.wfc_mode_cellular_preferred_summary; 643 break; 644 case ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED: 645 resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary; 646 break; 647 default: 648 Log.e(TAG, "Unexpected WFC mode value: " + wfcMode); 649 } 650 } 651 return getResourcesForSubId().getString(resId); 652 } 653 654 @VisibleForTesting getResourcesForSubId()655 Resources getResourcesForSubId() { 656 return SubscriptionManager.getResourcesForSubId(getContext(), mSubId); 657 } 658 659 @VisibleForTesting registerProvisioningChangedCallback()660 void registerProvisioningChangedCallback() { 661 if (mProvisioningManager == null) { 662 return; 663 } 664 try { 665 mProvisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(), 666 mProvisioningCallback); 667 } catch (Exception ex) { 668 Log.w(TAG, "onResume: Unable to register callback for provisioning changes."); 669 } 670 } 671 672 @VisibleForTesting unregisterProvisioningChangedCallback()673 void unregisterProvisioningChangedCallback() { 674 if (mProvisioningManager == null) { 675 return; 676 } 677 mProvisioningManager.unregisterProvisioningChangedCallback(mProvisioningCallback); 678 } 679 } 680