blob: 68d0dcce0cc39c5fb943e6c40da7b4925f9735ef [file] [log] [blame]
Wink Savilleef36ef62014-06-11 08:39:38 -07001/*
2 * Copyright (c) 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
17package com.android.ims;
18
19import android.app.PendingIntent;
20import android.content.Context;
21import android.content.Intent;
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -080022import android.net.Uri;
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -070023import android.os.AsyncTask;
Wink Savilleef36ef62014-06-11 08:39:38 -070024import android.os.IBinder;
Wink Savilleef36ef62014-06-11 08:39:38 -070025import android.os.Message;
Naveen Kalla525c3a22017-02-06 14:46:42 -080026import android.os.Parcel;
Jonathan Basseri2acea6f2015-07-01 15:00:38 -070027import android.os.PersistableBundle;
Wink Savilleef36ef62014-06-11 08:39:38 -070028import android.os.RemoteException;
29import android.os.ServiceManager;
Etan Cohenaf55a402014-09-04 22:34:41 -070030import android.os.SystemProperties;
Etan Cohen82f78122014-12-15 10:10:14 -080031import android.provider.Settings;
32import android.telecom.TelecomManager;
Junda Liue7663c02015-06-23 11:16:26 -070033import android.telephony.CarrierConfigManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070034import android.telephony.Rlog;
Etan Cohen82f78122014-12-15 10:10:14 -080035import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070036import android.telephony.TelephonyManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070037
38import com.android.ims.internal.IImsCallSession;
Naveen Kalla525c3a22017-02-06 14:46:42 -080039import com.android.ims.internal.IImsConfig;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070040import com.android.ims.internal.IImsEcbm;
Tyler Gunn4d128b62016-04-13 15:44:38 -070041import com.android.ims.internal.IImsMultiEndpoint;
Wink Savilleef36ef62014-06-11 08:39:38 -070042import com.android.ims.internal.IImsRegistrationListener;
43import com.android.ims.internal.IImsService;
44import com.android.ims.internal.IImsUt;
45import com.android.ims.internal.ImsCallSession;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050046
Jack Yu2f102bd2015-12-28 15:31:48 -080047import java.io.FileDescriptor;
48import java.io.PrintWriter;
Naveen Kalla525c3a22017-02-06 14:46:42 -080049import java.util.ArrayList;
Etan Cohend7727462014-07-12 14:54:10 -070050import java.util.HashMap;
Naveen Kalla525c3a22017-02-06 14:46:42 -080051import java.util.concurrent.ConcurrentLinkedDeque;
Etan Cohend7727462014-07-12 14:54:10 -070052
Wink Savilleef36ef62014-06-11 08:39:38 -070053/**
54 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
55 * the operator's IMS network. This class is the starting point for any IMS actions.
56 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
57 * <p>The APIs in this class allows you to:</p>
58 *
59 * @hide
60 */
61public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070062
Etan Cohenaf55a402014-09-04 22:34:41 -070063 /*
64 * Debug flag to override configuration flag
65 */
Etan Cohenb651fa52014-10-22 10:51:29 -070066 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
67 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070068 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
69 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080070 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
71 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Meng Wang9352c432016-06-08 14:22:20 -070072 public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off";
73 public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070074
Wink Savilleef36ef62014-06-11 08:39:38 -070075 /**
76 * For accessing the IMS related service.
77 * Internal use only.
78 * @hide
79 */
Etan Cohend7727462014-07-12 14:54:10 -070080 private static final String IMS_SERVICE = "ims";
Wink Savilleef36ef62014-06-11 08:39:38 -070081
82 /**
83 * The result code to be sent back with the incoming call {@link PendingIntent}.
84 * @see #open(PendingIntent, ImsConnectionStateListener)
85 */
86 public static final int INCOMING_CALL_RESULT_CODE = 101;
87
88 /**
89 * Key to retrieve the call ID from an incoming call intent.
90 * @see #open(PendingIntent, ImsConnectionStateListener)
91 */
92 public static final String EXTRA_CALL_ID = "android:imsCallID";
93
94 /**
95 * Action to broadcast when ImsService is up.
96 * Internal use only.
97 * @hide
98 */
99 public static final String ACTION_IMS_SERVICE_UP =
100 "com.android.ims.IMS_SERVICE_UP";
101
102 /**
103 * Action to broadcast when ImsService is down.
104 * Internal use only.
105 * @hide
106 */
107 public static final String ACTION_IMS_SERVICE_DOWN =
108 "com.android.ims.IMS_SERVICE_DOWN";
109
110 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700111 * Action to broadcast when ImsService registration fails.
112 * Internal use only.
113 * @hide
114 */
115 public static final String ACTION_IMS_REGISTRATION_ERROR =
116 "com.android.ims.REGISTRATION_ERROR";
117
118 /**
Etan Cohend7727462014-07-12 14:54:10 -0700119 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700120 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700121 * Internal use only.
122 * @hide
123 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700124 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700125
126 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700127 * Action for the incoming call intent for the Phone app.
128 * Internal use only.
129 * @hide
130 */
131 public static final String ACTION_IMS_INCOMING_CALL =
132 "com.android.ims.IMS_INCOMING_CALL";
133
134 /**
135 * Part of the ACTION_IMS_INCOMING_CALL intents.
136 * An integer value; service identifier obtained from {@link ImsManager#open}.
137 * Internal use only.
138 * @hide
139 */
140 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
141
142 /**
143 * Part of the ACTION_IMS_INCOMING_CALL intents.
144 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
145 * The value "true" indicates that the incoming call is for USSD.
146 * Internal use only.
147 * @hide
148 */
149 public static final String EXTRA_USSD = "android:ussd";
150
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700151 /**
152 * Part of the ACTION_IMS_INCOMING_CALL intents.
153 * A boolean value; Flag to indicate whether the call is an unknown
154 * dialing call. Such calls are originated by sending commands (like
155 * AT commands) directly to modem without Android involvement.
156 * Even though they are not incoming calls, they are propagated
157 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
158 * Internal use only.
159 * @hide
160 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700161 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700162
Wink Savilleef36ef62014-06-11 08:39:38 -0700163 private static final String TAG = "ImsManager";
164 private static final boolean DBG = true;
165
Wink Saville1e5a38a2014-10-23 10:24:46 -0700166 private static HashMap<Integer, ImsManager> sImsManagerInstances =
167 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700168
Wink Savilleef36ef62014-06-11 08:39:38 -0700169 private Context mContext;
Etan Cohenabbd7882014-09-26 22:35:35 -0700170 private int mPhoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700171 private IImsService mImsService = null;
172 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
173 // Ut interface for the supplementary service configuration
174 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500175 // Interface to get/set ims config items
176 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700177 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700178
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800179 private ImsConfigListener mImsConfigListener;
180
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700181 // ECBM interface
182 private ImsEcbm mEcbm = null;
183
Tyler Gunn4d128b62016-04-13 15:44:38 -0700184 private ImsMultiEndpoint mMultiEndpoint = null;
185
Amit Mahajan24f7b162016-07-21 16:33:53 -0700186 // SystemProperties used as cache
187 private static final String VOLTE_PROVISIONED_PROP = "net.lte.ims.volte.provisioned";
188 private static final String WFC_PROVISIONED_PROP = "net.lte.ims.wfc.provisioned";
189 private static final String VT_PROVISIONED_PROP = "net.lte.ims.vt.provisioned";
Jack Yu643ffe42016-07-08 14:25:46 -0700190 // Flag indicating data enabled or not. This flag should be in sync with
191 // DcTracker.isDataEnabled(). The flag will be set later during boot up.
Amit Mahajan24f7b162016-07-21 16:33:53 -0700192 private static final String DATA_ENABLED_PROP = "net.lte.ims.data.enabled";
193
194 public static final String TRUE = "true";
195 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700196
Naveen Kalla525c3a22017-02-06 14:46:42 -0800197 // mRecentDisconnectReasons stores the last 16 disconnect reasons
198 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
199 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
200 new ConcurrentLinkedDeque<>();
201
Wink Savilleef36ef62014-06-11 08:39:38 -0700202 /**
203 * Gets a manager instance.
204 *
205 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700206 * @param phoneId the phone ID for the IMS Service
207 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700208 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700209 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700210 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800211 if (sImsManagerInstances.containsKey(phoneId)) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700212 return sImsManagerInstances.get(phoneId);
Naveen Kalla525c3a22017-02-06 14:46:42 -0800213 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700214
Etan Cohenabbd7882014-09-26 22:35:35 -0700215 ImsManager mgr = new ImsManager(context, phoneId);
216 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700217
218 return mgr;
219 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700220 }
221
Etan Cohen45b5f312014-08-19 15:55:08 -0700222 /**
223 * Returns the user configuration of Enhanced 4G LTE Mode setting
224 */
225 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Sungmin Choi2f1af952016-02-01 17:15:35 +0900226 // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true.
227 // If user changes SIM from editable mode to uneditable mode, need to return true.
228 if (!getBooleanCarrierConfig(context,
229 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
230 return true;
231 }
Libin.Tang@motorola.com8a6bf4b2014-10-10 15:02:41 -0500232 int enabled = android.provider.Settings.Global.getInt(
233 context.getContentResolver(),
Etan Cohenb651fa52014-10-22 10:51:29 -0700234 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
Etan Cohena00c9192014-12-23 15:02:29 -0800235 return (enabled == 1) ? true : false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700236 }
237
238 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800239 * Change persistent Enhanced 4G LTE Mode setting
240 */
241 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
242 int value = enabled ? 1 : 0;
243 android.provider.Settings.Global.putInt(
244 context.getContentResolver(),
245 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
246
247 if (isNonTtyOrTtyOnVolteEnabled(context)) {
248 ImsManager imsManager = ImsManager.getInstance(context,
249 SubscriptionManager.getDefaultVoicePhoneId());
250 if (imsManager != null) {
251 try {
252 imsManager.setAdvanced4GMode(enabled);
253 } catch (ImsException ie) {
254 // do nothing
255 }
256 }
257 }
258 }
259
260 /**
261 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
262 * supported.
263 */
264 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700265 if (getBooleanCarrierConfig(context,
fionaxu5803ef02016-03-08 11:48:48 -0800266 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800267 return true;
268 }
269
270 return Settings.Secure.getInt(context.getContentResolver(),
271 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
272 == TelecomManager.TTY_MODE_OFF;
273 }
274
275 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700276 * Returns a platform configuration for VoLTE which may override the user setting.
Etan Cohen45b5f312014-08-19 15:55:08 -0700277 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700278 public static boolean isVolteEnabledByPlatform(Context context) {
Etan Cohenb651fa52014-10-22 10:51:29 -0700279 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
280 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
Etan Cohenaf55a402014-09-04 22:34:41 -0700281 return true;
282 }
283
Etan Cohenb5388a32014-11-26 11:57:47 -0800284 return context.getResources().getBoolean(
Junda Liue7663c02015-06-23 11:16:26 -0700285 com.android.internal.R.bool.config_device_volte_available)
286 && getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700287 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
288 && isGbaValid(context);
Etan Cohenb5388a32014-11-26 11:57:47 -0800289 }
290
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700291 /**
Etan Cohenb5388a32014-11-26 11:57:47 -0800292 * Indicates whether VoLTE is provisioned on device
293 */
294 public static boolean isVolteProvisionedOnDevice(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700295 if (getBooleanCarrierConfig(context,
296 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Etan Cohenb5388a32014-11-26 11:57:47 -0800297 ImsManager mgr = ImsManager.getInstance(context,
Jonathan Basserid7133652015-04-07 19:54:24 -0700298 SubscriptionManager.getDefaultVoicePhoneId());
Etan Cohenb5388a32014-11-26 11:57:47 -0800299 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700300 return mgr.isVolteProvisioned();
Etan Cohenb5388a32014-11-26 11:57:47 -0800301 }
302 }
303
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700304 return true;
305 }
306
307 /**
308 * Indicates whether VoWifi is provisioned on device
309 */
310 public static boolean isWfcProvisionedOnDevice(Context context) {
311 if (getBooleanCarrierConfig(context,
312 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
313 ImsManager mgr = ImsManager.getInstance(context,
314 SubscriptionManager.getDefaultVoicePhoneId());
315 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700316 return mgr.isWfcProvisioned();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700317 }
318 }
319
320 return true;
321 }
322
323 /**
324 * Indicates whether VT is provisioned on device
325 */
326 public static boolean isVtProvisionedOnDevice(Context context) {
327 if (getBooleanCarrierConfig(context,
328 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
329 ImsManager mgr = ImsManager.getInstance(context,
330 SubscriptionManager.getDefaultVoicePhoneId());
331 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700332 return mgr.isVtProvisioned();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700333 }
334 }
335
336 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700337 }
338
Etan Cohenea2b5832014-10-23 18:50:35 -0700339 /**
340 * Returns a platform configuration for VT which may override the user setting.
341 *
342 * Note: VT presumes that VoLTE is enabled (these are configuration settings
343 * which must be done correctly).
344 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700345 public static boolean isVtEnabledByPlatform(Context context) {
Etan Cohenea2b5832014-10-23 18:50:35 -0700346 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
347 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
348 return true;
349 }
350
Etan Cohenb651fa52014-10-22 10:51:29 -0700351 return
352 context.getResources().getBoolean(
353 com.android.internal.R.bool.config_device_vt_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700354 getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700355 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
356 isGbaValid(context);
Etan Cohen45b5f312014-08-19 15:55:08 -0700357 }
358
Etan Cohena00c9192014-12-23 15:02:29 -0800359 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700360 * Returns the user configuration of VT setting
361 */
362 public static boolean isVtEnabledByUser(Context context) {
363 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
364 android.provider.Settings.Global.VT_IMS_ENABLED,
365 ImsConfig.FeatureValueConstants.ON);
366 return (enabled == 1) ? true : false;
367 }
368
369 /**
370 * Change persistent VT enabled setting
371 */
372 public static void setVtSetting(Context context, boolean enabled) {
373 int value = enabled ? 1 : 0;
374 android.provider.Settings.Global.putInt(context.getContentResolver(),
375 android.provider.Settings.Global.VT_IMS_ENABLED, value);
376
377 ImsManager imsManager = ImsManager.getInstance(context,
378 SubscriptionManager.getDefaultVoicePhoneId());
379 if (imsManager != null) {
380 try {
381 ImsConfig config = imsManager.getConfigInterface();
382 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
383 TelephonyManager.NETWORK_TYPE_LTE,
384 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800385 : ImsConfig.FeatureValueConstants.OFF,
386 imsManager.mImsConfigListener);
Etan Cohena7d32e82015-05-04 18:02:09 -0700387
388 if (enabled) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700389 log("setVtSetting() : turnOnIms");
Etan Cohena7d32e82015-05-04 18:02:09 -0700390 imsManager.turnOnIms();
Meng Wang9352c432016-06-08 14:22:20 -0700391 } else if (isTurnOffImsAllowedByPlatform(context)
Pavel Zhamaitsiak4ca0cde2015-12-22 16:51:57 -0800392 && (!isVolteEnabledByPlatform(context)
Etan Cohena7d32e82015-05-04 18:02:09 -0700393 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
394 log("setVtSetting() : imsServiceAllowTurnOff -> turnOffIms");
395 imsManager.turnOffIms();
396 }
397 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700398 loge("setVtSetting(): ", e);
Etan Cohena7d32e82015-05-04 18:02:09 -0700399 }
400 }
401 }
402
Meng Wang9352c432016-06-08 14:22:20 -0700403 /*
404 * Returns whether turning off ims is allowed by platform.
405 * The platform property may override the carrier config.
406 */
407 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
408 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
409 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
410 return true;
411 }
412 return getBooleanCarrierConfig(context,
413 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
414 }
415
Etan Cohena7d32e82015-05-04 18:02:09 -0700416 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800417 * Returns the user configuration of WFC setting
418 */
419 public static boolean isWfcEnabledByUser(Context context) {
420 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
421 android.provider.Settings.Global.WFC_IMS_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800422 getBooleanCarrierConfig(context,
423 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
424 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800425 return (enabled == 1) ? true : false;
426 }
427
428 /**
429 * Change persistent WFC enabled setting
430 */
431 public static void setWfcSetting(Context context, boolean enabled) {
432 int value = enabled ? 1 : 0;
433 android.provider.Settings.Global.putInt(context.getContentResolver(),
434 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
435
436 ImsManager imsManager = ImsManager.getInstance(context,
437 SubscriptionManager.getDefaultVoicePhoneId());
438 if (imsManager != null) {
439 try {
440 ImsConfig config = imsManager.getConfigInterface();
Etan Cohena00c9192014-12-23 15:02:29 -0800441 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
Nathan Harold3a99f782015-07-24 15:02:34 -0700442 TelephonyManager.NETWORK_TYPE_IWLAN,
Etan Cohena00c9192014-12-23 15:02:29 -0800443 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800444 : ImsConfig.FeatureValueConstants.OFF,
445 imsManager.mImsConfigListener);
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800446
447 if (enabled) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700448 log("setWfcSetting() : turnOnIms");
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800449 imsManager.turnOnIms();
Meng Wang9352c432016-06-08 14:22:20 -0700450 } else if (isTurnOffImsAllowedByPlatform(context)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800451 && (!isVolteEnabledByPlatform(context)
452 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
453 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
454 imsManager.turnOffIms();
455 }
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700456
457 // Force IMS to register over LTE when turning off WFC
458 setWfcModeInternal(context, enabled
459 ? getWfcMode(context)
460 : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED);
Etan Cohena00c9192014-12-23 15:02:29 -0800461 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700462 loge("setWfcSetting(): ", e);
Etan Cohena00c9192014-12-23 15:02:29 -0800463 }
464 }
465 }
466
467 /**
Meng Wang37477012016-09-20 09:59:56 -0700468 * Returns the user configuration of WFC preference setting
Etan Cohena00c9192014-12-23 15:02:29 -0800469 */
470 public static int getWfcMode(Context context) {
471 int setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
fionaxu5803ef02016-03-08 11:48:48 -0800472 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context,
473 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
Etan Cohena00c9192014-12-23 15:02:29 -0800474 if (DBG) log("getWfcMode - setting=" + setting);
475 return setting;
476 }
477
478 /**
Meng Wang37477012016-09-20 09:59:56 -0700479 * Change persistent WFC preference setting
Etan Cohena00c9192014-12-23 15:02:29 -0800480 */
481 public static void setWfcMode(Context context, int wfcMode) {
482 if (DBG) log("setWfcMode - setting=" + wfcMode);
483 android.provider.Settings.Global.putInt(context.getContentResolver(),
484 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
485
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700486 setWfcModeInternal(context, wfcMode);
487 }
488
Meng Wang37477012016-09-20 09:59:56 -0700489 /**
490 * Returns the user configuration of WFC preference setting
491 *
492 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
493 */
494 public static int getWfcMode(Context context, boolean roaming) {
495 int setting = 0;
496 if (!roaming) {
497 setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
498 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context,
499 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
500 if (DBG) log("getWfcMode - setting=" + setting);
501 } else {
502 setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
503 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE,
504 getIntCarrierConfig(context,
505 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT));
506 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
507 }
508 return setting;
509 }
510
511 /**
512 * Change persistent WFC preference setting
513 *
514 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
515 */
516 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
517 if (!roaming) {
518 if (DBG) log("setWfcMode - setting=" + wfcMode);
519 android.provider.Settings.Global.putInt(context.getContentResolver(),
520 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
521 } else {
522 if (DBG) log("setWfcMode (roaming) - setting=" + wfcMode);
523 android.provider.Settings.Global.putInt(context.getContentResolver(),
524 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, wfcMode);
525 }
526
527 TelephonyManager tm = (TelephonyManager)
528 context.getSystemService(Context.TELEPHONY_SERVICE);
529 if (roaming == tm.isNetworkRoaming()) {
530 setWfcModeInternal(context, wfcMode);
531 }
532 }
533
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700534 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800535 final ImsManager imsManager = ImsManager.getInstance(context,
536 SubscriptionManager.getDefaultVoicePhoneId());
537 if (imsManager != null) {
538 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700539 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800540 public void run() {
541 try {
542 imsManager.getConfigInterface().setProvisionedValue(
543 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
544 value);
545 } catch (ImsException e) {
546 // do nothing
547 }
548 }
549 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700550 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800551 }
552 }
553
554 /**
555 * Returns the user configuration of WFC roaming setting
556 */
557 public static boolean isWfcRoamingEnabledByUser(Context context) {
558 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
559 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800560 getBooleanCarrierConfig(context,
561 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
562 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800563 return (enabled == 1) ? true : false;
564 }
565
566 /**
567 * Change persistent WFC roaming enabled setting
568 */
569 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Etan Cohena00c9192014-12-23 15:02:29 -0800570 android.provider.Settings.Global.putInt(context.getContentResolver(),
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700571 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800572 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700573 : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800574
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700575 setWfcRoamingSettingInternal(context, enabled);
576 }
577
578 private static void setWfcRoamingSettingInternal(Context context, boolean enabled) {
Etan Cohena00c9192014-12-23 15:02:29 -0800579 final ImsManager imsManager = ImsManager.getInstance(context,
580 SubscriptionManager.getDefaultVoicePhoneId());
581 if (imsManager != null) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700582 final int value = enabled
583 ? ImsConfig.FeatureValueConstants.ON
584 : ImsConfig.FeatureValueConstants.OFF;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700585 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800586 public void run() {
587 try {
588 imsManager.getConfigInterface().setProvisionedValue(
589 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING,
590 value);
591 } catch (ImsException e) {
592 // do nothing
593 }
594 }
595 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700596 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800597 }
598 }
599
600 /**
601 * Returns a platform configuration for WFC which may override the user
602 * setting. Note: WFC presumes that VoLTE is enabled (these are
603 * configuration settings which must be done correctly).
604 */
605 public static boolean isWfcEnabledByPlatform(Context context) {
606 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
607 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
608 return true;
609 }
610
611 return
612 context.getResources().getBoolean(
613 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700614 getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700615 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
616 isGbaValid(context);
617 }
618
619 /**
620 * If carrier requires that IMS is only available if GBA capable SIM is used,
621 * then this function checks GBA bit in EF IST.
622 *
623 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
624 */
625 private static boolean isGbaValid(Context context) {
626 if (getBooleanCarrierConfig(context,
627 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
628 final TelephonyManager telephonyManager = TelephonyManager.getDefault();
629 String efIst = telephonyManager.getIsimIst();
630 if (efIst == null) {
631 loge("ISF is NULL");
632 return true;
633 }
634 boolean result = efIst != null && efIst.length() > 1 &&
635 (0x02 & (byte)efIst.charAt(1)) != 0;
636 if (DBG) log("GBA capable=" + result + ", ISF=" + efIst);
637 return result;
638 }
639 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800640 }
641
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700642 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700643 * This function should be called when ImsConfig.ACTION_IMS_CONFIG_CHANGED is received.
644 *
645 * We cannot register receiver in ImsManager because this would lead to resource leak.
646 * ImsManager can be created in different processes and it is not notified when that process
647 * is about to be terminated.
648 *
649 * @hide
650 * */
651 public static void onProvisionedValueChanged(Context context, int item, String value) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700652 if (DBG) Rlog.d(TAG, "onProvisionedValueChanged: item=" + item + " val=" + value);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700653 ImsManager mgr = ImsManager.getInstance(context,
654 SubscriptionManager.getDefaultVoicePhoneId());
655
656 switch (item) {
657 case ImsConfig.ConfigConstants.VLT_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -0700658 mgr.setVolteProvisionedProperty(value.equals("1"));
659 if (DBG) Rlog.d(TAG,"isVoLteProvisioned = " + mgr.isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700660 break;
661
662 case ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -0700663 mgr.setWfcProvisionedProperty(value.equals("1"));
664 if (DBG) Rlog.d(TAG,"isWfcProvisioned = " + mgr.isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700665 break;
666
Nathan Harolda9fc7f12016-06-30 16:12:14 -0700667 case ImsConfig.ConfigConstants.LVC_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -0700668 mgr.setVtProvisionedProperty(value.equals("1"));
669 if (DBG) Rlog.d(TAG,"isVtProvisioned = " + mgr.isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -0700670 break;
671
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700672 }
673 }
674
675 private class AsyncUpdateProvisionedValues extends AsyncTask<Void, Void, Void> {
676 @Override
677 protected Void doInBackground(Void... params) {
678 // disable on any error
Amit Mahajan24f7b162016-07-21 16:33:53 -0700679 setVolteProvisionedProperty(false);
680 setWfcProvisionedProperty(false);
681 setVtProvisionedProperty(false);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700682
683 try {
684 ImsConfig config = getConfigInterface();
685 if (config != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700686 setVolteProvisionedProperty(getProvisionedBool(config,
687 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED));
688 if (DBG) Rlog.d(TAG, "isVoLteProvisioned = " + isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700689
Amit Mahajan24f7b162016-07-21 16:33:53 -0700690 setWfcProvisionedProperty(getProvisionedBool(config,
691 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED));
692 if (DBG) Rlog.d(TAG, "isWfcProvisioned = " + isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700693
Amit Mahajan24f7b162016-07-21 16:33:53 -0700694 setVtProvisionedProperty(getProvisionedBool(config,
695 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED));
696 if (DBG) Rlog.d(TAG, "isVtProvisioned = " + isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -0700697
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700698 }
699 } catch (ImsException ie) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700700 Rlog.e(TAG, "AsyncUpdateProvisionedValues error: ", ie);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700701 }
702
703 return null;
704 }
705
706 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
707 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
708 }
709 }
710
711 /** Asynchronously get VoLTE, WFC, VT provisioning statuses */
712 private void updateProvisionedValues() {
713 if (getBooleanCarrierConfig(mContext,
714 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
715
716 new AsyncUpdateProvisionedValues().execute();
717 }
718 }
719
720 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700721 * Sync carrier config and user settings with ImsConfig.
722 *
723 * @param context for the manager object
724 * @param phoneId phone id
725 * @param force update
726 */
727 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -0700728 if (!force) {
729 if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) {
730 log("updateImsServiceConfig: SIM not ready");
731 // Don't disable IMS if SIM is not ready
732 return;
733 }
734 }
735
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700736 final ImsManager imsManager = ImsManager.getInstance(context, phoneId);
737 if (imsManager != null && (!imsManager.mConfigUpdated || force)) {
738 try {
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700739 imsManager.updateProvisionedValues();
740
Pavel Zhamaitsiakd46779c2016-06-03 10:39:51 -0700741 // TODO: Extend ImsConfig API and set all feature values in single function call.
742
743 // Note: currently the order of updates is set to produce different order of
744 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
745 // differentiate this code path from vendor code perspective.
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800746 boolean isImsUsed = imsManager.updateVolteFeatureValue();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800747 isImsUsed |= imsManager.updateWfcFeatureAndProvisionedValues();
Pavel Zhamaitsiakd46779c2016-06-03 10:39:51 -0700748 isImsUsed |= imsManager.updateVideoCallFeatureValue();
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700749
Meng Wang9352c432016-06-08 14:22:20 -0700750 if (isImsUsed || !isTurnOffImsAllowedByPlatform(context)) {
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800751 // Turn on IMS if it is used.
752 // Also, if turning off is not allowed for current carrier,
753 // we need to turn IMS on because it might be turned off before
754 // phone switched to current carrier.
Meng Wangca7d4c42016-06-30 22:05:24 -0700755 log("updateImsServiceConfig: turnOnIms");
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700756 imsManager.turnOnIms();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800757 } else {
758 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Meng Wangca7d4c42016-06-30 22:05:24 -0700759 log("updateImsServiceConfig: turnOffIms");
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700760 imsManager.turnOffIms();
761 }
762
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700763 imsManager.mConfigUpdated = true;
764 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700765 loge("updateImsServiceConfig: ", e);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700766 imsManager.mConfigUpdated = false;
767 }
768 }
769 }
770
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700771 /**
772 * Update VoLTE config
773 * @return whether feature is On
774 * @throws ImsException
775 */
776 private boolean updateVolteFeatureValue() throws ImsException {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700777 boolean available = isVolteEnabledByPlatform(mContext);
778 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(mContext);
779 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(mContext);
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800780 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700781
782 log("updateVolteFeatureValue: available = " + available
783 + ", enabled = " + enabled
784 + ", nonTTY = " + isNonTty);
785
786 getConfigInterface().setFeatureValue(
787 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
788 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800789 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700790 ImsConfig.FeatureValueConstants.ON :
791 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800792 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700793
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800794 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700795 }
796
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700797 /**
Jack Yu643ffe42016-07-08 14:25:46 -0700798 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700799 * @return whether feature is On
800 * @throws ImsException
801 */
802 private boolean updateVideoCallFeatureValue() throws ImsException {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700803 boolean available = isVtEnabledByPlatform(mContext);
Tyler Gunnfb4abdf2016-08-01 11:14:46 -0700804 boolean enabled = isVtEnabledByUser(mContext);
Omkar Kolangadec0f450d2016-02-11 20:59:48 +0530805 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(mContext);
Amit Mahajan24f7b162016-07-21 16:33:53 -0700806 boolean isDataEnabled = isDataEnabled();
Jack Yu643ffe42016-07-08 14:25:46 -0700807
Amit Mahajan24f7b162016-07-21 16:33:53 -0700808 boolean isFeatureOn = available && enabled && isNonTty && isDataEnabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700809
810 log("updateVideoCallFeatureValue: available = " + available
811 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -0700812 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -0700813 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700814
815 getConfigInterface().setFeatureValue(
816 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
817 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800818 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700819 ImsConfig.FeatureValueConstants.ON :
820 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800821 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700822
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800823 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700824 }
825
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700826 /**
827 * Update WFC config
828 * @return whether feature is On
829 * @throws ImsException
830 */
831 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
Meng Wang531a8b62016-10-06 11:29:46 -0700832 boolean isNetworkRoaming = TelephonyManager.getDefault().isNetworkRoaming();
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700833 boolean available = isWfcEnabledByPlatform(mContext);
834 boolean enabled = isWfcEnabledByUser(mContext);
Meng Wang531a8b62016-10-06 11:29:46 -0700835 int mode = getWfcMode(mContext, isNetworkRoaming);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700836 boolean roaming = isWfcRoamingEnabledByUser(mContext);
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800837 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700838
839 log("updateWfcFeatureAndProvisionedValues: available = " + available
840 + ", enabled = " + enabled
841 + ", mode = " + mode
842 + ", roaming = " + roaming);
843
844 getConfigInterface().setFeatureValue(
Pavel Zhamaitsiake6f99432015-09-11 10:29:30 -0700845 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
846 TelephonyManager.NETWORK_TYPE_IWLAN,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800847 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700848 ImsConfig.FeatureValueConstants.ON :
849 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800850 mImsConfigListener);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700851
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800852 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700853 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
854 roaming = false;
855 }
856 setWfcModeInternal(mContext, mode);
857 setWfcRoamingSettingInternal(mContext, roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700858
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800859 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700860 }
861
Etan Cohenabbd7882014-09-26 22:35:35 -0700862 private ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700863 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -0700864 mPhoneId = phoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700865 createImsService(true);
866 }
867
Etan Cohenf4311122015-02-26 17:47:13 -0800868 /*
869 * Returns a flag indicating whether the IMS service is available.
870 */
871 public boolean isServiceAvailable() {
872 if (mImsService != null) {
873 return true;
874 }
875
876 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
877 if (binder != null) {
878 return true;
879 }
880
881 return false;
882 }
883
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800884 public void setImsConfigListener(ImsConfigListener listener) {
885 mImsConfigListener = listener;
886 }
887
Wink Savilleef36ef62014-06-11 08:39:38 -0700888 /**
889 * Opens the IMS service for making calls and/or receiving generic IMS calls.
890 * The caller may make subsquent calls through {@link #makeCall}.
891 * The IMS service will register the device to the operator's network with the credentials
892 * (from ISIM) periodically in order to receive calls from the operator's network.
893 * When the IMS service receives a new call, it will send out an intent with
894 * the provided action string.
895 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
896 *
897 * @param serviceClass a service class specified in {@link ImsServiceClass}
898 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
899 * @param incomingCallPendingIntent When an incoming call is received,
900 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
901 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
902 * as the result code and the intent to fill in the call ID; It cannot be null
903 * @param listener To listen to IMS registration events; It cannot be null
904 * @return identifier (greater than 0) for the specified service
905 * @throws NullPointerException if {@code incomingCallPendingIntent}
906 * or {@code listener} is null
907 * @throws ImsException if calling the IMS service results in an error
908 * @see #getCallId
909 * @see #getServiceId
910 */
911 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
912 ImsConnectionStateListener listener) throws ImsException {
913 checkAndThrowExceptionIfServiceUnavailable();
914
915 if (incomingCallPendingIntent == null) {
916 throw new NullPointerException("incomingCallPendingIntent can't be null");
917 }
918
919 if (listener == null) {
920 throw new NullPointerException("listener can't be null");
921 }
922
923 int result = 0;
924
925 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700926 result = mImsService.open(mPhoneId, serviceClass, incomingCallPendingIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -0700927 createRegistrationListenerProxy(serviceClass, listener));
928 } catch (RemoteException e) {
929 throw new ImsException("open()", e,
930 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
931 }
932
933 if (result <= 0) {
934 // If the return value is a minus value,
935 // it means that an error occurred in the service.
936 // So, it needs to convert to the reason code specified in ImsReasonInfo.
937 throw new ImsException("open()", (result * (-1)));
938 }
939
940 return result;
941 }
942
943 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -0700944 * Adds registration listener to the IMS service.
945 *
946 * @param serviceClass a service class specified in {@link ImsServiceClass}
947 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
948 * @param listener To listen to IMS registration events; It cannot be null
949 * @throws NullPointerException if {@code listener} is null
950 * @throws ImsException if calling the IMS service results in an error
951 */
952 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
953 throws ImsException {
954 checkAndThrowExceptionIfServiceUnavailable();
955
956 if (listener == null) {
957 throw new NullPointerException("listener can't be null");
958 }
959
960 try {
961 mImsService.addRegistrationListener(mPhoneId, serviceClass,
962 createRegistrationListenerProxy(serviceClass, listener));
963 } catch (RemoteException e) {
964 throw new ImsException("addRegistrationListener()", e,
965 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
966 }
967 }
968
969 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700970 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
971 * All the resources that were allocated to the service are also released.
972 *
973 * @param serviceId a service id to be closed which is obtained from {@link ImsManager#open}
974 * @throws ImsException if calling the IMS service results in an error
975 */
976 public void close(int serviceId) throws ImsException {
977 checkAndThrowExceptionIfServiceUnavailable();
978
979 try {
980 mImsService.close(serviceId);
981 } catch (RemoteException e) {
982 throw new ImsException("close()", e,
983 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
984 } finally {
985 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500986 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700987 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -0700988 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700989 }
990 }
991
992 /**
993 * Gets the configuration interface to provision / withdraw the supplementary service settings.
994 *
995 * @param serviceId a service id which is obtained from {@link ImsManager#open}
996 * @return the Ut interface instance
997 * @throws ImsException if getting the Ut interface results in an error
998 */
999 public ImsUtInterface getSupplementaryServiceConfiguration(int serviceId)
1000 throws ImsException {
1001 // FIXME: manage the multiple Ut interfaces based on the service id
1002 if (mUt == null) {
1003 checkAndThrowExceptionIfServiceUnavailable();
1004
1005 try {
1006 IImsUt iUt = mImsService.getUtInterface(serviceId);
1007
1008 if (iUt == null) {
1009 throw new ImsException("getSupplementaryServiceConfiguration()",
1010 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1011 }
1012
1013 mUt = new ImsUt(iUt);
1014 } catch (RemoteException e) {
1015 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1016 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1017 }
1018 }
1019
1020 return mUt;
1021 }
1022
1023 /**
1024 * Checks if the IMS service has successfully registered to the IMS network
1025 * with the specified service & call type.
1026 *
1027 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1028 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1029 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1030 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1031 * @param callType a call type that is specified in {@link ImsCallProfile}
1032 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
1033 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1034 * {@link ImsCallProfile#CALL_TYPE_VT}
1035 * {@link ImsCallProfile#CALL_TYPE_VS}
1036 * @return true if the specified service id is connected to the IMS network;
1037 * false otherwise
1038 * @throws ImsException if calling the IMS service results in an error
1039 */
1040 public boolean isConnected(int serviceId, int serviceType, int callType)
1041 throws ImsException {
1042 checkAndThrowExceptionIfServiceUnavailable();
1043
1044 try {
1045 return mImsService.isConnected(serviceId, serviceType, callType);
1046 } catch (RemoteException e) {
1047 throw new ImsException("isServiceConnected()", e,
1048 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1049 }
1050 }
1051
1052 /**
1053 * Checks if the specified IMS service is opend.
1054 *
1055 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1056 * @return true if the specified service id is opened; false otherwise
1057 * @throws ImsException if calling the IMS service results in an error
1058 */
1059 public boolean isOpened(int serviceId) throws ImsException {
1060 checkAndThrowExceptionIfServiceUnavailable();
1061
1062 try {
1063 return mImsService.isOpened(serviceId);
1064 } catch (RemoteException e) {
1065 throw new ImsException("isOpened()", e,
1066 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1067 }
1068 }
1069
1070 /**
1071 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1072 *
1073 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1074 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1075 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1076 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1077 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1078 * @param callType a call type that is specified in {@link ImsCallProfile}
1079 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1080 * {@link ImsCallProfile#CALL_TYPE_VT}
1081 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1082 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1083 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1084 * {@link ImsCallProfile#CALL_TYPE_VS}
1085 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1086 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1087 * @return a {@link ImsCallProfile} object
1088 * @throws ImsException if calling the IMS service results in an error
1089 */
1090 public ImsCallProfile createCallProfile(int serviceId,
1091 int serviceType, int callType) throws ImsException {
1092 checkAndThrowExceptionIfServiceUnavailable();
1093
1094 try {
1095 return mImsService.createCallProfile(serviceId, serviceType, callType);
1096 } catch (RemoteException e) {
1097 throw new ImsException("createCallProfile()", e,
1098 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1099 }
1100 }
1101
1102 /**
1103 * Creates a {@link ImsCall} to make a call.
1104 *
1105 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1106 * @param profile a call profile to make the call
1107 * (it contains service type, call type, media information, etc.)
1108 * @param participants participants to invite the conference call
1109 * @param listener listen to the call events from {@link ImsCall}
1110 * @return a {@link ImsCall} object
1111 * @throws ImsException if calling the IMS service results in an error
1112 */
1113 public ImsCall makeCall(int serviceId, ImsCallProfile profile, String[] callees,
1114 ImsCall.Listener listener) throws ImsException {
1115 if (DBG) {
1116 log("makeCall :: serviceId=" + serviceId
fionaxu7b3107c2016-07-06 14:04:06 -07001117 + ", profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001118 }
1119
1120 checkAndThrowExceptionIfServiceUnavailable();
1121
1122 ImsCall call = new ImsCall(mContext, profile);
1123
1124 call.setListener(listener);
1125 ImsCallSession session = createCallSession(serviceId, profile);
1126
1127 if ((callees != null) && (callees.length == 1)) {
1128 call.start(session, callees[0]);
1129 } else {
1130 call.start(session, callees);
1131 }
1132
1133 return call;
1134 }
1135
1136 /**
1137 * Creates a {@link ImsCall} to take an incoming call.
1138 *
1139 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1140 * @param incomingCallIntent the incoming call broadcast intent
1141 * @param listener to listen to the call events from {@link ImsCall}
1142 * @return a {@link ImsCall} object
1143 * @throws ImsException if calling the IMS service results in an error
1144 */
1145 public ImsCall takeCall(int serviceId, Intent incomingCallIntent,
1146 ImsCall.Listener listener) throws ImsException {
1147 if (DBG) {
1148 log("takeCall :: serviceId=" + serviceId
1149 + ", incomingCall=" + incomingCallIntent);
1150 }
1151
1152 checkAndThrowExceptionIfServiceUnavailable();
1153
1154 if (incomingCallIntent == null) {
1155 throw new ImsException("Can't retrieve session with null intent",
1156 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1157 }
1158
1159 int incomingServiceId = getServiceId(incomingCallIntent);
1160
1161 if (serviceId != incomingServiceId) {
1162 throw new ImsException("Service id is mismatched in the incoming call intent",
1163 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1164 }
1165
1166 String callId = getCallId(incomingCallIntent);
1167
1168 if (callId == null) {
1169 throw new ImsException("Call ID missing in the incoming call intent",
1170 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1171 }
1172
1173 try {
1174 IImsCallSession session = mImsService.getPendingCallSession(serviceId, callId);
1175
1176 if (session == null) {
1177 throw new ImsException("No pending session for the call",
1178 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1179 }
1180
1181 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1182
1183 call.attachSession(new ImsCallSession(session));
1184 call.setListener(listener);
1185
1186 return call;
1187 } catch (Throwable t) {
1188 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1189 }
1190 }
1191
1192 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001193 * Gets the config interface to get/set service/capability parameters.
1194 *
1195 * @return the ImsConfig instance.
1196 * @throws ImsException if getting the setting interface results in an error.
1197 */
1198 public ImsConfig getConfigInterface() throws ImsException {
1199
1200 if (mConfig == null) {
1201 checkAndThrowExceptionIfServiceUnavailable();
1202
1203 try {
Etan Cohenabbd7882014-09-26 22:35:35 -07001204 IImsConfig config = mImsService.getConfigInterface(mPhoneId);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001205 if (config == null) {
1206 throw new ImsException("getConfigInterface()",
1207 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1208 }
Libin.Tang@motorola.com54953c72014-08-07 15:02:08 -05001209 mConfig = new ImsConfig(config, mContext);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001210 } catch (RemoteException e) {
1211 throw new ImsException("getConfigInterface()", e,
1212 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1213 }
1214 }
1215 if (DBG) log("getConfigInterface(), mConfig= " + mConfig);
1216 return mConfig;
1217 }
1218
Etan Cohen82f78122014-12-15 10:10:14 -08001219 public void setUiTTYMode(Context context, int serviceId, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301220 throws ImsException {
1221
Etan Cohen82f78122014-12-15 10:10:14 -08001222 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301223
Etan Cohen82f78122014-12-15 10:10:14 -08001224 try {
1225 mImsService.setUiTTYMode(serviceId, uiTtyMode, onComplete);
1226 } catch (RemoteException e) {
1227 throw new ImsException("setTTYMode()", e,
1228 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1229 }
1230
Junda Liue7663c02015-06-23 11:16:26 -07001231 if (!getBooleanCarrierConfig(context,
1232 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -08001233 setAdvanced4GMode((uiTtyMode == TelecomManager.TTY_MODE_OFF) &&
1234 isEnhanced4gLteModeSettingEnabledByUser(context));
1235 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301236 }
1237
Naveen Kalla525c3a22017-02-06 14:46:42 -08001238 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1239 Parcel p = Parcel.obtain();
1240 imsReasonInfo.writeToParcel(p, 0);
1241 p.setDataPosition(0);
1242 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1243 p.recycle();
1244 return clonedReasonInfo;
1245 }
1246
1247 /**
1248 * Get Recent IMS Disconnect Reasons.
1249 *
1250 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1251 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1252 * chronological order.
1253 */
1254 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1255 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1256
1257 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1258 disconnectReasons.add(makeACopy(reason));
1259 }
1260 return disconnectReasons;
1261 }
1262
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001263 /**
Junda Liue7663c02015-06-23 11:16:26 -07001264 * Get the boolean config from carrier config manager.
1265 *
1266 * @param context the context to get carrier service
1267 * @param key config key defined in CarrierConfigManager
1268 * @return boolean value of corresponding key.
1269 */
1270 private static boolean getBooleanCarrierConfig(Context context, String key) {
1271 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
1272 Context.CARRIER_CONFIG_SERVICE);
Jonathan Basseri2acea6f2015-07-01 15:00:38 -07001273 PersistableBundle b = null;
Junda Liue7663c02015-06-23 11:16:26 -07001274 if (configManager != null) {
Jonathan Basseri2acea6f2015-07-01 15:00:38 -07001275 b = configManager.getConfig();
1276 }
1277 if (b != null) {
1278 return b.getBoolean(key);
Junda Liue7663c02015-06-23 11:16:26 -07001279 } else {
1280 // Return static default defined in CarrierConfigManager.
1281 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1282 }
1283 }
1284
1285 /**
fionaxu5803ef02016-03-08 11:48:48 -08001286 * Get the int config from carrier config manager.
1287 *
1288 * @param context the context to get carrier service
1289 * @param key config key defined in CarrierConfigManager
1290 * @return integer value of corresponding key.
1291 */
1292 private static int getIntCarrierConfig(Context context, String key) {
1293 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
1294 Context.CARRIER_CONFIG_SERVICE);
1295 PersistableBundle b = null;
1296 if (configManager != null) {
1297 b = configManager.getConfig();
1298 }
1299 if (b != null) {
1300 return b.getInt(key);
1301 } else {
1302 // Return static default defined in CarrierConfigManager.
1303 return CarrierConfigManager.getDefaultConfig().getInt(key);
1304 }
1305 }
1306
1307 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001308 * Gets the call ID from the specified incoming call broadcast intent.
1309 *
1310 * @param incomingCallIntent the incoming call broadcast intent
1311 * @return the call ID or null if the intent does not contain it
1312 */
1313 private static String getCallId(Intent incomingCallIntent) {
1314 if (incomingCallIntent == null) {
1315 return null;
1316 }
1317
1318 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
1319 }
1320
1321 /**
1322 * Gets the service type from the specified incoming call broadcast intent.
1323 *
1324 * @param incomingCallIntent the incoming call broadcast intent
1325 * @return the service identifier or -1 if the intent does not contain it
1326 */
1327 private static int getServiceId(Intent incomingCallIntent) {
1328 if (incomingCallIntent == null) {
1329 return (-1);
1330 }
1331
1332 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
1333 }
1334
1335 /**
1336 * Binds the IMS service only if the service is not created.
1337 */
1338 private void checkAndThrowExceptionIfServiceUnavailable()
1339 throws ImsException {
1340 if (mImsService == null) {
1341 createImsService(true);
1342
1343 if (mImsService == null) {
1344 throw new ImsException("Service is unavailable",
1345 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1346 }
1347 }
1348 }
1349
Etan Cohenabbd7882014-09-26 22:35:35 -07001350 private static String getImsServiceName(int phoneId) {
1351 // TODO: MSIM implementation needs to decide on service name as a function of phoneId
Etan Cohend7727462014-07-12 14:54:10 -07001352 return IMS_SERVICE;
1353 }
1354
Wink Savilleef36ef62014-06-11 08:39:38 -07001355 /**
1356 * Binds the IMS service to make/receive the call.
1357 */
1358 private void createImsService(boolean checkService) {
1359 if (checkService) {
Etan Cohenabbd7882014-09-26 22:35:35 -07001360 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -07001361
1362 if (binder == null) {
1363 return;
1364 }
1365 }
1366
Etan Cohenabbd7882014-09-26 22:35:35 -07001367 IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -07001368
1369 if (b != null) {
1370 try {
1371 b.linkToDeath(mDeathRecipient, 0);
1372 } catch (RemoteException e) {
1373 }
1374 }
1375
1376 mImsService = IImsService.Stub.asInterface(b);
1377 }
1378
1379 /**
1380 * Creates a {@link ImsCallSession} with the specified call profile.
1381 * Use other methods, if applicable, instead of interacting with
1382 * {@link ImsCallSession} directly.
1383 *
1384 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1385 * @param profile a call profile to make the call
1386 */
1387 private ImsCallSession createCallSession(int serviceId,
1388 ImsCallProfile profile) throws ImsException {
1389 try {
1390 return new ImsCallSession(mImsService.createCallSession(serviceId, profile, null));
1391 } catch (RemoteException e) {
1392 return null;
1393 }
1394 }
1395
1396 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass,
1397 ImsConnectionStateListener listener) {
1398 ImsRegistrationListenerProxy proxy =
1399 new ImsRegistrationListenerProxy(serviceClass, listener);
1400 return proxy;
1401 }
1402
Etan Cohena00c9192014-12-23 15:02:29 -08001403 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001404 Rlog.d(TAG, s);
1405 }
1406
Etan Cohena00c9192014-12-23 15:02:29 -08001407 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001408 Rlog.e(TAG, s);
1409 }
1410
Etan Cohena00c9192014-12-23 15:02:29 -08001411 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001412 Rlog.e(TAG, s, t);
1413 }
1414
1415 /**
ram7da5a112014-07-16 20:59:27 +05301416 * Used for turning on IMS.if its off already
1417 */
Etan Cohen82f78122014-12-15 10:10:14 -08001418 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07001419 checkAndThrowExceptionIfServiceUnavailable();
1420
ram7da5a112014-07-16 20:59:27 +05301421 try {
Etan Cohenabbd7882014-09-26 22:35:35 -07001422 mImsService.turnOnIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05301423 } catch (RemoteException e) {
1424 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1425 }
1426 }
1427
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001428 private boolean isImsTurnOffAllowed() {
Meng Wang9352c432016-06-08 14:22:20 -07001429 return isTurnOffImsAllowedByPlatform(mContext)
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001430 && (!isWfcEnabledByPlatform(mContext)
1431 || !isWfcEnabledByUser(mContext));
1432 }
1433
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001434 private void setLteFeatureValues(boolean turnOn) {
1435 log("setLteFeatureValues: " + turnOn);
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001436 try {
1437 ImsConfig config = getConfigInterface();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001438 if (config != null) {
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001439 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001440 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07001441
1442 if (isVtEnabledByPlatform(mContext)) {
Jack Yu643ffe42016-07-08 14:25:46 -07001443 boolean enableViLte = turnOn && isVtEnabledByUser(mContext) &&
Amit Mahajan24f7b162016-07-21 16:33:53 -07001444 isDataEnabled();
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07001445 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1446 TelephonyManager.NETWORK_TYPE_LTE,
1447 enableViLte ? 1 : 0,
1448 mImsConfigListener);
1449 }
Etan Cohenb651fa52014-10-22 10:51:29 -07001450 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001451 } catch (ImsException e) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001452 loge("setLteFeatureValues: exception ", e);
Etan Cohencfc784d2014-08-07 18:40:31 -07001453 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001454 }
1455
1456 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
1457 checkAndThrowExceptionIfServiceUnavailable();
1458
1459 // if turnOn: first set feature values then call turnOnIms()
1460 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
1461 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07001462 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001463 setLteFeatureValues(turnOn);
1464 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07001465 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07001466 } else {
1467 if (isImsTurnOffAllowed()) {
1468 log("setAdvanced4GMode: turnOffIms");
1469 turnOffIms();
1470 }
1471 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07001472 }
1473 }
1474
ram7da5a112014-07-16 20:59:27 +05301475 /**
1476 * Used for turning off IMS completely in order to make the device CSFB'ed.
1477 * Once turned off, all calls will be over CS.
1478 */
Etan Cohen82f78122014-12-15 10:10:14 -08001479 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07001480 checkAndThrowExceptionIfServiceUnavailable();
1481
ram7da5a112014-07-16 20:59:27 +05301482 try {
Etan Cohenabbd7882014-09-26 22:35:35 -07001483 mImsService.turnOffIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05301484 } catch (RemoteException e) {
1485 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1486 }
1487 }
1488
Naveen Kalla525c3a22017-02-06 14:46:42 -08001489 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
1490 if (reason == null) return;
1491 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
1492 mRecentDisconnectReasons.removeFirst();
1493 }
1494 mRecentDisconnectReasons.addLast(reason);
1495 }
1496
ram7da5a112014-07-16 20:59:27 +05301497 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001498 * Death recipient class for monitoring IMS service.
1499 */
1500 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
1501 @Override
1502 public void binderDied() {
1503 mImsService = null;
1504 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001505 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001506 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001507 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001508
1509 if (mContext != null) {
Etan Cohend7727462014-07-12 14:54:10 -07001510 Intent intent = new Intent(ACTION_IMS_SERVICE_DOWN);
Etan Cohenabbd7882014-09-26 22:35:35 -07001511 intent.putExtra(EXTRA_PHONE_ID, mPhoneId);
Etan Cohend7727462014-07-12 14:54:10 -07001512 mContext.sendBroadcast(new Intent(intent));
Wink Savilleef36ef62014-06-11 08:39:38 -07001513 }
1514 }
1515 }
1516
1517 /**
1518 * Adapter class for {@link IImsRegistrationListener}.
1519 */
1520 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
1521 private int mServiceClass;
1522 private ImsConnectionStateListener mListener;
1523
1524 public ImsRegistrationListenerProxy(int serviceClass,
1525 ImsConnectionStateListener listener) {
1526 mServiceClass = serviceClass;
1527 mListener = listener;
1528 }
1529
1530 public boolean isSameProxy(int serviceClass) {
1531 return (mServiceClass == serviceClass);
1532 }
1533
Omkar Kolangadea7ced642015-05-04 17:55:13 -07001534 @Deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -07001535 public void registrationConnected() {
1536 if (DBG) {
1537 log("registrationConnected ::");
1538 }
1539
1540 if (mListener != null) {
1541 mListener.onImsConnected();
1542 }
1543 }
1544
Omkar Kolangadea7ced642015-05-04 17:55:13 -07001545 @Deprecated
Rekha Kumar14631742015-02-04 10:47:00 -08001546 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07001547 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08001548 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07001549 }
1550
1551 if (mListener != null) {
Rekha Kumar14631742015-02-04 10:47:00 -08001552 mListener.onImsProgressing();
1553 }
1554 }
1555
1556 @Override
Omkar Kolangadea7ced642015-05-04 17:55:13 -07001557 public void registrationConnectedWithRadioTech(int imsRadioTech) {
1558 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
1559 // values in ServiceState.java.
1560 if (DBG) {
1561 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
1562 }
1563
1564 if (mListener != null) {
1565 mListener.onImsConnected();
1566 }
1567 }
1568
1569 @Override
1570 public void registrationProgressingWithRadioTech(int imsRadioTech) {
1571 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
1572 // values in ServiceState.java.
1573 if (DBG) {
1574 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
1575 }
1576
1577 if (mListener != null) {
1578 mListener.onImsProgressing();
1579 }
1580 }
1581
1582 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08001583 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
1584 if (DBG) {
1585 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
1586 }
1587
Naveen Kalla525c3a22017-02-06 14:46:42 -08001588 addToRecentDisconnectReasons(imsReasonInfo);
1589
Rekha Kumar14631742015-02-04 10:47:00 -08001590 if (mListener != null) {
1591 mListener.onImsDisconnected(imsReasonInfo);
Wink Savilleef36ef62014-06-11 08:39:38 -07001592 }
1593 }
1594
1595 @Override
1596 public void registrationResumed() {
1597 if (DBG) {
1598 log("registrationResumed ::");
1599 }
1600
1601 if (mListener != null) {
1602 mListener.onImsResumed();
1603 }
1604 }
1605
1606 @Override
1607 public void registrationSuspended() {
1608 if (DBG) {
1609 log("registrationSuspended ::");
1610 }
1611
1612 if (mListener != null) {
1613 mListener.onImsSuspended();
1614 }
1615 }
1616
1617 @Override
1618 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
1619 log("registrationServiceCapabilityChanged :: serviceClass=" +
1620 serviceClass + ", event=" + event);
1621
1622 if (mListener != null) {
1623 mListener.onImsConnected();
1624 }
1625 }
ram7da5a112014-07-16 20:59:27 +05301626
1627 @Override
1628 public void registrationFeatureCapabilityChanged(int serviceClass,
1629 int[] enabledFeatures, int[] disabledFeatures) {
1630 log("registrationFeatureCapabilityChanged :: serviceClass=" +
1631 serviceClass);
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05001632 if (mListener != null) {
1633 mListener.onFeatureCapabilityChanged(serviceClass,
1634 enabledFeatures, disabledFeatures);
1635 }
ram7da5a112014-07-16 20:59:27 +05301636 }
1637
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07001638 @Override
1639 public void voiceMessageCountUpdate(int count) {
1640 log("voiceMessageCountUpdate :: count=" + count);
1641
1642 if (mListener != null) {
1643 mListener.onVoiceMessageCountChanged(count);
1644 }
1645 }
1646
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08001647 @Override
1648 public void registrationAssociatedUriChanged(Uri[] uris) {
1649 if (DBG) log("registrationAssociatedUriChanged ::");
1650
1651 if (mListener != null) {
1652 mListener.registrationAssociatedUriChanged(uris);
1653 }
1654 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001655 }
Tyler Gunn4d128b62016-04-13 15:44:38 -07001656
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001657 /**
1658 * Gets the ECBM interface to request ECBM exit.
1659 *
1660 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1661 * @return the ECBM interface instance
1662 * @throws ImsException if getting the ECBM interface results in an error
1663 */
1664 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
1665 if (mEcbm == null) {
1666 checkAndThrowExceptionIfServiceUnavailable();
1667
1668 try {
1669 IImsEcbm iEcbm = mImsService.getEcbmInterface(serviceId);
1670
1671 if (iEcbm == null) {
1672 throw new ImsException("getEcbmInterface()",
1673 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
1674 }
1675 mEcbm = new ImsEcbm(iEcbm);
1676 } catch (RemoteException e) {
1677 throw new ImsException("getEcbmInterface()", e,
1678 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1679 }
1680 }
1681 return mEcbm;
1682 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001683
1684 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07001685 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
1686 *
1687 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1688 * @return the multi-endpoint interface instance
1689 * @throws ImsException if getting the multi-endpoint interface results in an error
1690 */
1691 public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
1692 if (mMultiEndpoint == null) {
1693 checkAndThrowExceptionIfServiceUnavailable();
1694
1695 try {
1696 IImsMultiEndpoint iImsMultiEndpoint = mImsService.getMultiEndpointInterface(
1697 serviceId);
1698
1699 if (iImsMultiEndpoint == null) {
1700 throw new ImsException("getMultiEndpointInterface()",
1701 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
1702 }
1703 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
1704 } catch (RemoteException e) {
1705 throw new ImsException("getMultiEndpointInterface()", e,
1706 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1707 }
1708 }
1709 return mMultiEndpoint;
1710 }
1711
1712 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001713 * Resets ImsManager settings back to factory defaults.
1714 *
1715 * @hide
1716 */
1717 public static void factoryReset(Context context) {
1718 // Set VoLTE to default
1719 android.provider.Settings.Global.putInt(context.getContentResolver(),
1720 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
1721 ImsConfig.FeatureValueConstants.ON);
1722
1723 // Set VoWiFi to default
1724 android.provider.Settings.Global.putInt(context.getContentResolver(),
1725 android.provider.Settings.Global.WFC_IMS_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08001726 getBooleanCarrierConfig(context,
1727 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
1728 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001729
1730 // Set VoWiFi mode to default
1731 android.provider.Settings.Global.putInt(context.getContentResolver(),
1732 android.provider.Settings.Global.WFC_IMS_MODE,
fionaxu5803ef02016-03-08 11:48:48 -08001733 getIntCarrierConfig(context,
1734 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001735
1736 // Set VoWiFi roaming to default
1737 android.provider.Settings.Global.putInt(context.getContentResolver(),
1738 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08001739 getBooleanCarrierConfig(context,
1740 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
1741 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001742
1743 // Set VT to default
Pavel Zhamaitsiak92b54b22016-04-01 15:55:47 -07001744 android.provider.Settings.Global.putInt(context.getContentResolver(),
1745 android.provider.Settings.Global.VT_IMS_ENABLED,
1746 ImsConfig.FeatureValueConstants.ON);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001747
1748 // Push settings to ImsConfig
1749 ImsManager.updateImsServiceConfig(context,
1750 SubscriptionManager.getDefaultVoicePhoneId(), true);
1751 }
Jack Yu2f102bd2015-12-28 15:31:48 -08001752
Amit Mahajan24f7b162016-07-21 16:33:53 -07001753 private boolean isDataEnabled() {
1754 return SystemProperties.getBoolean(DATA_ENABLED_PROP, true);
1755 }
1756
Jack Yu643ffe42016-07-08 14:25:46 -07001757 /**
1758 * Set data enabled/disabled flag.
1759 * @param enabled True if data is enabled, otherwise disabled.
1760 */
1761 public void setDataEnabled(boolean enabled) {
1762 log("setDataEnabled: " + enabled);
Amit Mahajan24f7b162016-07-21 16:33:53 -07001763 SystemProperties.set(DATA_ENABLED_PROP, enabled ? TRUE : FALSE);
1764 }
1765
1766 private boolean isVolteProvisioned() {
1767 return SystemProperties.getBoolean(VOLTE_PROVISIONED_PROP, true);
1768 }
1769
1770 private void setVolteProvisionedProperty(boolean provisioned) {
1771 SystemProperties.set(VOLTE_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
1772 }
1773
1774 private boolean isWfcProvisioned() {
1775 return SystemProperties.getBoolean(WFC_PROVISIONED_PROP, true);
1776 }
1777
1778 private void setWfcProvisionedProperty(boolean provisioned) {
1779 SystemProperties.set(WFC_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
1780 }
1781
1782 private boolean isVtProvisioned() {
1783 return SystemProperties.getBoolean(VT_PROVISIONED_PROP, true);
1784 }
1785
1786 private void setVtProvisionedProperty(boolean provisioned) {
1787 SystemProperties.set(VT_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
Jack Yu643ffe42016-07-08 14:25:46 -07001788 }
1789
Jack Yu2f102bd2015-12-28 15:31:48 -08001790 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1791 pw.println("ImsManager:");
1792 pw.println(" mPhoneId = " + mPhoneId);
1793 pw.println(" mConfigUpdated = " + mConfigUpdated);
1794 pw.println(" mImsService = " + mImsService);
Amit Mahajan24f7b162016-07-21 16:33:53 -07001795 pw.println(" mDataEnabled = " + isDataEnabled());
Jack Yu2f102bd2015-12-28 15:31:48 -08001796
1797 pw.println(" isGbaValid = " + isGbaValid(mContext));
1798 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
1799 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled(mContext));
1800
1801 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform(mContext));
1802 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice(mContext));
1803 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
1804 isEnhanced4gLteModeSettingEnabledByUser(mContext));
1805 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform(mContext));
1806 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser(mContext));
1807
1808 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform(mContext));
1809 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser(mContext));
1810 pw.println(" getWfcMode = " + getWfcMode(mContext));
1811 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser(mContext));
1812
pkanwar10d18832016-07-12 08:50:01 -07001813 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDevice(mContext));
1814 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDevice(mContext));
Jack Yu2f102bd2015-12-28 15:31:48 -08001815 pw.flush();
1816 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001817}