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