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