1 /* 2 * Copyright (C) 2018 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.network.telephony; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.pm.PackageManager; 22 import android.content.pm.ResolveInfo; 23 import android.os.PersistableBundle; 24 import android.provider.Settings; 25 import android.telecom.PhoneAccountHandle; 26 import android.telecom.TelecomManager; 27 import android.telephony.CarrierConfigManager; 28 import android.telephony.PhoneStateListener; 29 import android.telephony.SubscriptionManager; 30 import android.telephony.TelephonyCallback; 31 import android.telephony.TelephonyManager; 32 import android.telephony.ims.ImsMmTelManager; 33 import android.util.Log; 34 35 import androidx.annotation.VisibleForTesting; 36 import androidx.preference.Preference; 37 import androidx.preference.PreferenceScreen; 38 39 import com.android.settings.R; 40 import com.android.settings.network.ims.WifiCallingQueryImsState; 41 import com.android.settingslib.core.lifecycle.LifecycleObserver; 42 import com.android.settingslib.core.lifecycle.events.OnStart; 43 import com.android.settingslib.core.lifecycle.events.OnStop; 44 45 import java.util.List; 46 47 /** 48 * Preference controller for "Wifi Calling" 49 */ 50 //TODO: Remove the class once Provider Model is always enabled in the future. 51 public class WifiCallingPreferenceController extends TelephonyBasePreferenceController implements 52 LifecycleObserver, OnStart, OnStop { 53 54 private static final String TAG = "WifiCallingPreference"; 55 56 @VisibleForTesting 57 Integer mCallState; 58 @VisibleForTesting 59 CarrierConfigManager mCarrierConfigManager; 60 private ImsMmTelManager mImsMmTelManager; 61 @VisibleForTesting 62 PhoneAccountHandle mSimCallManager; 63 private PhoneTelephonyCallback mTelephonyCallback; 64 private Preference mPreference; 65 WifiCallingPreferenceController(Context context, String key)66 public WifiCallingPreferenceController(Context context, String key) { 67 super(context, key); 68 mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); 69 mTelephonyCallback = new PhoneTelephonyCallback(); 70 } 71 72 @Override getAvailabilityStatus(int subId)73 public int getAvailabilityStatus(int subId) { 74 return SubscriptionManager.isValidSubscriptionId(subId) 75 && MobileNetworkUtils.isWifiCallingEnabled(mContext, subId, null, null) 76 ? AVAILABLE 77 : UNSUPPORTED_ON_DEVICE; 78 } 79 80 @Override onStart()81 public void onStart() { 82 mTelephonyCallback.register(mContext, mSubId); 83 } 84 85 @Override onStop()86 public void onStop() { 87 mTelephonyCallback.unregister(); 88 } 89 90 @Override displayPreference(PreferenceScreen screen)91 public void displayPreference(PreferenceScreen screen) { 92 super.displayPreference(screen); 93 mPreference = screen.findPreference(getPreferenceKey()); 94 final Intent intent = mPreference.getIntent(); 95 if (intent != null) { 96 intent.putExtra(Settings.EXTRA_SUB_ID, mSubId); 97 } 98 } 99 100 @Override updateState(Preference preference)101 public void updateState(Preference preference) { 102 super.updateState(preference); 103 if ((mCallState == null) || (preference == null)) { 104 Log.d(TAG, "Skip update under mCallState=" + mCallState); 105 return; 106 } 107 CharSequence summaryText = null; 108 if (mSimCallManager != null) { 109 final Intent intent = MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, 110 mSimCallManager); 111 if (intent == null) { 112 // Do nothing in this case since preference is invisible 113 return; 114 } 115 final PackageManager pm = mContext.getPackageManager(); 116 final List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0); 117 preference.setTitle(resolutions.get(0).loadLabel(pm)); 118 preference.setIntent(intent); 119 } else { 120 final String title = SubscriptionManager.getResourcesForSubId(mContext, mSubId) 121 .getString(R.string.wifi_calling_settings_title); 122 preference.setTitle(title); 123 summaryText = getResourceIdForWfcMode(mSubId); 124 } 125 preference.setSummary(summaryText); 126 preference.setEnabled(mCallState == TelephonyManager.CALL_STATE_IDLE); 127 } 128 getResourceIdForWfcMode(int subId)129 private CharSequence getResourceIdForWfcMode(int subId) { 130 int resId = com.android.internal.R.string.wifi_calling_off_summary; 131 if (queryImsState(subId).isEnabledByUser()) { 132 boolean useWfcHomeModeForRoaming = false; 133 if (mCarrierConfigManager != null) { 134 final PersistableBundle carrierConfig = 135 mCarrierConfigManager.getConfigForSubId(subId); 136 if (carrierConfig != null) { 137 useWfcHomeModeForRoaming = carrierConfig.getBoolean( 138 CarrierConfigManager 139 .KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL); 140 } 141 } 142 final boolean isRoaming = getTelephonyManager(mContext, subId) 143 .isNetworkRoaming(); 144 final int wfcMode = (isRoaming && !useWfcHomeModeForRoaming) 145 ? mImsMmTelManager.getVoWiFiRoamingModeSetting() : 146 mImsMmTelManager.getVoWiFiModeSetting(); 147 switch (wfcMode) { 148 case ImsMmTelManager.WIFI_MODE_WIFI_ONLY: 149 resId = com.android.internal.R.string.wfc_mode_wifi_only_summary; 150 break; 151 case ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED: 152 resId = com.android.internal.R.string 153 .wfc_mode_cellular_preferred_summary; 154 break; 155 case ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED: 156 resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary; 157 break; 158 default: 159 break; 160 } 161 } 162 return SubscriptionManager.getResourcesForSubId(mContext, subId).getText(resId); 163 } 164 init(int subId)165 public WifiCallingPreferenceController init(int subId) { 166 mSubId = subId; 167 mImsMmTelManager = getImsMmTelManager(mSubId); 168 mSimCallManager = mContext.getSystemService(TelecomManager.class) 169 .getSimCallManagerForSubscription(mSubId); 170 171 return this; 172 } 173 174 @VisibleForTesting queryImsState(int subId)175 WifiCallingQueryImsState queryImsState(int subId) { 176 return new WifiCallingQueryImsState(mContext, subId); 177 } 178 getImsMmTelManager(int subId)179 protected ImsMmTelManager getImsMmTelManager(int subId) { 180 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 181 return null; 182 } 183 return ImsMmTelManager.createForSubscriptionId(subId); 184 } 185 186 @VisibleForTesting getTelephonyManager(Context context, int subId)187 TelephonyManager getTelephonyManager(Context context, int subId) { 188 final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); 189 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 190 return telephonyMgr; 191 } 192 final TelephonyManager subscriptionTelephonyMgr = 193 telephonyMgr.createForSubscriptionId(subId); 194 return (subscriptionTelephonyMgr == null) ? telephonyMgr : subscriptionTelephonyMgr; 195 } 196 197 198 private class PhoneTelephonyCallback extends TelephonyCallback implements 199 TelephonyCallback.CallStateListener { 200 201 private TelephonyManager mTelephonyManager; 202 203 @Override onCallStateChanged(int state)204 public void onCallStateChanged(int state) { 205 mCallState = state; 206 updateState(mPreference); 207 } 208 register(Context context, int subId)209 public void register(Context context, int subId) { 210 mTelephonyManager = getTelephonyManager(context, subId); 211 // assign current call state so that it helps to show correct preference state even 212 // before first onCallStateChanged() by initial registration. 213 mCallState = mTelephonyManager.getCallState(subId); 214 mTelephonyManager.registerTelephonyCallback(context.getMainExecutor(), this); 215 } 216 unregister()217 public void unregister() { 218 mCallState = null; 219 mTelephonyManager.unregisterTelephonyCallback(this); 220 } 221 } 222 } 223