1 /* 2 * Copyright 2013 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.phone; 18 19 import android.content.Context; 20 import android.net.ConnectivityManager; 21 import android.net.NetworkInfo; 22 import android.telephony.CarrierConfigManager; 23 import android.telephony.SubscriptionManager; 24 import android.util.Log; 25 26 import com.android.ims.ImsConfig; 27 import com.android.ims.ImsManager; 28 import com.android.internal.telephony.PhoneFactory; 29 import com.android.internal.telephony.imsphone.ImsPhone; 30 31 public class ImsUtil { 32 private static final String LOG_TAG = ImsUtil.class.getSimpleName(); 33 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2); 34 35 private static boolean sImsPhoneSupported = false; 36 ImsUtil()37 private ImsUtil() { 38 } 39 40 static { 41 PhoneGlobals app = PhoneGlobals.getInstance(); 42 sImsPhoneSupported = true; 43 } 44 45 /** 46 * @return {@code true} if this device supports voice calls using the built-in SIP stack. 47 */ isImsPhoneSupported()48 static boolean isImsPhoneSupported() { 49 return sImsPhoneSupported; 50 51 } 52 53 /** 54 * @return {@code true} if WFC is supported by the platform and has been enabled by the user. 55 */ isWfcEnabled(Context context)56 public static boolean isWfcEnabled(Context context) { 57 return isWfcEnabled(context, SubscriptionManager.getDefaultVoicePhoneId()); 58 } 59 60 /** 61 * @return {@code true} if WFC is supported per Slot and has been enabled by the user. 62 */ isWfcEnabled(Context context, int phoneId)63 public static boolean isWfcEnabled(Context context, int phoneId) { 64 ImsManager imsManager = ImsManager.getInstance(context, phoneId); 65 boolean isEnabledByPlatform = imsManager.isWfcEnabledByPlatform(); 66 boolean isEnabledByUser = imsManager.isWfcEnabledByUser(); 67 if (DBG) Log.d(LOG_TAG, "isWfcEnabled :: isEnabledByPlatform=" + isEnabledByPlatform 68 + " phoneId=" + phoneId); 69 if (DBG) Log.d(LOG_TAG, "isWfcEnabled :: isEnabledByUser=" + isEnabledByUser 70 + " phoneId=" + phoneId); 71 return isEnabledByPlatform && isEnabledByUser; 72 } 73 74 /** 75 * @return {@code true} if the device is configured to use "Wi-Fi only" mode. If WFC is not 76 * enabled, this will return {@code false}. 77 */ isWfcModeWifiOnly(Context context)78 public static boolean isWfcModeWifiOnly(Context context) { 79 return isWfcModeWifiOnly(context, SubscriptionManager.getDefaultVoicePhoneId()); 80 } 81 82 /** 83 * @return {@code true} if the Slot is configured to use "Wi-Fi only" mode. If WFC is not 84 * enabled, this will return {@code false}. 85 */ isWfcModeWifiOnly(Context context, int phoneId)86 public static boolean isWfcModeWifiOnly(Context context, int phoneId) { 87 ImsManager imsManager = ImsManager.getInstance(context, phoneId); 88 boolean isWifiOnlyMode = 89 imsManager.getWfcMode() == ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY; 90 if (DBG) Log.d(LOG_TAG, "isWfcModeWifiOnly :: isWifiOnlyMode" + isWifiOnlyMode 91 + " phoneId=" + phoneId); 92 return isWfcEnabled(context, phoneId) && isWifiOnlyMode; 93 } 94 95 /** 96 * When a call cannot be placed, determines if the use of WFC should be promoted, per the 97 * carrier config. Use of WFC is promoted to the user if the device is connected to a WIFI 98 * network, WFC is disabled but provisioned, and the carrier config indicates that the 99 * features should be promoted. 100 * 101 * @return {@code true} if use of WFC should be promoted, {@code false} otherwise. 102 */ shouldPromoteWfc(Context context)103 public static boolean shouldPromoteWfc(Context context) { 104 return shouldPromoteWfc(context, SubscriptionManager.getDefaultVoicePhoneId()); 105 } 106 107 /** 108 * When a call cannot be placed, determines if the use of WFC should be promoted, per the 109 * carrier config of the slot. Use of WFC is promoted to the user if the device is 110 * connected to a WIFI network, WFC is disabled but provisioned, and the carrier config 111 * indicates that the features should be promoted. 112 * 113 * @return {@code true} if use of WFC should be promoted, {@code false} otherwise. 114 */ shouldPromoteWfc(Context context, int phoneId)115 public static boolean shouldPromoteWfc(Context context, int phoneId) { 116 CarrierConfigManager cfgManager = (CarrierConfigManager) context 117 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 118 119 ImsManager imsManager = ImsManager.getInstance(context, phoneId); 120 if (!imsManager.isWfcEnabledByPlatform()) { 121 return false; 122 } 123 124 if (!imsManager.isWfcProvisionedOnDevice()) { 125 return false; 126 } 127 128 if (cfgManager == null || !cfgManager.getConfigForSubId(getSubId(phoneId)) 129 .getBoolean(CarrierConfigManager.KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL)) { 130 return false; 131 } 132 133 // Do not promote WFC if in roaming and WFC roaming not allowed. 134 // WFC roaming setting is not modifiable, so its value is decided by the default value 135 // chosen by the carrier, hence it really means if the carrier supports WFC roaming. 136 if (getLastKnownRoamingState(phoneId) && !imsManager.isWfcRoamingEnabledByUser()) { 137 return false; 138 } 139 140 ConnectivityManager cm = 141 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 142 if (cm != null) { 143 NetworkInfo ni = cm.getActiveNetworkInfo(); 144 if (ni != null && ni.isConnected()) { 145 return ni.getType() == ConnectivityManager.TYPE_WIFI && !isWfcEnabled(context, 146 phoneId); 147 } 148 } 149 return false; 150 } 151 getDefaultImsManagerInstance(Context context)152 private static ImsManager getDefaultImsManagerInstance(Context context) { 153 return ImsManager.getInstance(context, SubscriptionManager.getDefaultVoicePhoneId()); 154 } 155 getSubId(int phoneId)156 private static int getSubId(int phoneId) { 157 return SubscriptionManager.getSubscriptionId(phoneId); 158 } 159 getLastKnownRoamingState(int phoneId)160 private static boolean getLastKnownRoamingState(int phoneId) { 161 try { 162 ImsPhone imsPhone = (ImsPhone) (PhoneFactory.getPhone(phoneId).getImsPhone()); 163 return imsPhone.getLastKnownRoamingState(); 164 } catch (NullPointerException | ClassCastException e) { 165 return false; 166 } 167 } 168 } 169