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