blob: d10691dd0d4bd12218c056e03f8488443dd77ff1 [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;
Brad Ebinger14b0a9e2017-01-26 11:18:21 -080037import android.telephony.ims.ImsServiceProxy;
38import android.telephony.ims.ImsServiceProxyCompat;
39import android.telephony.ims.feature.ImsFeature;
Wink Savilleef36ef62014-06-11 08:39:38 -070040
41import com.android.ims.internal.IImsCallSession;
Naveen Kalla525c3a22017-02-06 14:46:42 -080042import com.android.ims.internal.IImsConfig;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070043import com.android.ims.internal.IImsEcbm;
Tyler Gunn4d128b62016-04-13 15:44:38 -070044import com.android.ims.internal.IImsMultiEndpoint;
Wink Savilleef36ef62014-06-11 08:39:38 -070045import com.android.ims.internal.IImsRegistrationListener;
Brad Ebinger14b0a9e2017-01-26 11:18:21 -080046import com.android.ims.internal.IImsServiceController;
Wink Savilleef36ef62014-06-11 08:39:38 -070047import com.android.ims.internal.IImsUt;
48import com.android.ims.internal.ImsCallSession;
Brad Ebinger14b0a9e2017-01-26 11:18:21 -080049import com.android.ims.internal.IImsConfig;
50import com.android.internal.annotations.VisibleForTesting;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050051
Jack Yu2f102bd2015-12-28 15:31:48 -080052import java.io.FileDescriptor;
53import java.io.PrintWriter;
Naveen Kalla525c3a22017-02-06 14:46:42 -080054import java.util.ArrayList;
Etan Cohend7727462014-07-12 14:54:10 -070055import java.util.HashMap;
Naveen Kalla525c3a22017-02-06 14:46:42 -080056import java.util.concurrent.ConcurrentLinkedDeque;
Brad Ebinger14b0a9e2017-01-26 11:18:21 -080057import java.util.HashSet;
58import java.util.Optional;
59import java.util.Set;
Etan Cohend7727462014-07-12 14:54:10 -070060
Wink Savilleef36ef62014-06-11 08:39:38 -070061/**
62 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
63 * the operator's IMS network. This class is the starting point for any IMS actions.
64 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
65 * <p>The APIs in this class allows you to:</p>
66 *
67 * @hide
68 */
69public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070070
Etan Cohenaf55a402014-09-04 22:34:41 -070071 /*
72 * Debug flag to override configuration flag
73 */
Etan Cohenb651fa52014-10-22 10:51:29 -070074 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
75 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070076 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
77 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080078 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
79 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Meng Wang9352c432016-06-08 14:22:20 -070080 public static final String PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE = "persist.dbg.allow_ims_off";
81 public static final int PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070082
Wink Savilleef36ef62014-06-11 08:39:38 -070083 /**
84 * For accessing the IMS related service.
85 * Internal use only.
86 * @hide
87 */
Etan Cohend7727462014-07-12 14:54:10 -070088 private static final String IMS_SERVICE = "ims";
Wink Savilleef36ef62014-06-11 08:39:38 -070089
90 /**
91 * The result code to be sent back with the incoming call {@link PendingIntent}.
92 * @see #open(PendingIntent, ImsConnectionStateListener)
93 */
94 public static final int INCOMING_CALL_RESULT_CODE = 101;
95
96 /**
97 * Key to retrieve the call ID from an incoming call intent.
98 * @see #open(PendingIntent, ImsConnectionStateListener)
99 */
100 public static final String EXTRA_CALL_ID = "android:imsCallID";
101
102 /**
103 * Action to broadcast when ImsService is up.
104 * Internal use only.
Brad Ebinger14b0a9e2017-01-26 11:18:21 -0800105 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700106 * @hide
107 */
108 public static final String ACTION_IMS_SERVICE_UP =
109 "com.android.ims.IMS_SERVICE_UP";
110
111 /**
112 * Action to broadcast when ImsService is down.
113 * Internal use only.
Brad Ebinger14b0a9e2017-01-26 11:18:21 -0800114 * @deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -0700115 * @hide
116 */
117 public static final String ACTION_IMS_SERVICE_DOWN =
118 "com.android.ims.IMS_SERVICE_DOWN";
119
120 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700121 * Action to broadcast when ImsService registration fails.
122 * Internal use only.
123 * @hide
124 */
125 public static final String ACTION_IMS_REGISTRATION_ERROR =
126 "com.android.ims.REGISTRATION_ERROR";
127
128 /**
Etan Cohend7727462014-07-12 14:54:10 -0700129 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700130 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700131 * Internal use only.
132 * @hide
133 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700134 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700135
136 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700137 * Action for the incoming call intent for the Phone app.
138 * Internal use only.
139 * @hide
140 */
141 public static final String ACTION_IMS_INCOMING_CALL =
142 "com.android.ims.IMS_INCOMING_CALL";
143
144 /**
145 * Part of the ACTION_IMS_INCOMING_CALL intents.
146 * An integer value; service identifier obtained from {@link ImsManager#open}.
147 * Internal use only.
148 * @hide
149 */
150 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
151
152 /**
153 * Part of the ACTION_IMS_INCOMING_CALL intents.
154 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
155 * The value "true" indicates that the incoming call is for USSD.
156 * Internal use only.
157 * @hide
158 */
159 public static final String EXTRA_USSD = "android:ussd";
160
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700161 /**
162 * Part of the ACTION_IMS_INCOMING_CALL intents.
163 * A boolean value; Flag to indicate whether the call is an unknown
164 * dialing call. Such calls are originated by sending commands (like
165 * AT commands) directly to modem without Android involvement.
166 * Even though they are not incoming calls, they are propagated
167 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
168 * Internal use only.
169 * @hide
170 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700171 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700172
Wink Savilleef36ef62014-06-11 08:39:38 -0700173 private static final String TAG = "ImsManager";
174 private static final boolean DBG = true;
175
Wink Saville1e5a38a2014-10-23 10:24:46 -0700176 private static HashMap<Integer, ImsManager> sImsManagerInstances =
177 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700178
Wink Savilleef36ef62014-06-11 08:39:38 -0700179 private Context mContext;
Brad Ebinger16417b42017-03-07 13:48:50 -0800180 private CarrierConfigManager mConfigManager;
Etan Cohenabbd7882014-09-26 22:35:35 -0700181 private int mPhoneId;
Brad Ebinger14b0a9e2017-01-26 11:18:21 -0800182 private final boolean mConfigDynamicBind;
183 private ImsServiceProxyCompat mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700184 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
185 // Ut interface for the supplementary service configuration
186 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500187 // Interface to get/set ims config items
188 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700189 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700190
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800191 private ImsConfigListener mImsConfigListener;
192
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700193 // ECBM interface
194 private ImsEcbm mEcbm = null;
195
Tyler Gunn4d128b62016-04-13 15:44:38 -0700196 private ImsMultiEndpoint mMultiEndpoint = null;
197
Brad Ebinger14b0a9e2017-01-26 11:18:21 -0800198 private Set<ImsServiceProxy.INotifyStatusChanged> mStatusCallbacks = new HashSet<>();
199
200 // Keep track of the ImsRegistrationListenerProxys that have been created so that we can
201 // remove them from the ImsService.
202 private Set<ImsRegistrationListenerProxy> mRegistrationListeners = new HashSet<>();
203
Amit Mahajan24f7b162016-07-21 16:33:53 -0700204 // SystemProperties used as cache
205 private static final String VOLTE_PROVISIONED_PROP = "net.lte.ims.volte.provisioned";
206 private static final String WFC_PROVISIONED_PROP = "net.lte.ims.wfc.provisioned";
207 private static final String VT_PROVISIONED_PROP = "net.lte.ims.vt.provisioned";
Jack Yu643ffe42016-07-08 14:25:46 -0700208 // Flag indicating data enabled or not. This flag should be in sync with
209 // DcTracker.isDataEnabled(). The flag will be set later during boot up.
Amit Mahajan24f7b162016-07-21 16:33:53 -0700210 private static final String DATA_ENABLED_PROP = "net.lte.ims.data.enabled";
211
212 public static final String TRUE = "true";
213 public static final String FALSE = "false";
Jack Yu643ffe42016-07-08 14:25:46 -0700214
Naveen Kalla525c3a22017-02-06 14:46:42 -0800215 // mRecentDisconnectReasons stores the last 16 disconnect reasons
216 private static final int MAX_RECENT_DISCONNECT_REASONS = 16;
217 private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
218 new ConcurrentLinkedDeque<>();
219
Wink Savilleef36ef62014-06-11 08:39:38 -0700220 /**
221 * Gets a manager instance.
222 *
223 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700224 * @param phoneId the phone ID for the IMS Service
225 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700226 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700227 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700228 synchronized (sImsManagerInstances) {
Naveen Kalla525c3a22017-02-06 14:46:42 -0800229 if (sImsManagerInstances.containsKey(phoneId)) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700230 return sImsManagerInstances.get(phoneId);
Naveen Kalla525c3a22017-02-06 14:46:42 -0800231 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700232
Etan Cohenabbd7882014-09-26 22:35:35 -0700233 ImsManager mgr = new ImsManager(context, phoneId);
234 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700235
236 return mgr;
237 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700238 }
239
Etan Cohen45b5f312014-08-19 15:55:08 -0700240 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800241 * Returns the user configuration of Enhanced 4G LTE Mode setting.
242 *
243 * @deprecated Doesn't support MSIM devices. Use
244 * {@link #isEnhanced4gLteModeSettingEnabledByUserForSlot} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700245 */
246 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Sungmin Choi2f1af952016-02-01 17:15:35 +0900247 // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true.
248 // If user changes SIM from editable mode to uneditable mode, need to return true.
249 if (!getBooleanCarrierConfig(context,
250 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
251 return true;
252 }
Libin.Tang@motorola.com8a6bf4b2014-10-10 15:02:41 -0500253 int enabled = android.provider.Settings.Global.getInt(
Brad Ebinger16417b42017-03-07 13:48:50 -0800254 context.getContentResolver(),
255 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
256 ImsConfig.FeatureValueConstants.ON);
Etan Cohena00c9192014-12-23 15:02:29 -0800257 return (enabled == 1) ? true : false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700258 }
259
260 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800261 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot.
262 */
263 public boolean isEnhanced4gLteModeSettingEnabledByUserForSlot() {
264 // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true.
265 // If user changes SIM from editable mode to uneditable mode, need to return true.
266 if (!getBooleanCarrierConfigForSlot(
267 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
268 return true;
269 }
270 int enabled = android.provider.Settings.Global.getInt(
271 mContext.getContentResolver(),
272 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
273 ImsConfig.FeatureValueConstants.ON);
274 return (enabled == 1);
275 }
276
277 /**
278 * Change persistent Enhanced 4G LTE Mode setting.
279 *
280 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSettingForSlot}
281 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800282 */
283 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
284 int value = enabled ? 1 : 0;
285 android.provider.Settings.Global.putInt(
286 context.getContentResolver(),
287 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
288
289 if (isNonTtyOrTtyOnVolteEnabled(context)) {
290 ImsManager imsManager = ImsManager.getInstance(context,
291 SubscriptionManager.getDefaultVoicePhoneId());
292 if (imsManager != null) {
293 try {
294 imsManager.setAdvanced4GMode(enabled);
295 } catch (ImsException ie) {
296 // do nothing
297 }
298 }
299 }
300 }
301
302 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800303 * Change persistent Enhanced 4G LTE Mode setting. If the the option is not editable
304 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
305 * always set the setting to true.
306 *
307 */
308 public void setEnhanced4gLteModeSettingForSlot(boolean enabled) {
309 // If false, we must always keep advanced 4G mode set to true (1).
310 int value = getBooleanCarrierConfigForSlot(
311 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL) ? (enabled ? 1: 0) : 1;
312
313 try {
314 int prevSetting = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
315 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED);
316 if (prevSetting == value) {
317 // Don't trigger setAdvanced4GMode if the setting hasn't changed.
318 return;
319 }
320 } catch (Settings.SettingNotFoundException e) {
321 // Setting doesn't exist yet, so set it below.
322 }
323
324 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
325 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
326 if (isNonTtyOrTtyOnVolteEnabledForSlot()) {
327 try {
328 setAdvanced4GMode(enabled);
329 } catch (ImsException ie) {
330 // do nothing
331 }
332 }
333 }
334
335 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800336 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
337 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800338 * @deprecated Does not support MSIM devices. Please use
339 * {@link #isNonTtyOrTtyOnVolteEnabledForSlot} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800340 */
341 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700342 if (getBooleanCarrierConfig(context,
fionaxu5803ef02016-03-08 11:48:48 -0800343 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800344 return true;
345 }
346
347 return Settings.Secure.getInt(context.getContentResolver(),
348 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
349 == TelecomManager.TTY_MODE_OFF;
350 }
351
352 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800353 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
354 * supported on a per slot basis.
355 */
356 public boolean isNonTtyOrTtyOnVolteEnabledForSlot() {
357 if (getBooleanCarrierConfigForSlot(
358 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
359 return true;
360 }
361
362 return Settings.Secure.getInt(mContext.getContentResolver(),
363 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
364 == TelecomManager.TTY_MODE_OFF;
365 }
366
367 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700368 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800369 * @deprecated Does not support MSIM devices. Please use
370 * {@link #isVolteEnabledByPlatformForSlot()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700371 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700372 public static boolean isVolteEnabledByPlatform(Context context) {
Etan Cohenb651fa52014-10-22 10:51:29 -0700373 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
374 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
Etan Cohenaf55a402014-09-04 22:34:41 -0700375 return true;
376 }
377
Etan Cohenb5388a32014-11-26 11:57:47 -0800378 return context.getResources().getBoolean(
Junda Liue7663c02015-06-23 11:16:26 -0700379 com.android.internal.R.bool.config_device_volte_available)
380 && getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700381 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
382 && isGbaValid(context);
Etan Cohenb5388a32014-11-26 11:57:47 -0800383 }
384
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700385 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800386 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
387 * basis.
388 */
389 public boolean isVolteEnabledByPlatformForSlot() {
390 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
391 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
392 return true;
393 }
394
395 return mContext.getResources().getBoolean(
396 com.android.internal.R.bool.config_device_volte_available)
397 && getBooleanCarrierConfigForSlot(
398 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
399 && isGbaValidForSlot();
400 }
401
402 /**
403 * Indicates whether VoLTE is provisioned on device.
404 *
405 * @deprecated Does not support MSIM devices. Please use
406 * {@link #isVolteProvisionedOnDeviceForSlot()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800407 */
408 public static boolean isVolteProvisionedOnDevice(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700409 if (getBooleanCarrierConfig(context,
410 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Etan Cohenb5388a32014-11-26 11:57:47 -0800411 ImsManager mgr = ImsManager.getInstance(context,
Jonathan Basserid7133652015-04-07 19:54:24 -0700412 SubscriptionManager.getDefaultVoicePhoneId());
Etan Cohenb5388a32014-11-26 11:57:47 -0800413 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700414 return mgr.isVolteProvisioned();
Etan Cohenb5388a32014-11-26 11:57:47 -0800415 }
416 }
417
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700418 return true;
419 }
420
421 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800422 * Indicates whether VoLTE is provisioned on this slot.
423 */
424 public boolean isVolteProvisionedOnDeviceForSlot() {
425 if (getBooleanCarrierConfigForSlot(
426 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
427 return isVolteProvisioned();
428 }
429
430 return true;
431 }
432
433 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700434 * Indicates whether VoWifi is provisioned on device.
435 *
436 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
437 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800438 *
439 * @deprecated Does not support MSIM devices. Please use
440 * {@link #isWfcProvisionedOnDeviceForSlot()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700441 */
442 public static boolean isWfcProvisionedOnDevice(Context context) {
443 if (getBooleanCarrierConfig(context,
Meng Wang54fd41a2017-04-12 11:44:47 -0700444 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
445 if (!isVolteProvisionedOnDevice(context)) {
446 return false;
447 }
448 }
449
450 if (getBooleanCarrierConfig(context,
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700451 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
452 ImsManager mgr = ImsManager.getInstance(context,
453 SubscriptionManager.getDefaultVoicePhoneId());
454 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700455 return mgr.isWfcProvisioned();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700456 }
457 }
458
459 return true;
460 }
461
462 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800463 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700464 *
465 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
466 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800467 */
468 public boolean isWfcProvisionedOnDeviceForSlot() {
469 if (getBooleanCarrierConfigForSlot(
Meng Wang54fd41a2017-04-12 11:44:47 -0700470 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
471 if (!isVolteProvisionedOnDeviceForSlot()) {
472 return false;
473 }
474 }
475
476 if (getBooleanCarrierConfigForSlot(
Brad Ebinger16417b42017-03-07 13:48:50 -0800477 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700478 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800479 }
480
481 return true;
482 }
483
484 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700485 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800486 *
487 * @deprecated Does not support MSIM devices. Please use
488 * {@link #isVtProvisionedOnDeviceForSlot()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700489 */
490 public static boolean isVtProvisionedOnDevice(Context context) {
491 if (getBooleanCarrierConfig(context,
492 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
493 ImsManager mgr = ImsManager.getInstance(context,
494 SubscriptionManager.getDefaultVoicePhoneId());
495 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700496 return mgr.isVtProvisioned();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700497 }
498 }
499
500 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700501 }
502
Etan Cohenea2b5832014-10-23 18:50:35 -0700503 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800504 * Indicates whether VT is provisioned on slot.
505 */
506 public boolean isVtProvisionedOnDeviceForSlot() {
507 if (getBooleanCarrierConfigForSlot(
508 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
509 return isVtProvisioned();
510 }
511
512 return true;
513 }
514
515 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700516 * Returns a platform configuration for VT which may override the user setting.
517 *
518 * Note: VT presumes that VoLTE is enabled (these are configuration settings
519 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800520 *
521 * @deprecated Does not support MSIM devices. Please use
522 * {@link #isVtEnabledByPlatformForSlot()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700523 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700524 public static boolean isVtEnabledByPlatform(Context context) {
Etan Cohenea2b5832014-10-23 18:50:35 -0700525 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
526 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
527 return true;
528 }
529
Etan Cohenb651fa52014-10-22 10:51:29 -0700530 return
531 context.getResources().getBoolean(
532 com.android.internal.R.bool.config_device_vt_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700533 getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700534 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
535 isGbaValid(context);
Etan Cohen45b5f312014-08-19 15:55:08 -0700536 }
537
Etan Cohena00c9192014-12-23 15:02:29 -0800538 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800539 * Returns a platform configuration for VT which may override the user setting.
540 *
541 * Note: VT presumes that VoLTE is enabled (these are configuration settings
542 * which must be done correctly).
543 */
544 public boolean isVtEnabledByPlatformForSlot() {
545 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
546 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
547 return true;
548 }
549
550 return mContext.getResources().getBoolean(
551 com.android.internal.R.bool.config_device_vt_available) &&
552 getBooleanCarrierConfigForSlot(
553 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
554 isGbaValidForSlot();
555 }
556
557 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700558 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800559 * @deprecated Does not support MSIM devices. Please use
560 * {@link #isVtEnabledByUserForSlot()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700561 */
562 public static boolean isVtEnabledByUser(Context context) {
563 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
564 android.provider.Settings.Global.VT_IMS_ENABLED,
565 ImsConfig.FeatureValueConstants.ON);
566 return (enabled == 1) ? true : false;
567 }
568
569 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800570 * Returns the user configuration of VT setting per slot.
571 */
572 public boolean isVtEnabledByUserForSlot() {
573 int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
574 android.provider.Settings.Global.VT_IMS_ENABLED,
575 ImsConfig.FeatureValueConstants.ON);
576 return (enabled == 1);
577 }
578
579 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700580 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800581 *
582 * @deprecated Does not support MSIM devices. Please use
583 * {@link #setVtSettingForSlot} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700584 */
585 public static void setVtSetting(Context context, boolean enabled) {
586 int value = enabled ? 1 : 0;
587 android.provider.Settings.Global.putInt(context.getContentResolver(),
588 android.provider.Settings.Global.VT_IMS_ENABLED, value);
589
590 ImsManager imsManager = ImsManager.getInstance(context,
591 SubscriptionManager.getDefaultVoicePhoneId());
592 if (imsManager != null) {
593 try {
594 ImsConfig config = imsManager.getConfigInterface();
595 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
596 TelephonyManager.NETWORK_TYPE_LTE,
597 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800598 : ImsConfig.FeatureValueConstants.OFF,
599 imsManager.mImsConfigListener);
Etan Cohena7d32e82015-05-04 18:02:09 -0700600
601 if (enabled) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700602 log("setVtSetting() : turnOnIms");
Etan Cohena7d32e82015-05-04 18:02:09 -0700603 imsManager.turnOnIms();
Meng Wang9352c432016-06-08 14:22:20 -0700604 } else if (isTurnOffImsAllowedByPlatform(context)
Pavel Zhamaitsiak4ca0cde2015-12-22 16:51:57 -0800605 && (!isVolteEnabledByPlatform(context)
Etan Cohena7d32e82015-05-04 18:02:09 -0700606 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
607 log("setVtSetting() : imsServiceAllowTurnOff -> turnOffIms");
608 imsManager.turnOffIms();
609 }
610 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700611 loge("setVtSetting(): ", e);
Etan Cohena7d32e82015-05-04 18:02:09 -0700612 }
613 }
614 }
615
Brad Ebinger16417b42017-03-07 13:48:50 -0800616 /**
617 * Change persistent VT enabled setting for slot.
618 */
619 public void setVtSettingForSlot(boolean enabled) {
620 int value = enabled ? 1 : 0;
621 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
622 android.provider.Settings.Global.VT_IMS_ENABLED, value);
623
624 try {
625 ImsConfig config = getConfigInterface();
626 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
627 TelephonyManager.NETWORK_TYPE_LTE,
628 enabled ? ImsConfig.FeatureValueConstants.ON
629 : ImsConfig.FeatureValueConstants.OFF,
630 mImsConfigListener);
631
632 if (enabled) {
633 log("setVtSettingForSlot() : turnOnIms");
634 turnOnIms();
635 } else if (isVolteEnabledByPlatformForSlot()
636 && (!isVolteEnabledByPlatformForSlot()
637 || !isEnhanced4gLteModeSettingEnabledByUserForSlot())) {
638 log("setVtSettingForSlot() : imsServiceAllowTurnOff -> turnOffIms");
639 turnOffIms();
640 }
641 } catch (ImsException e) {
642 loge("setVtSettingForSlot(): ", e);
643 }
644 }
645
646 /**
Meng Wang9352c432016-06-08 14:22:20 -0700647 * Returns whether turning off ims is allowed by platform.
648 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800649 *
650 * @deprecated Does not support MSIM devices. Please use
651 * {@link #isTurnOffImsAllowedByPlatformForSlot} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700652 */
653 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
654 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
655 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
656 return true;
657 }
658 return getBooleanCarrierConfig(context,
659 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
660 }
661
Etan Cohena7d32e82015-05-04 18:02:09 -0700662 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800663 * Returns whether turning off ims is allowed by platform.
664 * The platform property may override the carrier config.
665 */
666 private boolean isTurnOffImsAllowedByPlatformForSlot() {
667 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
668 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
669 return true;
670 }
671 return getBooleanCarrierConfigForSlot(
672 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
673 }
674
675 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800676 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800677 *
678 * @deprecated Does not support MSIM devices. Please use
679 * {@link #isTurnOffImsAllowedByPlatformForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800680 */
681 public static boolean isWfcEnabledByUser(Context context) {
682 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
683 android.provider.Settings.Global.WFC_IMS_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800684 getBooleanCarrierConfig(context,
685 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
686 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800687 return (enabled == 1) ? true : false;
688 }
689
690 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800691 * Returns the user configuration of WFC setting for slot.
692 */
693 public boolean isWfcEnabledByUserForSlot() {
694 int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
695 android.provider.Settings.Global.WFC_IMS_ENABLED,
696 getBooleanCarrierConfigForSlot(
697 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
698 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
699 return enabled == 1;
700 }
701
702 /**
703 * Change persistent WFC enabled setting.
704 * @deprecated Does not support MSIM devices. Please use
705 * {@link #setWfcSettingForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800706 */
707 public static void setWfcSetting(Context context, boolean enabled) {
708 int value = enabled ? 1 : 0;
709 android.provider.Settings.Global.putInt(context.getContentResolver(),
710 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
711
712 ImsManager imsManager = ImsManager.getInstance(context,
713 SubscriptionManager.getDefaultVoicePhoneId());
714 if (imsManager != null) {
715 try {
716 ImsConfig config = imsManager.getConfigInterface();
Etan Cohena00c9192014-12-23 15:02:29 -0800717 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
Nathan Harold3a99f782015-07-24 15:02:34 -0700718 TelephonyManager.NETWORK_TYPE_IWLAN,
Etan Cohena00c9192014-12-23 15:02:29 -0800719 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800720 : ImsConfig.FeatureValueConstants.OFF,
721 imsManager.mImsConfigListener);
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800722
723 if (enabled) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700724 log("setWfcSetting() : turnOnIms");
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800725 imsManager.turnOnIms();
Meng Wang9352c432016-06-08 14:22:20 -0700726 } else if (isTurnOffImsAllowedByPlatform(context)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800727 && (!isVolteEnabledByPlatform(context)
728 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
729 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
730 imsManager.turnOffIms();
731 }
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700732
Meng Wang663aa122016-11-14 21:04:19 -0800733 TelephonyManager tm = (TelephonyManager) context
734 .getSystemService(Context.TELEPHONY_SERVICE);
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700735 setWfcModeInternal(context, enabled
Meng Wang663aa122016-11-14 21:04:19 -0800736 // Choose wfc mode per current roaming preference
737 ? getWfcMode(context, tm.isNetworkRoaming())
738 // Force IMS to register over LTE when turning off WFC
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700739 : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED);
Etan Cohena00c9192014-12-23 15:02:29 -0800740 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700741 loge("setWfcSetting(): ", e);
Etan Cohena00c9192014-12-23 15:02:29 -0800742 }
743 }
744 }
745
746 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800747 * Change persistent WFC enabled setting for slot.
748 */
749 public void setWfcSettingForSlot(boolean enabled) {
750 int value = enabled ? 1 : 0;
751 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
752 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
753
Meng Wang51c09072017-03-27 10:47:45 -0700754 setWfcNonPersistentForSlot(enabled, getWfcModeForSlot());
755 }
756
757 /**
758 * Non-persistently change WFC enabled setting and WFC mode for slot
759 *
760 * @param wfcMode The WFC preference if WFC is enabled
761 */
762 public void setWfcNonPersistentForSlot(boolean enabled, int wfcMode) {
763 int imsFeatureValue =
764 enabled ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF;
765 // Force IMS to register over LTE when turning off WFC
766 int imsWfcModeFeatureValue =
767 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
768
Brad Ebinger16417b42017-03-07 13:48:50 -0800769 try {
770 ImsConfig config = getConfigInterface();
771 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
772 TelephonyManager.NETWORK_TYPE_IWLAN,
Meng Wang51c09072017-03-27 10:47:45 -0700773 imsFeatureValue,
Brad Ebinger16417b42017-03-07 13:48:50 -0800774 mImsConfigListener);
775
776 if (enabled) {
777 log("setWfcSettingForSlot() : turnOnIms");
778 turnOnIms();
779 } else if (isTurnOffImsAllowedByPlatformForSlot()
780 && (!isVolteEnabledByPlatformForSlot()
781 || !isEnhanced4gLteModeSettingEnabledByUserForSlot())) {
782 log("setWfcSettingForSlot() : imsServiceAllowTurnOff -> turnOffIms");
783 turnOffIms();
784 }
785
Meng Wang51c09072017-03-27 10:47:45 -0700786 setWfcModeInternalForSlot(imsWfcModeFeatureValue);
Brad Ebinger16417b42017-03-07 13:48:50 -0800787 } catch (ImsException e) {
788 loge("setWfcSettingForSlot(): ", e);
789 }
790 }
791
792 /**
793 * Returns the user configuration of WFC preference setting.
794 *
795 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcModeForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800796 */
797 public static int getWfcMode(Context context) {
798 int setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
fionaxu5803ef02016-03-08 11:48:48 -0800799 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context,
800 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
Etan Cohena00c9192014-12-23 15:02:29 -0800801 if (DBG) log("getWfcMode - setting=" + setting);
802 return setting;
803 }
804
805 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800806 * Returns the user configuration of WFC preference setting
807 */
808 public int getWfcModeForSlot() {
809 int setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
810 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfigForSlot(
811 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
812 if (DBG) log("getWfcMode - setting=" + setting);
813 return setting;
814 }
815
816 /**
817 * Change persistent WFC preference setting.
818 *
819 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcModeForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800820 */
821 public static void setWfcMode(Context context, int wfcMode) {
822 if (DBG) log("setWfcMode - setting=" + wfcMode);
823 android.provider.Settings.Global.putInt(context.getContentResolver(),
824 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
825
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700826 setWfcModeInternal(context, wfcMode);
827 }
828
Meng Wang37477012016-09-20 09:59:56 -0700829 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800830 * Change persistent WFC preference setting for slot.
831 */
832 public void setWfcModeForSlot(int wfcMode) {
833 if (DBG) log("setWfcModeForSlot - setting=" + wfcMode);
834 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
835 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
836
837 setWfcModeInternalForSlot(wfcMode);
838 }
839
840 /**
Meng Wang37477012016-09-20 09:59:56 -0700841 * Returns the user configuration of WFC preference setting
842 *
843 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800844 *
845 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcModeForSlot} instead.
Meng Wang37477012016-09-20 09:59:56 -0700846 */
847 public static int getWfcMode(Context context, boolean roaming) {
848 int setting = 0;
849 if (!roaming) {
850 setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
851 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context,
852 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
853 if (DBG) log("getWfcMode - setting=" + setting);
854 } else {
855 setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
856 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE,
857 getIntCarrierConfig(context,
858 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT));
859 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
860 }
861 return setting;
862 }
863
864 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800865 * Returns the user configuration of WFC preference setting for slot
866 *
867 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
868 */
869 public int getWfcModeForSlot(boolean roaming) {
870 int setting = 0;
871 if (!roaming) {
872 setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
873 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfigForSlot(
874 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
875 if (DBG) log("getWfcModeForSlot - setting=" + setting);
876 } else {
877 setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
878 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE,
879 getIntCarrierConfigForSlot(
880 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT));
881 if (DBG) log("getWfcModeForSlot (roaming) - setting=" + setting);
882 }
883 return setting;
884 }
885
886 /**
Meng Wang37477012016-09-20 09:59:56 -0700887 * Change persistent WFC preference setting
888 *
889 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800890 *
891 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcModeForSlot} instead.
Meng Wang37477012016-09-20 09:59:56 -0700892 */
893 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
894 if (!roaming) {
895 if (DBG) log("setWfcMode - setting=" + wfcMode);
896 android.provider.Settings.Global.putInt(context.getContentResolver(),
897 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
898 } else {
899 if (DBG) log("setWfcMode (roaming) - setting=" + wfcMode);
900 android.provider.Settings.Global.putInt(context.getContentResolver(),
901 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, wfcMode);
902 }
903
904 TelephonyManager tm = (TelephonyManager)
905 context.getSystemService(Context.TELEPHONY_SERVICE);
906 if (roaming == tm.isNetworkRoaming()) {
907 setWfcModeInternal(context, wfcMode);
908 }
909 }
910
Brad Ebinger16417b42017-03-07 13:48:50 -0800911 /**
912 * Change persistent WFC preference setting
913 *
914 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
915 */
916 public void setWfcModeForSlot(int wfcMode, boolean roaming) {
917 if (!roaming) {
918 if (DBG) log("setWfcModeForSlot - setting=" + wfcMode);
919 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
920 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
921 } else {
922 if (DBG) log("setWfcModeForSlot (roaming) - setting=" + wfcMode);
923 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
924 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, wfcMode);
925 }
926
927 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
928 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
929 if (subIds != null && subIds.length >= 1) {
930 subId = subIds[0];
931 }
932 TelephonyManager tm = (TelephonyManager)
933 mContext.getSystemService(Context.TELEPHONY_SERVICE);
934 if (roaming == tm.isNetworkRoaming(subId)) {
935 setWfcModeInternalForSlot(wfcMode);
936 }
937 }
938
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700939 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800940 final ImsManager imsManager = ImsManager.getInstance(context,
941 SubscriptionManager.getDefaultVoicePhoneId());
942 if (imsManager != null) {
943 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700944 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800945 public void run() {
946 try {
947 imsManager.getConfigInterface().setProvisionedValue(
948 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
949 value);
950 } catch (ImsException e) {
951 // do nothing
952 }
953 }
954 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700955 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800956 }
957 }
958
Brad Ebinger16417b42017-03-07 13:48:50 -0800959 private void setWfcModeInternalForSlot(int wfcMode) {
960 final int value = wfcMode;
961 Thread thread = new Thread(() -> {
962 try {
963 getConfigInterface().setProvisionedValue(
964 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
965 value);
966 } catch (ImsException e) {
967 // do nothing
968 }
969 });
970 thread.start();
971 }
972
Etan Cohena00c9192014-12-23 15:02:29 -0800973 /**
974 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800975 *
976 * @deprecated Does not support MSIM devices. Please use
977 * {@link #isWfcRoamingEnabledByUserForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800978 */
979 public static boolean isWfcRoamingEnabledByUser(Context context) {
980 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
981 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800982 getBooleanCarrierConfig(context,
983 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
984 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800985 return (enabled == 1) ? true : false;
986 }
987
988 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800989 * Returns the user configuration of WFC roaming setting for slot
990 */
991 public boolean isWfcRoamingEnabledByUserForSlot() {
992 int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
993 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
994 getBooleanCarrierConfigForSlot(
995 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
996 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
997 return (enabled == 1);
998 }
999
1000 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001001 * Change persistent WFC roaming enabled setting
1002 */
1003 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Etan Cohena00c9192014-12-23 15:02:29 -08001004 android.provider.Settings.Global.putInt(context.getContentResolver(),
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001005 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08001006 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001007 : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -08001008
1009 final ImsManager imsManager = ImsManager.getInstance(context,
1010 SubscriptionManager.getDefaultVoicePhoneId());
1011 if (imsManager != null) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001012 imsManager.setWfcRoamingSettingInternal(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -08001013 }
1014 }
1015
1016 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001017 * Change persistent WFC roaming enabled setting
1018 */
1019 public void setWfcRoamingSettingForSlot(boolean enabled) {
1020 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
1021 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
1022 enabled ? ImsConfig.FeatureValueConstants.ON
1023 : ImsConfig.FeatureValueConstants.OFF);
1024
1025 setWfcRoamingSettingInternal(enabled);
1026 }
1027
1028 private void setWfcRoamingSettingInternal(boolean enabled) {
1029 final int value = enabled
1030 ? ImsConfig.FeatureValueConstants.ON
1031 : ImsConfig.FeatureValueConstants.OFF;
1032 Thread thread = new Thread(() -> {
1033 try {
1034 getConfigInterface().setProvisionedValue(
1035 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING,
1036 value);
1037 } catch (ImsException e) {
1038 // do nothing
1039 }
1040 });
1041 thread.start();
1042 }
1043
1044 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001045 * Returns a platform configuration for WFC which may override the user
1046 * setting. Note: WFC presumes that VoLTE is enabled (these are
1047 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -08001048 *
1049 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatformForSlot}
1050 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001051 */
1052 public static boolean isWfcEnabledByPlatform(Context context) {
1053 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
1054 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
1055 return true;
1056 }
1057
1058 return
1059 context.getResources().getBoolean(
1060 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Junda Liue7663c02015-06-23 11:16:26 -07001061 getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001062 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
1063 isGbaValid(context);
1064 }
1065
1066 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001067 * Returns a platform configuration for WFC which may override the user
1068 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1069 * configuration settings which must be done correctly).
1070 */
1071 public boolean isWfcEnabledByPlatformForSlot() {
1072 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
1073 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
1074 return true;
1075 }
1076
1077 return mContext.getResources().getBoolean(
1078 com.android.internal.R.bool.config_device_wfc_ims_available) &&
1079 getBooleanCarrierConfigForSlot(
1080 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
1081 isGbaValidForSlot();
1082 }
1083
1084 /**
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001085 * If carrier requires that IMS is only available if GBA capable SIM is used,
1086 * then this function checks GBA bit in EF IST.
1087 *
1088 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
Brad Ebinger16417b42017-03-07 13:48:50 -08001089 *
1090 * @deprecated Use {@link #isGbaValidForSlot} instead
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001091 */
1092 private static boolean isGbaValid(Context context) {
1093 if (getBooleanCarrierConfig(context,
1094 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
1095 final TelephonyManager telephonyManager = TelephonyManager.getDefault();
1096 String efIst = telephonyManager.getIsimIst();
1097 if (efIst == null) {
1098 loge("ISF is NULL");
1099 return true;
1100 }
1101 boolean result = efIst != null && efIst.length() > 1 &&
1102 (0x02 & (byte)efIst.charAt(1)) != 0;
1103 if (DBG) log("GBA capable=" + result + ", ISF=" + efIst);
1104 return result;
1105 }
1106 return true;
Etan Cohena00c9192014-12-23 15:02:29 -08001107 }
1108
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001109 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001110 * If carrier requires that IMS is only available if GBA capable SIM is used,
1111 * then this function checks GBA bit in EF IST.
1112 *
1113 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1114 */
1115 private boolean isGbaValidForSlot() {
1116 if (getBooleanCarrierConfigForSlot(
1117 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
1118 final TelephonyManager telephonyManager = TelephonyManager.getDefault();
1119 String efIst = telephonyManager.getIsimIst();
1120 if (efIst == null) {
1121 loge("isGbaValidForSlot - ISF is NULL");
1122 return true;
1123 }
1124 boolean result = efIst != null && efIst.length() > 1 &&
1125 (0x02 & (byte)efIst.charAt(1)) != 0;
1126 if (DBG) log("isGbaValidForSlot - GBA capable=" + result + ", ISF=" + efIst);
1127 return result;
1128 }
1129 return true;
1130 }
1131
1132 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001133 * This function should be called when ImsConfig.ACTION_IMS_CONFIG_CHANGED is received.
1134 *
1135 * We cannot register receiver in ImsManager because this would lead to resource leak.
1136 * ImsManager can be created in different processes and it is not notified when that process
1137 * is about to be terminated.
1138 *
1139 * @hide
1140 * */
1141 public static void onProvisionedValueChanged(Context context, int item, String value) {
Amit Mahajan24f7b162016-07-21 16:33:53 -07001142 if (DBG) Rlog.d(TAG, "onProvisionedValueChanged: item=" + item + " val=" + value);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001143 ImsManager mgr = ImsManager.getInstance(context,
1144 SubscriptionManager.getDefaultVoicePhoneId());
1145
1146 switch (item) {
1147 case ImsConfig.ConfigConstants.VLT_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001148 mgr.setVolteProvisionedProperty(value.equals("1"));
1149 if (DBG) Rlog.d(TAG,"isVoLteProvisioned = " + mgr.isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001150 break;
1151
1152 case ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001153 mgr.setWfcProvisionedProperty(value.equals("1"));
1154 if (DBG) Rlog.d(TAG,"isWfcProvisioned = " + mgr.isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001155 break;
1156
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001157 case ImsConfig.ConfigConstants.LVC_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001158 mgr.setVtProvisionedProperty(value.equals("1"));
1159 if (DBG) Rlog.d(TAG,"isVtProvisioned = " + mgr.isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001160 break;
1161
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001162 }
1163 }
1164
1165 private class AsyncUpdateProvisionedValues extends AsyncTask<Void, Void, Void> {
1166 @Override
1167 protected Void doInBackground(Void... params) {
1168 // disable on any error
Amit Mahajan24f7b162016-07-21 16:33:53 -07001169 setVolteProvisionedProperty(false);
1170 setWfcProvisionedProperty(false);
1171 setVtProvisionedProperty(false);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001172
1173 try {
1174 ImsConfig config = getConfigInterface();
1175 if (config != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -07001176 setVolteProvisionedProperty(getProvisionedBool(config,
1177 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED));
1178 if (DBG) Rlog.d(TAG, "isVoLteProvisioned = " + isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001179
Amit Mahajan24f7b162016-07-21 16:33:53 -07001180 setWfcProvisionedProperty(getProvisionedBool(config,
1181 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED));
1182 if (DBG) Rlog.d(TAG, "isWfcProvisioned = " + isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001183
Amit Mahajan24f7b162016-07-21 16:33:53 -07001184 setVtProvisionedProperty(getProvisionedBool(config,
1185 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED));
1186 if (DBG) Rlog.d(TAG, "isVtProvisioned = " + isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001187
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001188 }
1189 } catch (ImsException ie) {
Meng Wangca7d4c42016-06-30 22:05:24 -07001190 Rlog.e(TAG, "AsyncUpdateProvisionedValues error: ", ie);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001191 }
1192
1193 return null;
1194 }
1195
1196 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
1197 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
1198 }
1199 }
1200
1201 /** Asynchronously get VoLTE, WFC, VT provisioning statuses */
1202 private void updateProvisionedValues() {
Brad Ebinger16417b42017-03-07 13:48:50 -08001203 if (getBooleanCarrierConfigForSlot(
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001204 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
1205
1206 new AsyncUpdateProvisionedValues().execute();
1207 }
1208 }
1209
1210 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001211 * Sync carrier config and user settings with ImsConfig.
1212 *
1213 * @param context for the manager object
1214 * @param phoneId phone id
1215 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001216 *
1217 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfigForSlot} instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001218 */
1219 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001220 if (!force) {
1221 if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) {
1222 log("updateImsServiceConfig: SIM not ready");
1223 // Don't disable IMS if SIM is not ready
1224 return;
1225 }
1226 }
1227
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001228 final ImsManager imsManager = ImsManager.getInstance(context, phoneId);
1229 if (imsManager != null && (!imsManager.mConfigUpdated || force)) {
1230 try {
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001231 imsManager.updateProvisionedValues();
1232
Pavel Zhamaitsiakd46779c2016-06-03 10:39:51 -07001233 // TODO: Extend ImsConfig API and set all feature values in single function call.
1234
1235 // Note: currently the order of updates is set to produce different order of
1236 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
1237 // differentiate this code path from vendor code perspective.
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001238 boolean isImsUsed = imsManager.updateVolteFeatureValue();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001239 isImsUsed |= imsManager.updateWfcFeatureAndProvisionedValues();
Pavel Zhamaitsiakd46779c2016-06-03 10:39:51 -07001240 isImsUsed |= imsManager.updateVideoCallFeatureValue();
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001241
Meng Wang9352c432016-06-08 14:22:20 -07001242 if (isImsUsed || !isTurnOffImsAllowedByPlatform(context)) {
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001243 // Turn on IMS if it is used.
1244 // Also, if turning off is not allowed for current carrier,
1245 // we need to turn IMS on because it might be turned off before
1246 // phone switched to current carrier.
Meng Wangca7d4c42016-06-30 22:05:24 -07001247 log("updateImsServiceConfig: turnOnIms");
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001248 imsManager.turnOnIms();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001249 } else {
1250 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Meng Wangca7d4c42016-06-30 22:05:24 -07001251 log("updateImsServiceConfig: turnOffIms");
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001252 imsManager.turnOffIms();
1253 }
1254
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001255 imsManager.mConfigUpdated = true;
1256 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -07001257 loge("updateImsServiceConfig: ", e);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001258 imsManager.mConfigUpdated = false;
1259 }
1260 }
1261 }
1262
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001263 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001264 * Sync carrier config and user settings with ImsConfig.
1265 *
1266 * @param context for the manager object
1267 * @param phoneId phone id
1268 * @param force update
1269 */
1270 public void updateImsServiceConfigForSlot(boolean force) {
1271 if (!force) {
1272 if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) {
1273 log("updateImsServiceConfigForSlot: SIM not ready");
1274 // Don't disable IMS if SIM is not ready
1275 return;
1276 }
1277 }
1278
1279 if (!mConfigUpdated || force) {
1280 try {
1281 updateProvisionedValues();
1282
1283 // TODO: Extend ImsConfig API and set all feature values in single function call.
1284
1285 // Note: currently the order of updates is set to produce different order of
1286 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
1287 // differentiate this code path from vendor code perspective.
1288 boolean isImsUsed = updateVolteFeatureValue();
1289 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1290 isImsUsed |= updateVideoCallFeatureValue();
1291
1292 if (isImsUsed || !isTurnOffImsAllowedByPlatformForSlot()) {
1293 // Turn on IMS if it is used.
1294 // Also, if turning off is not allowed for current carrier,
1295 // we need to turn IMS on because it might be turned off before
1296 // phone switched to current carrier.
1297 log("updateImsServiceConfigForSlot: turnOnIms");
1298 turnOnIms();
1299 } else {
1300 // Turn off IMS if it is not used AND turning off is allowed for carrier.
1301 log("updateImsServiceConfigForSlot: turnOffIms");
1302 turnOffIms();
1303 }
1304
1305 mConfigUpdated = true;
1306 } catch (ImsException e) {
1307 loge("updateImsServiceConfigForSlot: ", e);
1308 mConfigUpdated = false;
1309 }
1310 }
1311 }
1312
1313 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001314 * Update VoLTE config
1315 * @return whether feature is On
1316 * @throws ImsException
1317 */
1318 private boolean updateVolteFeatureValue() throws ImsException {
Brad Ebinger16417b42017-03-07 13:48:50 -08001319 boolean available = isVolteEnabledByPlatformForSlot();
1320 boolean enabled = isEnhanced4gLteModeSettingEnabledByUserForSlot();
1321 boolean isNonTty = isNonTtyOrTtyOnVolteEnabledForSlot();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001322 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001323
1324 log("updateVolteFeatureValue: available = " + available
1325 + ", enabled = " + enabled
1326 + ", nonTTY = " + isNonTty);
1327
1328 getConfigInterface().setFeatureValue(
1329 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
1330 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001331 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001332 ImsConfig.FeatureValueConstants.ON :
1333 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001334 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001335
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001336 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001337 }
1338
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001339 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001340 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001341 * @return whether feature is On
1342 * @throws ImsException
1343 */
1344 private boolean updateVideoCallFeatureValue() throws ImsException {
Brad Ebinger16417b42017-03-07 13:48:50 -08001345 boolean available = isVtEnabledByPlatformForSlot();
1346 boolean enabled = isVtEnabledByUserForSlot();
1347 boolean isNonTty = isNonTtyOrTtyOnVolteEnabledForSlot();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001348 boolean isDataEnabled = isDataEnabled();
Jack Yu57781852016-11-16 17:20:38 -08001349 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext,
1350 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001351
Jack Yu57781852016-11-16 17:20:38 -08001352 boolean isFeatureOn = available && enabled && isNonTty
1353 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001354
1355 log("updateVideoCallFeatureValue: available = " + available
1356 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001357 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001358 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001359
1360 getConfigInterface().setFeatureValue(
1361 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1362 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001363 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001364 ImsConfig.FeatureValueConstants.ON :
1365 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001366 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001367
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001368 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001369 }
1370
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001371 /**
1372 * Update WFC config
1373 * @return whether feature is On
1374 * @throws ImsException
1375 */
1376 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
Meng Wang531a8b62016-10-06 11:29:46 -07001377 boolean isNetworkRoaming = TelephonyManager.getDefault().isNetworkRoaming();
Brad Ebinger16417b42017-03-07 13:48:50 -08001378 boolean available = isWfcEnabledByPlatformForSlot();
1379 boolean enabled = isWfcEnabledByUserForSlot();
1380 int mode = getWfcModeForSlot(isNetworkRoaming);
1381 boolean roaming = isWfcRoamingEnabledByUserForSlot();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001382 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001383
1384 log("updateWfcFeatureAndProvisionedValues: available = " + available
1385 + ", enabled = " + enabled
1386 + ", mode = " + mode
1387 + ", roaming = " + roaming);
1388
1389 getConfigInterface().setFeatureValue(
Pavel Zhamaitsiake6f99432015-09-11 10:29:30 -07001390 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
1391 TelephonyManager.NETWORK_TYPE_IWLAN,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001392 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001393 ImsConfig.FeatureValueConstants.ON :
1394 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001395 mImsConfigListener);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001396
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001397 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001398 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1399 roaming = false;
1400 }
1401 setWfcModeInternal(mContext, mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001402 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001403
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001404 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001405 }
1406
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001407 /**
1408 * Do NOT use this directly, instead use {@link #getInstance}.
1409 */
1410 @VisibleForTesting
1411 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001412 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001413 mPhoneId = phoneId;
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001414 mConfigDynamicBind = mContext.getResources().getBoolean(
1415 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001416 mConfigManager = (CarrierConfigManager) context.getSystemService(
1417 Context.CARRIER_CONFIG_SERVICE);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001418 createImsService();
1419 }
1420
1421 /**
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001422 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1423 * devices.
1424 */
1425 public boolean isDynamicBinding() {
1426 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001427 }
1428
Etan Cohenf4311122015-02-26 17:47:13 -08001429 /*
1430 * Returns a flag indicating whether the IMS service is available.
1431 */
1432 public boolean isServiceAvailable() {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001433 if (mImsServiceProxy == null) {
1434 createImsService();
Etan Cohenf4311122015-02-26 17:47:13 -08001435 }
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001436 // mImsServiceProxy will always create an ImsServiceProxy.
1437 return mImsServiceProxy.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001438 }
1439
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001440 public void setImsConfigListener(ImsConfigListener listener) {
1441 mImsConfigListener = listener;
1442 }
1443
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001444
1445 /**
1446 * Adds a callback for status changed events if the binder is already available. If it is not,
1447 * this method will throw an ImsException.
1448 */
1449 public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.INotifyStatusChanged c)
1450 throws ImsException {
1451 if (!mImsServiceProxy.isBinderAlive()) {
1452 throw new ImsException("Binder is not active!",
1453 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1454 }
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001455 if (c != null) {
1456 mStatusCallbacks.add(c);
1457 }
1458 }
1459
Wink Savilleef36ef62014-06-11 08:39:38 -07001460 /**
1461 * Opens the IMS service for making calls and/or receiving generic IMS calls.
1462 * The caller may make subsquent calls through {@link #makeCall}.
1463 * The IMS service will register the device to the operator's network with the credentials
1464 * (from ISIM) periodically in order to receive calls from the operator's network.
1465 * When the IMS service receives a new call, it will send out an intent with
1466 * the provided action string.
1467 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
1468 *
1469 * @param serviceClass a service class specified in {@link ImsServiceClass}
1470 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1471 * @param incomingCallPendingIntent When an incoming call is received,
1472 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
1473 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
1474 * as the result code and the intent to fill in the call ID; It cannot be null
1475 * @param listener To listen to IMS registration events; It cannot be null
1476 * @return identifier (greater than 0) for the specified service
1477 * @throws NullPointerException if {@code incomingCallPendingIntent}
1478 * or {@code listener} is null
1479 * @throws ImsException if calling the IMS service results in an error
1480 * @see #getCallId
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001481 * @see #getImsSessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001482 */
1483 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
1484 ImsConnectionStateListener listener) throws ImsException {
1485 checkAndThrowExceptionIfServiceUnavailable();
1486
1487 if (incomingCallPendingIntent == null) {
1488 throw new NullPointerException("incomingCallPendingIntent can't be null");
1489 }
1490
1491 if (listener == null) {
1492 throw new NullPointerException("listener can't be null");
1493 }
1494
1495 int result = 0;
1496
1497 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001498 result = mImsServiceProxy.startSession(incomingCallPendingIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -07001499 createRegistrationListenerProxy(serviceClass, listener));
1500 } catch (RemoteException e) {
1501 throw new ImsException("open()", e,
1502 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1503 }
1504
1505 if (result <= 0) {
1506 // If the return value is a minus value,
1507 // it means that an error occurred in the service.
1508 // So, it needs to convert to the reason code specified in ImsReasonInfo.
1509 throw new ImsException("open()", (result * (-1)));
1510 }
1511
1512 return result;
1513 }
1514
1515 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001516 * Adds registration listener to the IMS service.
1517 *
1518 * @param serviceClass a service class specified in {@link ImsServiceClass}
1519 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1520 * @param listener To listen to IMS registration events; It cannot be null
1521 * @throws NullPointerException if {@code listener} is null
1522 * @throws ImsException if calling the IMS service results in an error
1523 */
1524 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1525 throws ImsException {
1526 checkAndThrowExceptionIfServiceUnavailable();
1527
1528 if (listener == null) {
1529 throw new NullPointerException("listener can't be null");
1530 }
1531
1532 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001533 ImsRegistrationListenerProxy p = createRegistrationListenerProxy(serviceClass,
1534 listener);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001535 mRegistrationListeners.add(p);
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001536 mImsServiceProxy.addRegistrationListener(p);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001537 } catch (RemoteException e) {
1538 throw new ImsException("addRegistrationListener()", e,
1539 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1540 }
1541 }
1542
1543 /**
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001544 * Removes the registration listener from the IMS service.
1545 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001546 * @param listener Previously registered listener that will be removed. Can not be null.
1547 * @throws NullPointerException if {@code listener} is null
1548 * @throws ImsException if calling the IMS service results in an error
1549 * instead.
1550 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001551 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001552 throws ImsException {
1553 checkAndThrowExceptionIfServiceUnavailable();
1554
1555 if (listener == null) {
1556 throw new NullPointerException("listener can't be null");
1557 }
1558
1559 try {
1560 Optional<ImsRegistrationListenerProxy> optionalProxy = mRegistrationListeners.stream()
1561 .filter(l -> listener.equals(l.mListener)).findFirst();
1562 if(optionalProxy.isPresent()) {
1563 ImsRegistrationListenerProxy p = optionalProxy.get();
1564 mRegistrationListeners.remove(p);
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001565 mImsServiceProxy.removeRegistrationListener(p);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001566 }
1567 } catch (RemoteException e) {
1568 throw new ImsException("removeRegistrationListener()", e,
1569 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1570 }
1571 }
1572
1573 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001574 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
1575 * All the resources that were allocated to the service are also released.
1576 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001577 * @param sessionId a session id to be closed which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001578 * @throws ImsException if calling the IMS service results in an error
1579 */
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001580 public void close(int sessionId) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001581 checkAndThrowExceptionIfServiceUnavailable();
1582
1583 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001584 mImsServiceProxy.endSession(sessionId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001585 } catch (RemoteException e) {
1586 throw new ImsException("close()", e,
1587 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1588 } finally {
1589 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001590 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001591 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001592 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001593 }
1594 }
1595
1596 /**
1597 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1598 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001599 * @return the Ut interface instance
1600 * @throws ImsException if getting the Ut interface results in an error
1601 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001602 public ImsUtInterface getSupplementaryServiceConfiguration()
Wink Savilleef36ef62014-06-11 08:39:38 -07001603 throws ImsException {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001604 // FIXME: manage the multiple Ut interfaces based on the session id
1605 if (mUt == null || !mImsServiceProxy.isBinderAlive()) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001606 checkAndThrowExceptionIfServiceUnavailable();
1607
1608 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001609 IImsUt iUt = mImsServiceProxy.getUtInterface();
Wink Savilleef36ef62014-06-11 08:39:38 -07001610
1611 if (iUt == null) {
1612 throw new ImsException("getSupplementaryServiceConfiguration()",
1613 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1614 }
1615
1616 mUt = new ImsUt(iUt);
1617 } catch (RemoteException e) {
1618 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1619 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1620 }
1621 }
1622
1623 return mUt;
1624 }
1625
1626 /**
1627 * Checks if the IMS service has successfully registered to the IMS network
1628 * with the specified service & call type.
1629 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001630 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1631 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1632 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1633 * @param callType a call type that is specified in {@link ImsCallProfile}
1634 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
1635 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1636 * {@link ImsCallProfile#CALL_TYPE_VT}
1637 * {@link ImsCallProfile#CALL_TYPE_VS}
1638 * @return true if the specified service id is connected to the IMS network;
1639 * false otherwise
1640 * @throws ImsException if calling the IMS service results in an error
1641 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001642 public boolean isConnected(int serviceType, int callType)
Wink Savilleef36ef62014-06-11 08:39:38 -07001643 throws ImsException {
1644 checkAndThrowExceptionIfServiceUnavailable();
1645
1646 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001647 return mImsServiceProxy.isConnected(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001648 } catch (RemoteException e) {
1649 throw new ImsException("isServiceConnected()", e,
1650 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1651 }
1652 }
1653
1654 /**
1655 * Checks if the specified IMS service is opend.
1656 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001657 * @return true if the specified service id is opened; false otherwise
1658 * @throws ImsException if calling the IMS service results in an error
1659 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001660 public boolean isOpened() throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001661 checkAndThrowExceptionIfServiceUnavailable();
1662
1663 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001664 return mImsServiceProxy.isOpened();
Wink Savilleef36ef62014-06-11 08:39:38 -07001665 } catch (RemoteException e) {
1666 throw new ImsException("isOpened()", e,
1667 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1668 }
1669 }
1670
1671 /**
1672 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1673 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001674 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001675 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1676 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1677 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1678 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1679 * @param callType a call type that is specified in {@link ImsCallProfile}
1680 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1681 * {@link ImsCallProfile#CALL_TYPE_VT}
1682 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1683 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1684 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1685 * {@link ImsCallProfile#CALL_TYPE_VS}
1686 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1687 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1688 * @return a {@link ImsCallProfile} object
1689 * @throws ImsException if calling the IMS service results in an error
1690 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001691 public ImsCallProfile createCallProfile(int sessionId, int serviceType, int callType)
1692 throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001693 checkAndThrowExceptionIfServiceUnavailable();
1694
1695 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001696 return mImsServiceProxy.createCallProfile(sessionId, serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001697 } catch (RemoteException e) {
1698 throw new ImsException("createCallProfile()", e,
1699 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1700 }
1701 }
1702
1703 /**
1704 * Creates a {@link ImsCall} to make a call.
1705 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001706 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001707 * @param profile a call profile to make the call
1708 * (it contains service type, call type, media information, etc.)
1709 * @param participants participants to invite the conference call
1710 * @param listener listen to the call events from {@link ImsCall}
1711 * @return a {@link ImsCall} object
1712 * @throws ImsException if calling the IMS service results in an error
1713 */
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001714 public ImsCall makeCall(int sessionId, ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001715 ImsCall.Listener listener) throws ImsException {
1716 if (DBG) {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001717 log("makeCall :: sessionId=" + sessionId
fionaxu7b3107c2016-07-06 14:04:06 -07001718 + ", profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001719 }
1720
1721 checkAndThrowExceptionIfServiceUnavailable();
1722
1723 ImsCall call = new ImsCall(mContext, profile);
1724
1725 call.setListener(listener);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001726 ImsCallSession session = createCallSession(sessionId, profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001727
1728 if ((callees != null) && (callees.length == 1)) {
1729 call.start(session, callees[0]);
1730 } else {
1731 call.start(session, callees);
1732 }
1733
1734 return call;
1735 }
1736
1737 /**
1738 * Creates a {@link ImsCall} to take an incoming call.
1739 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001740 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001741 * @param incomingCallIntent the incoming call broadcast intent
1742 * @param listener to listen to the call events from {@link ImsCall}
1743 * @return a {@link ImsCall} object
1744 * @throws ImsException if calling the IMS service results in an error
1745 */
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001746 public ImsCall takeCall(int sessionId, Intent incomingCallIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -07001747 ImsCall.Listener listener) throws ImsException {
1748 if (DBG) {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001749 log("takeCall :: sessionId=" + sessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001750 + ", incomingCall=" + incomingCallIntent);
1751 }
1752
1753 checkAndThrowExceptionIfServiceUnavailable();
1754
1755 if (incomingCallIntent == null) {
1756 throw new ImsException("Can't retrieve session with null intent",
1757 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1758 }
1759
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001760 int incomingServiceId = getImsSessionId(incomingCallIntent);
Wink Savilleef36ef62014-06-11 08:39:38 -07001761
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001762 if (sessionId != incomingServiceId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001763 throw new ImsException("Service id is mismatched in the incoming call intent",
1764 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1765 }
1766
1767 String callId = getCallId(incomingCallIntent);
1768
1769 if (callId == null) {
1770 throw new ImsException("Call ID missing in the incoming call intent",
1771 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1772 }
1773
1774 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001775 IImsCallSession session = mImsServiceProxy.getPendingCallSession(sessionId, callId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001776
1777 if (session == null) {
1778 throw new ImsException("No pending session for the call",
1779 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1780 }
1781
1782 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1783
1784 call.attachSession(new ImsCallSession(session));
1785 call.setListener(listener);
1786
1787 return call;
1788 } catch (Throwable t) {
1789 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1790 }
1791 }
1792
1793 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001794 * Gets the config interface to get/set service/capability parameters.
1795 *
1796 * @return the ImsConfig instance.
1797 * @throws ImsException if getting the setting interface results in an error.
1798 */
1799 public ImsConfig getConfigInterface() throws ImsException {
1800
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001801 if (mConfig == null || !mImsServiceProxy.isBinderAlive()) {
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001802 checkAndThrowExceptionIfServiceUnavailable();
1803
1804 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001805 IImsConfig config = mImsServiceProxy.getConfigInterface();
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001806 if (config == null) {
1807 throw new ImsException("getConfigInterface()",
1808 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1809 }
Libin.Tang@motorola.com54953c72014-08-07 15:02:08 -05001810 mConfig = new ImsConfig(config, mContext);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001811 } catch (RemoteException e) {
1812 throw new ImsException("getConfigInterface()", e,
1813 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1814 }
1815 }
1816 if (DBG) log("getConfigInterface(), mConfig= " + mConfig);
1817 return mConfig;
1818 }
1819
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001820 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301821 throws ImsException {
1822
Etan Cohen82f78122014-12-15 10:10:14 -08001823 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301824
Etan Cohen82f78122014-12-15 10:10:14 -08001825 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001826 mImsServiceProxy.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001827 } catch (RemoteException e) {
1828 throw new ImsException("setTTYMode()", e,
1829 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1830 }
1831
Brad Ebinger16417b42017-03-07 13:48:50 -08001832 if (!getBooleanCarrierConfigForSlot(
Junda Liue7663c02015-06-23 11:16:26 -07001833 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -08001834 setAdvanced4GMode((uiTtyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebinger16417b42017-03-07 13:48:50 -08001835 isEnhanced4gLteModeSettingEnabledByUserForSlot());
Etan Cohen82f78122014-12-15 10:10:14 -08001836 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301837 }
1838
Naveen Kalla525c3a22017-02-06 14:46:42 -08001839 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1840 Parcel p = Parcel.obtain();
1841 imsReasonInfo.writeToParcel(p, 0);
1842 p.setDataPosition(0);
1843 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1844 p.recycle();
1845 return clonedReasonInfo;
1846 }
1847
1848 /**
1849 * Get Recent IMS Disconnect Reasons.
1850 *
1851 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1852 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1853 * chronological order.
1854 */
1855 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1856 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1857
1858 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1859 disconnectReasons.add(makeACopy(reason));
1860 }
1861 return disconnectReasons;
1862 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001863
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001864 public int getImsServiceStatus() throws ImsException {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001865 return mImsServiceProxy.getFeatureStatus();
1866 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001867
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001868 /**
Junda Liue7663c02015-06-23 11:16:26 -07001869 * Get the boolean config from carrier config manager.
1870 *
1871 * @param context the context to get carrier service
1872 * @param key config key defined in CarrierConfigManager
1873 * @return boolean value of corresponding key.
Brad Ebinger16417b42017-03-07 13:48:50 -08001874 *
1875 * @deprecated Does not support MSIM devices. Use
1876 * {@link #getBooleanCarrierConfigForSlot(Context, String)} instead.
Junda Liue7663c02015-06-23 11:16:26 -07001877 */
1878 private static boolean getBooleanCarrierConfig(Context context, String key) {
1879 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
1880 Context.CARRIER_CONFIG_SERVICE);
Jonathan Basseri2acea6f2015-07-01 15:00:38 -07001881 PersistableBundle b = null;
Junda Liue7663c02015-06-23 11:16:26 -07001882 if (configManager != null) {
Jonathan Basseri2acea6f2015-07-01 15:00:38 -07001883 b = configManager.getConfig();
1884 }
1885 if (b != null) {
1886 return b.getBoolean(key);
Junda Liue7663c02015-06-23 11:16:26 -07001887 } else {
1888 // Return static default defined in CarrierConfigManager.
1889 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1890 }
1891 }
1892
1893 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001894 * Get the boolean config from carrier config manager.
1895 *
1896 * @param key config key defined in CarrierConfigManager
1897 * @return boolean value of corresponding key.
1898 */
1899 private boolean getBooleanCarrierConfigForSlot(String key) {
1900 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1901 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1902 if (subIds != null && subIds.length >= 1) {
1903 subId = subIds[0];
1904 }
1905 PersistableBundle b = null;
1906 if (mConfigManager != null) {
1907 // If an invalid subId is used, this bundle will contain default values.
1908 b = mConfigManager.getConfigForSubId(subId);
1909 }
1910 if (b != null) {
1911 return b.getBoolean(key);
1912 } else {
1913 // Return static default defined in CarrierConfigManager.
1914 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1915 }
1916 }
1917
1918 /**
fionaxu5803ef02016-03-08 11:48:48 -08001919 * Get the int config from carrier config manager.
1920 *
1921 * @param context the context to get carrier service
1922 * @param key config key defined in CarrierConfigManager
1923 * @return integer value of corresponding key.
Brad Ebinger16417b42017-03-07 13:48:50 -08001924 *
1925 * @deprecated Doesn't support MSIM devices. Use {@link #getIntCarrierConfigForSlot} instead.
fionaxu5803ef02016-03-08 11:48:48 -08001926 */
1927 private static int getIntCarrierConfig(Context context, String key) {
1928 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
1929 Context.CARRIER_CONFIG_SERVICE);
1930 PersistableBundle b = null;
1931 if (configManager != null) {
1932 b = configManager.getConfig();
1933 }
1934 if (b != null) {
1935 return b.getInt(key);
1936 } else {
1937 // Return static default defined in CarrierConfigManager.
1938 return CarrierConfigManager.getDefaultConfig().getInt(key);
1939 }
1940 }
1941
1942 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001943 * Get the int config from carrier config manager.
1944 *
1945 * @param key config key defined in CarrierConfigManager
1946 * @return integer value of corresponding key.
1947 */
1948 private int getIntCarrierConfigForSlot(String key) {
1949 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1950 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1951 if (subIds != null && subIds.length >= 1) {
1952 subId = subIds[0];
1953 }
1954 PersistableBundle b = null;
1955 if (mConfigManager != null) {
1956 // If an invalid subId is used, this bundle will contain default values.
1957 b = mConfigManager.getConfigForSubId(subId);
1958 }
1959 if (b != null) {
1960 return b.getInt(key);
1961 } else {
1962 // Return static default defined in CarrierConfigManager.
1963 return CarrierConfigManager.getDefaultConfig().getInt(key);
1964 }
1965 }
1966
1967 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001968 * Gets the call ID from the specified incoming call broadcast intent.
1969 *
1970 * @param incomingCallIntent the incoming call broadcast intent
1971 * @return the call ID or null if the intent does not contain it
1972 */
1973 private static String getCallId(Intent incomingCallIntent) {
1974 if (incomingCallIntent == null) {
1975 return null;
1976 }
1977
1978 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
1979 }
1980
1981 /**
1982 * Gets the service type from the specified incoming call broadcast intent.
1983 *
1984 * @param incomingCallIntent the incoming call broadcast intent
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001985 * @return the session identifier or -1 if the intent does not contain it
Wink Savilleef36ef62014-06-11 08:39:38 -07001986 */
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001987 private static int getImsSessionId(Intent incomingCallIntent) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001988 if (incomingCallIntent == null) {
1989 return (-1);
1990 }
1991
1992 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
1993 }
1994
1995 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001996 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
1997 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07001998 */
1999 private void checkAndThrowExceptionIfServiceUnavailable()
2000 throws ImsException {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002001 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
2002 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07002003
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002004 if (mImsServiceProxy == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002005 throw new ImsException("Service is unavailable",
2006 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2007 }
2008 }
2009 }
2010
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002011 /**
2012 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
2013 * ImsService:
2014 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
2015 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
2016 */
2017 private void createImsService() {
2018 if (!mConfigDynamicBind) {
2019 // Old method of binding
2020 Rlog.i(TAG, "Creating ImsService using ServiceManager");
2021 mImsServiceProxy = getServiceProxyCompat();
2022 } else {
2023 Rlog.i(TAG, "Creating ImsService using ImsResolver");
2024 mImsServiceProxy = getServiceProxy();
2025 }
Etan Cohend7727462014-07-12 14:54:10 -07002026 }
2027
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002028 // Deprecated method of binding with the ImsService defined in the ServiceManager.
2029 private ImsServiceProxyCompat getServiceProxyCompat() {
2030 IBinder binder = ServiceManager.checkService(IMS_SERVICE);
Wink Savilleef36ef62014-06-11 08:39:38 -07002031
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002032 if (binder != null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002033 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002034 binder.linkToDeath(mDeathRecipient, 0);
Wink Savilleef36ef62014-06-11 08:39:38 -07002035 } catch (RemoteException e) {
2036 }
2037 }
2038
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002039 return new ImsServiceProxyCompat(mPhoneId, binder);
2040 }
2041
2042 // New method of binding with the ImsResolver
2043 private ImsServiceProxy getServiceProxy() {
2044 TelephonyManager tm = (TelephonyManager)
2045 mContext.getSystemService(Context.TELEPHONY_SERVICE);
2046 ImsServiceProxy serviceProxy = new ImsServiceProxy(mPhoneId, ImsFeature.MMTEL);
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002047 serviceProxy.setStatusCallback(() -> mStatusCallbacks.forEach(
2048 ImsServiceProxy.INotifyStatusChanged::notifyStatusChanged));
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002049 // Returns null if the service is not available.
2050 IImsServiceController b = tm.getImsServiceControllerAndListen(mPhoneId,
2051 ImsFeature.MMTEL, serviceProxy.getListener());
2052 if (b != null) {
2053 serviceProxy.setBinder(b.asBinder());
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002054 // Trigger the cache to be updated for feature status.
2055 serviceProxy.getFeatureStatus();
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002056 } else {
2057 Rlog.w(TAG, "getServiceProxy: b is null! Phone Id: " + mPhoneId);
2058 }
2059 return serviceProxy;
Wink Savilleef36ef62014-06-11 08:39:38 -07002060 }
2061
2062 /**
2063 * Creates a {@link ImsCallSession} with the specified call profile.
2064 * Use other methods, if applicable, instead of interacting with
2065 * {@link ImsCallSession} directly.
2066 *
2067 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2068 * @param profile a call profile to make the call
2069 */
2070 private ImsCallSession createCallSession(int serviceId,
2071 ImsCallProfile profile) throws ImsException {
2072 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002073 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002074 return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile, null));
Wink Savilleef36ef62014-06-11 08:39:38 -07002075 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002076 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
2077 throw new ImsException("createCallSession()", e,
2078 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2079
Wink Savilleef36ef62014-06-11 08:39:38 -07002080 }
2081 }
2082
2083 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass,
2084 ImsConnectionStateListener listener) {
2085 ImsRegistrationListenerProxy proxy =
2086 new ImsRegistrationListenerProxy(serviceClass, listener);
2087 return proxy;
2088 }
2089
Etan Cohena00c9192014-12-23 15:02:29 -08002090 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002091 Rlog.d(TAG, s);
2092 }
2093
Etan Cohena00c9192014-12-23 15:02:29 -08002094 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002095 Rlog.e(TAG, s);
2096 }
2097
Etan Cohena00c9192014-12-23 15:02:29 -08002098 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002099 Rlog.e(TAG, s, t);
2100 }
2101
2102 /**
ram7da5a112014-07-16 20:59:27 +05302103 * Used for turning on IMS.if its off already
2104 */
Etan Cohen82f78122014-12-15 10:10:14 -08002105 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002106 checkAndThrowExceptionIfServiceUnavailable();
2107
ram7da5a112014-07-16 20:59:27 +05302108 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002109 mImsServiceProxy.turnOnIms();
ram7da5a112014-07-16 20:59:27 +05302110 } catch (RemoteException e) {
2111 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2112 }
2113 }
2114
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002115 private boolean isImsTurnOffAllowed() {
Brad Ebinger16417b42017-03-07 13:48:50 -08002116 return isTurnOffImsAllowedByPlatformForSlot()
2117 && (!isWfcEnabledByPlatformForSlot()
2118 || !isWfcEnabledByUserForSlot());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002119 }
2120
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002121 private void setLteFeatureValues(boolean turnOn) {
2122 log("setLteFeatureValues: " + turnOn);
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002123 try {
2124 ImsConfig config = getConfigInterface();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002125 if (config != null) {
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002126 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08002127 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002128
Brad Ebinger16417b42017-03-07 13:48:50 -08002129 if (isVolteEnabledByPlatformForSlot()) {
Jack Yu57781852016-11-16 17:20:38 -08002130 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext,
2131 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Brad Ebinger16417b42017-03-07 13:48:50 -08002132 boolean enableViLte = turnOn && isVtEnabledByUserForSlot() &&
Jack Yu57781852016-11-16 17:20:38 -08002133 (ignoreDataEnabledChanged || isDataEnabled());
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002134 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
2135 TelephonyManager.NETWORK_TYPE_LTE,
2136 enableViLte ? 1 : 0,
2137 mImsConfigListener);
2138 }
Etan Cohenb651fa52014-10-22 10:51:29 -07002139 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002140 } catch (ImsException e) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002141 loge("setLteFeatureValues: exception ", e);
Etan Cohencfc784d2014-08-07 18:40:31 -07002142 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002143 }
2144
2145 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
2146 checkAndThrowExceptionIfServiceUnavailable();
2147
2148 // if turnOn: first set feature values then call turnOnIms()
2149 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
2150 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07002151 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002152 setLteFeatureValues(turnOn);
2153 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07002154 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002155 } else {
2156 if (isImsTurnOffAllowed()) {
2157 log("setAdvanced4GMode: turnOffIms");
2158 turnOffIms();
2159 }
2160 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07002161 }
2162 }
2163
ram7da5a112014-07-16 20:59:27 +05302164 /**
2165 * Used for turning off IMS completely in order to make the device CSFB'ed.
2166 * Once turned off, all calls will be over CS.
2167 */
Etan Cohen82f78122014-12-15 10:10:14 -08002168 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002169 checkAndThrowExceptionIfServiceUnavailable();
2170
ram7da5a112014-07-16 20:59:27 +05302171 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002172 mImsServiceProxy.turnOffIms();
ram7da5a112014-07-16 20:59:27 +05302173 } catch (RemoteException e) {
2174 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2175 }
2176 }
2177
Naveen Kalla525c3a22017-02-06 14:46:42 -08002178 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
2179 if (reason == null) return;
2180 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
2181 mRecentDisconnectReasons.removeFirst();
2182 }
2183 mRecentDisconnectReasons.addLast(reason);
2184 }
2185
ram7da5a112014-07-16 20:59:27 +05302186 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002187 * Death recipient class for monitoring IMS service.
2188 */
2189 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
2190 @Override
2191 public void binderDied() {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002192 mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002193 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05002194 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002195 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002196 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002197 }
2198 }
2199
2200 /**
2201 * Adapter class for {@link IImsRegistrationListener}.
2202 */
Naveen Kalla0484b732017-02-14 14:55:24 -08002203 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
Wink Savilleef36ef62014-06-11 08:39:38 -07002204 private int mServiceClass;
2205 private ImsConnectionStateListener mListener;
2206
2207 public ImsRegistrationListenerProxy(int serviceClass,
2208 ImsConnectionStateListener listener) {
2209 mServiceClass = serviceClass;
2210 mListener = listener;
2211 }
2212
2213 public boolean isSameProxy(int serviceClass) {
2214 return (mServiceClass == serviceClass);
2215 }
2216
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002217 @Deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -07002218 public void registrationConnected() {
2219 if (DBG) {
2220 log("registrationConnected ::");
2221 }
2222
2223 if (mListener != null) {
2224 mListener.onImsConnected();
2225 }
2226 }
2227
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002228 @Deprecated
Rekha Kumar14631742015-02-04 10:47:00 -08002229 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07002230 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08002231 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07002232 }
2233
2234 if (mListener != null) {
Rekha Kumar14631742015-02-04 10:47:00 -08002235 mListener.onImsProgressing();
2236 }
2237 }
2238
2239 @Override
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002240 public void registrationConnectedWithRadioTech(int imsRadioTech) {
2241 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2242 // values in ServiceState.java.
2243 if (DBG) {
2244 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
2245 }
2246
2247 if (mListener != null) {
2248 mListener.onImsConnected();
Meng Wange4414152016-12-07 16:27:15 -08002249 mListener.onImsConnected(imsRadioTech);
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002250 }
2251 }
2252
2253 @Override
2254 public void registrationProgressingWithRadioTech(int imsRadioTech) {
2255 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2256 // values in ServiceState.java.
2257 if (DBG) {
2258 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
2259 }
2260
2261 if (mListener != null) {
2262 mListener.onImsProgressing();
2263 }
2264 }
2265
2266 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08002267 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
2268 if (DBG) {
2269 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
2270 }
2271
Naveen Kalla525c3a22017-02-06 14:46:42 -08002272 addToRecentDisconnectReasons(imsReasonInfo);
2273
Rekha Kumar14631742015-02-04 10:47:00 -08002274 if (mListener != null) {
2275 mListener.onImsDisconnected(imsReasonInfo);
Wink Savilleef36ef62014-06-11 08:39:38 -07002276 }
2277 }
2278
2279 @Override
2280 public void registrationResumed() {
2281 if (DBG) {
2282 log("registrationResumed ::");
2283 }
2284
2285 if (mListener != null) {
2286 mListener.onImsResumed();
2287 }
2288 }
2289
2290 @Override
2291 public void registrationSuspended() {
2292 if (DBG) {
2293 log("registrationSuspended ::");
2294 }
2295
2296 if (mListener != null) {
2297 mListener.onImsSuspended();
2298 }
2299 }
2300
2301 @Override
2302 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
2303 log("registrationServiceCapabilityChanged :: serviceClass=" +
2304 serviceClass + ", event=" + event);
2305
2306 if (mListener != null) {
2307 mListener.onImsConnected();
2308 }
2309 }
ram7da5a112014-07-16 20:59:27 +05302310
2311 @Override
2312 public void registrationFeatureCapabilityChanged(int serviceClass,
2313 int[] enabledFeatures, int[] disabledFeatures) {
2314 log("registrationFeatureCapabilityChanged :: serviceClass=" +
2315 serviceClass);
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05002316 if (mListener != null) {
2317 mListener.onFeatureCapabilityChanged(serviceClass,
2318 enabledFeatures, disabledFeatures);
2319 }
ram7da5a112014-07-16 20:59:27 +05302320 }
2321
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002322 @Override
2323 public void voiceMessageCountUpdate(int count) {
2324 log("voiceMessageCountUpdate :: count=" + count);
2325
2326 if (mListener != null) {
2327 mListener.onVoiceMessageCountChanged(count);
2328 }
2329 }
2330
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002331 @Override
2332 public void registrationAssociatedUriChanged(Uri[] uris) {
2333 if (DBG) log("registrationAssociatedUriChanged ::");
2334
2335 if (mListener != null) {
2336 mListener.registrationAssociatedUriChanged(uris);
2337 }
2338 }
Meng Wange4414152016-12-07 16:27:15 -08002339
2340 @Override
2341 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo) {
2342 if (DBG) log("registrationChangeFailed :: targetAccessTech=" + targetAccessTech +
2343 ", imsReasonInfo=" + imsReasonInfo);
2344
2345 if (mListener != null) {
2346 mListener.onRegistrationChangeFailed(targetAccessTech, imsReasonInfo);
2347 }
2348 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002349 }
Tyler Gunn4d128b62016-04-13 15:44:38 -07002350
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002351 /**
2352 * Gets the ECBM interface to request ECBM exit.
2353 *
2354 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2355 * @return the ECBM interface instance
2356 * @throws ImsException if getting the ECBM interface results in an error
2357 */
2358 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002359 if (mEcbm == null || !mImsServiceProxy.isBinderAlive()) {
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002360 checkAndThrowExceptionIfServiceUnavailable();
2361
2362 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002363 IImsEcbm iEcbm = mImsServiceProxy.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002364
2365 if (iEcbm == null) {
2366 throw new ImsException("getEcbmInterface()",
2367 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
2368 }
2369 mEcbm = new ImsEcbm(iEcbm);
2370 } catch (RemoteException e) {
2371 throw new ImsException("getEcbmInterface()", e,
2372 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2373 }
2374 }
2375 return mEcbm;
2376 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002377
2378 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002379 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2380 *
2381 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2382 * @return the multi-endpoint interface instance
2383 * @throws ImsException if getting the multi-endpoint interface results in an error
2384 */
2385 public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002386 if (mMultiEndpoint == null || !mImsServiceProxy.isBinderAlive()) {
Tyler Gunn4d128b62016-04-13 15:44:38 -07002387 checkAndThrowExceptionIfServiceUnavailable();
2388
2389 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002390 IImsMultiEndpoint iImsMultiEndpoint = mImsServiceProxy.getMultiEndpointInterface();
Tyler Gunn4d128b62016-04-13 15:44:38 -07002391
2392 if (iImsMultiEndpoint == null) {
2393 throw new ImsException("getMultiEndpointInterface()",
2394 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2395 }
2396 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2397 } catch (RemoteException e) {
2398 throw new ImsException("getMultiEndpointInterface()", e,
2399 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2400 }
2401 }
2402 return mMultiEndpoint;
2403 }
2404
2405 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002406 * Resets ImsManager settings back to factory defaults.
2407 *
Brad Ebinger16417b42017-03-07 13:48:50 -08002408 * @deprecated Doesn't support MSIM devices. Use {@link #factoryResetSlot()} instead.
2409 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002410 * @hide
2411 */
2412 public static void factoryReset(Context context) {
2413 // Set VoLTE to default
2414 android.provider.Settings.Global.putInt(context.getContentResolver(),
2415 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
2416 ImsConfig.FeatureValueConstants.ON);
2417
2418 // Set VoWiFi to default
2419 android.provider.Settings.Global.putInt(context.getContentResolver(),
2420 android.provider.Settings.Global.WFC_IMS_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08002421 getBooleanCarrierConfig(context,
2422 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
2423 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002424
2425 // Set VoWiFi mode to default
2426 android.provider.Settings.Global.putInt(context.getContentResolver(),
2427 android.provider.Settings.Global.WFC_IMS_MODE,
fionaxu5803ef02016-03-08 11:48:48 -08002428 getIntCarrierConfig(context,
2429 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002430
2431 // Set VoWiFi roaming to default
2432 android.provider.Settings.Global.putInt(context.getContentResolver(),
2433 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08002434 getBooleanCarrierConfig(context,
2435 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
2436 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002437
2438 // Set VT to default
Pavel Zhamaitsiak92b54b22016-04-01 15:55:47 -07002439 android.provider.Settings.Global.putInt(context.getContentResolver(),
2440 android.provider.Settings.Global.VT_IMS_ENABLED,
2441 ImsConfig.FeatureValueConstants.ON);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002442
2443 // Push settings to ImsConfig
2444 ImsManager.updateImsServiceConfig(context,
2445 SubscriptionManager.getDefaultVoicePhoneId(), true);
2446 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002447
Brad Ebinger16417b42017-03-07 13:48:50 -08002448 /**
2449 * Resets ImsManager settings back to factory defaults.
2450 *
2451 * @hide
2452 */
2453 public void factoryResetSlot() {
2454 // Set VoLTE to default
2455 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2456 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
2457 ImsConfig.FeatureValueConstants.ON);
2458
2459 // Set VoWiFi to default
2460 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2461 android.provider.Settings.Global.WFC_IMS_ENABLED,
2462 getBooleanCarrierConfigForSlot(
2463 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
2464 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
2465
2466 // Set VoWiFi mode to default
2467 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2468 android.provider.Settings.Global.WFC_IMS_MODE,
2469 getIntCarrierConfigForSlot(
2470 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
2471
2472 // Set VoWiFi roaming to default
2473 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2474 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
2475 getBooleanCarrierConfigForSlot(
2476 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
2477 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
2478
2479 // Set VT to default
2480 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2481 android.provider.Settings.Global.VT_IMS_ENABLED,
2482 ImsConfig.FeatureValueConstants.ON);
2483
2484 // Push settings to ImsConfig
2485 updateImsServiceConfigForSlot(true);
2486 }
2487
Amit Mahajan24f7b162016-07-21 16:33:53 -07002488 private boolean isDataEnabled() {
2489 return SystemProperties.getBoolean(DATA_ENABLED_PROP, true);
2490 }
2491
Jack Yu643ffe42016-07-08 14:25:46 -07002492 /**
2493 * Set data enabled/disabled flag.
2494 * @param enabled True if data is enabled, otherwise disabled.
2495 */
2496 public void setDataEnabled(boolean enabled) {
2497 log("setDataEnabled: " + enabled);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002498 SystemProperties.set(DATA_ENABLED_PROP, enabled ? TRUE : FALSE);
2499 }
2500
2501 private boolean isVolteProvisioned() {
2502 return SystemProperties.getBoolean(VOLTE_PROVISIONED_PROP, true);
2503 }
2504
2505 private void setVolteProvisionedProperty(boolean provisioned) {
2506 SystemProperties.set(VOLTE_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
2507 }
2508
2509 private boolean isWfcProvisioned() {
2510 return SystemProperties.getBoolean(WFC_PROVISIONED_PROP, true);
2511 }
2512
2513 private void setWfcProvisionedProperty(boolean provisioned) {
2514 SystemProperties.set(WFC_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
2515 }
2516
2517 private boolean isVtProvisioned() {
2518 return SystemProperties.getBoolean(VT_PROVISIONED_PROP, true);
2519 }
2520
2521 private void setVtProvisionedProperty(boolean provisioned) {
2522 SystemProperties.set(VT_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
Jack Yu643ffe42016-07-08 14:25:46 -07002523 }
2524
Jack Yu2f102bd2015-12-28 15:31:48 -08002525 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2526 pw.println("ImsManager:");
2527 pw.println(" mPhoneId = " + mPhoneId);
2528 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002529 pw.println(" mImsServiceProxy = " + mImsServiceProxy);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002530 pw.println(" mDataEnabled = " + isDataEnabled());
Jack Yu57781852016-11-16 17:20:38 -08002531 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(mContext,
2532 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002533
Brad Ebinger16417b42017-03-07 13:48:50 -08002534 pw.println(" isGbaValid = " + isGbaValidForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002535 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebinger16417b42017-03-07 13:48:50 -08002536 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabledForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002537
Brad Ebinger16417b42017-03-07 13:48:50 -08002538 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatformForSlot());
2539 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDeviceForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002540 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebinger16417b42017-03-07 13:48:50 -08002541 isEnhanced4gLteModeSettingEnabledByUserForSlot());
2542 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatformForSlot());
2543 pw.println(" isVtEnabledByUser = " + isVtEnabledByUserForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002544
Brad Ebinger16417b42017-03-07 13:48:50 -08002545 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatformForSlot());
2546 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUserForSlot());
2547 pw.println(" getWfcMode = " + getWfcModeForSlot());
2548 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUserForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002549
Brad Ebinger16417b42017-03-07 13:48:50 -08002550 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDeviceForSlot());
2551 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDeviceForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002552 pw.flush();
2553 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002554}