blob: 7c258291961db1a0a1e597813d2794de0b48c78b [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)) {
Brad Ebingerff097922017-06-19 15:43:08 -0700230 ImsManager m = sImsManagerInstances.get(phoneId);
231 // May be null for some tests
232 if (m != null) {
233 m.connectIfServiceIsAvailable();
234 }
235 return m;
Naveen Kalla525c3a22017-02-06 14:46:42 -0800236 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700237
Etan Cohenabbd7882014-09-26 22:35:35 -0700238 ImsManager mgr = new ImsManager(context, phoneId);
239 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700240
241 return mgr;
242 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700243 }
244
Etan Cohen45b5f312014-08-19 15:55:08 -0700245 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800246 * Returns the user configuration of Enhanced 4G LTE Mode setting.
247 *
248 * @deprecated Doesn't support MSIM devices. Use
249 * {@link #isEnhanced4gLteModeSettingEnabledByUserForSlot} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700250 */
251 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Sungmin Choi2f1af952016-02-01 17:15:35 +0900252 // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true.
253 // If user changes SIM from editable mode to uneditable mode, need to return true.
254 if (!getBooleanCarrierConfig(context,
255 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
256 return true;
257 }
Libin.Tang@motorola.com8a6bf4b2014-10-10 15:02:41 -0500258 int enabled = android.provider.Settings.Global.getInt(
Brad Ebinger16417b42017-03-07 13:48:50 -0800259 context.getContentResolver(),
260 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
261 ImsConfig.FeatureValueConstants.ON);
Etan Cohena00c9192014-12-23 15:02:29 -0800262 return (enabled == 1) ? true : false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700263 }
264
265 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800266 * Returns the user configuration of Enhanced 4G LTE Mode setting for slot.
267 */
268 public boolean isEnhanced4gLteModeSettingEnabledByUserForSlot() {
269 // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true.
270 // If user changes SIM from editable mode to uneditable mode, need to return true.
271 if (!getBooleanCarrierConfigForSlot(
272 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
273 return true;
274 }
275 int enabled = android.provider.Settings.Global.getInt(
276 mContext.getContentResolver(),
277 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
278 ImsConfig.FeatureValueConstants.ON);
279 return (enabled == 1);
280 }
281
282 /**
283 * Change persistent Enhanced 4G LTE Mode setting.
284 *
285 * @deprecated Doesn't support MSIM devices. Use {@link #setEnhanced4gLteModeSettingForSlot}
286 * instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800287 */
288 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
289 int value = enabled ? 1 : 0;
290 android.provider.Settings.Global.putInt(
291 context.getContentResolver(),
292 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
293
294 if (isNonTtyOrTtyOnVolteEnabled(context)) {
295 ImsManager imsManager = ImsManager.getInstance(context,
296 SubscriptionManager.getDefaultVoicePhoneId());
297 if (imsManager != null) {
298 try {
299 imsManager.setAdvanced4GMode(enabled);
300 } catch (ImsException ie) {
301 // do nothing
302 }
303 }
304 }
305 }
306
307 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800308 * Change persistent Enhanced 4G LTE Mode setting. If the the option is not editable
309 * ({@link CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL} is false), this method will
310 * always set the setting to true.
311 *
312 */
313 public void setEnhanced4gLteModeSettingForSlot(boolean enabled) {
314 // If false, we must always keep advanced 4G mode set to true (1).
315 int value = getBooleanCarrierConfigForSlot(
316 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL) ? (enabled ? 1: 0) : 1;
317
318 try {
319 int prevSetting = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
320 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED);
321 if (prevSetting == value) {
322 // Don't trigger setAdvanced4GMode if the setting hasn't changed.
323 return;
324 }
325 } catch (Settings.SettingNotFoundException e) {
326 // Setting doesn't exist yet, so set it below.
327 }
328
329 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
330 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
331 if (isNonTtyOrTtyOnVolteEnabledForSlot()) {
332 try {
333 setAdvanced4GMode(enabled);
334 } catch (ImsException ie) {
335 // do nothing
336 }
337 }
338 }
339
340 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800341 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
342 * supported.
Brad Ebinger16417b42017-03-07 13:48:50 -0800343 * @deprecated Does not support MSIM devices. Please use
344 * {@link #isNonTtyOrTtyOnVolteEnabledForSlot} instead.
Etan Cohen82f78122014-12-15 10:10:14 -0800345 */
346 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700347 if (getBooleanCarrierConfig(context,
fionaxu5803ef02016-03-08 11:48:48 -0800348 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800349 return true;
350 }
351
352 return Settings.Secure.getInt(context.getContentResolver(),
353 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
354 == TelecomManager.TTY_MODE_OFF;
355 }
356
357 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800358 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
359 * supported on a per slot basis.
360 */
361 public boolean isNonTtyOrTtyOnVolteEnabledForSlot() {
362 if (getBooleanCarrierConfigForSlot(
363 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
364 return true;
365 }
366
367 return Settings.Secure.getInt(mContext.getContentResolver(),
368 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
369 == TelecomManager.TTY_MODE_OFF;
370 }
371
372 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700373 * Returns a platform configuration for VoLTE which may override the user setting.
Brad Ebinger16417b42017-03-07 13:48:50 -0800374 * @deprecated Does not support MSIM devices. Please use
375 * {@link #isVolteEnabledByPlatformForSlot()} instead.
Etan Cohen45b5f312014-08-19 15:55:08 -0700376 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700377 public static boolean isVolteEnabledByPlatform(Context context) {
Etan Cohenb651fa52014-10-22 10:51:29 -0700378 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
379 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
Etan Cohenaf55a402014-09-04 22:34:41 -0700380 return true;
381 }
382
Etan Cohenb5388a32014-11-26 11:57:47 -0800383 return context.getResources().getBoolean(
Junda Liue7663c02015-06-23 11:16:26 -0700384 com.android.internal.R.bool.config_device_volte_available)
385 && getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700386 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
387 && isGbaValid(context);
Etan Cohenb5388a32014-11-26 11:57:47 -0800388 }
389
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700390 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800391 * Returns a platform configuration for VoLTE which may override the user setting on a per Slot
392 * basis.
393 */
394 public boolean isVolteEnabledByPlatformForSlot() {
395 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
396 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
397 return true;
398 }
399
400 return mContext.getResources().getBoolean(
401 com.android.internal.R.bool.config_device_volte_available)
402 && getBooleanCarrierConfigForSlot(
403 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
404 && isGbaValidForSlot();
405 }
406
407 /**
408 * Indicates whether VoLTE is provisioned on device.
409 *
410 * @deprecated Does not support MSIM devices. Please use
411 * {@link #isVolteProvisionedOnDeviceForSlot()} instead.
Etan Cohenb5388a32014-11-26 11:57:47 -0800412 */
413 public static boolean isVolteProvisionedOnDevice(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700414 if (getBooleanCarrierConfig(context,
415 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Etan Cohenb5388a32014-11-26 11:57:47 -0800416 ImsManager mgr = ImsManager.getInstance(context,
Jonathan Basserid7133652015-04-07 19:54:24 -0700417 SubscriptionManager.getDefaultVoicePhoneId());
Etan Cohenb5388a32014-11-26 11:57:47 -0800418 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700419 return mgr.isVolteProvisioned();
Etan Cohenb5388a32014-11-26 11:57:47 -0800420 }
421 }
422
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700423 return true;
424 }
425
426 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800427 * Indicates whether VoLTE is provisioned on this slot.
428 */
429 public boolean isVolteProvisionedOnDeviceForSlot() {
430 if (getBooleanCarrierConfigForSlot(
431 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
432 return isVolteProvisioned();
433 }
434
435 return true;
436 }
437
438 /**
Meng Wang54fd41a2017-04-12 11:44:47 -0700439 * Indicates whether VoWifi is provisioned on device.
440 *
441 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
442 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800443 *
444 * @deprecated Does not support MSIM devices. Please use
445 * {@link #isWfcProvisionedOnDeviceForSlot()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700446 */
447 public static boolean isWfcProvisionedOnDevice(Context context) {
448 if (getBooleanCarrierConfig(context,
Meng Wang54fd41a2017-04-12 11:44:47 -0700449 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
450 if (!isVolteProvisionedOnDevice(context)) {
451 return false;
452 }
453 }
454
455 if (getBooleanCarrierConfig(context,
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700456 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
457 ImsManager mgr = ImsManager.getInstance(context,
458 SubscriptionManager.getDefaultVoicePhoneId());
459 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700460 return mgr.isWfcProvisioned();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700461 }
462 }
463
464 return true;
465 }
466
467 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800468 * Indicates whether VoWifi is provisioned on slot.
Meng Wang54fd41a2017-04-12 11:44:47 -0700469 *
470 * When CarrierConfig KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL is true, and VoLTE is not
471 * provisioned on device, this method returns false.
Brad Ebinger16417b42017-03-07 13:48:50 -0800472 */
473 public boolean isWfcProvisionedOnDeviceForSlot() {
474 if (getBooleanCarrierConfigForSlot(
Meng Wang54fd41a2017-04-12 11:44:47 -0700475 CarrierConfigManager.KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL)) {
476 if (!isVolteProvisionedOnDeviceForSlot()) {
477 return false;
478 }
479 }
480
481 if (getBooleanCarrierConfigForSlot(
Brad Ebinger16417b42017-03-07 13:48:50 -0800482 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Meng Wang54fd41a2017-04-12 11:44:47 -0700483 return isWfcProvisioned();
Brad Ebinger16417b42017-03-07 13:48:50 -0800484 }
485
486 return true;
487 }
488
489 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700490 * Indicates whether VT is provisioned on device
Brad Ebinger16417b42017-03-07 13:48:50 -0800491 *
492 * @deprecated Does not support MSIM devices. Please use
493 * {@link #isVtProvisionedOnDeviceForSlot()} instead.
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700494 */
495 public static boolean isVtProvisionedOnDevice(Context context) {
496 if (getBooleanCarrierConfig(context,
497 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
498 ImsManager mgr = ImsManager.getInstance(context,
499 SubscriptionManager.getDefaultVoicePhoneId());
500 if (mgr != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -0700501 return mgr.isVtProvisioned();
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -0700502 }
503 }
504
505 return true;
Etan Cohenb651fa52014-10-22 10:51:29 -0700506 }
507
Etan Cohenea2b5832014-10-23 18:50:35 -0700508 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800509 * Indicates whether VT is provisioned on slot.
510 */
511 public boolean isVtProvisionedOnDeviceForSlot() {
512 if (getBooleanCarrierConfigForSlot(
513 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
514 return isVtProvisioned();
515 }
516
517 return true;
518 }
519
520 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700521 * Returns a platform configuration for VT which may override the user setting.
522 *
523 * Note: VT presumes that VoLTE is enabled (these are configuration settings
524 * which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -0800525 *
526 * @deprecated Does not support MSIM devices. Please use
527 * {@link #isVtEnabledByPlatformForSlot()} instead.
Etan Cohenea2b5832014-10-23 18:50:35 -0700528 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700529 public static boolean isVtEnabledByPlatform(Context context) {
Etan Cohenea2b5832014-10-23 18:50:35 -0700530 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
531 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
532 return true;
533 }
534
Etan Cohenb651fa52014-10-22 10:51:29 -0700535 return
536 context.getResources().getBoolean(
537 com.android.internal.R.bool.config_device_vt_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700538 getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700539 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
540 isGbaValid(context);
Etan Cohen45b5f312014-08-19 15:55:08 -0700541 }
542
Etan Cohena00c9192014-12-23 15:02:29 -0800543 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800544 * Returns a platform configuration for VT which may override the user setting.
545 *
546 * Note: VT presumes that VoLTE is enabled (these are configuration settings
547 * which must be done correctly).
548 */
549 public boolean isVtEnabledByPlatformForSlot() {
550 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
551 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
552 return true;
553 }
554
555 return mContext.getResources().getBoolean(
556 com.android.internal.R.bool.config_device_vt_available) &&
557 getBooleanCarrierConfigForSlot(
558 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
559 isGbaValidForSlot();
560 }
561
562 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700563 * Returns the user configuration of VT setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800564 * @deprecated Does not support MSIM devices. Please use
565 * {@link #isVtEnabledByUserForSlot()} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700566 */
567 public static boolean isVtEnabledByUser(Context context) {
568 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
569 android.provider.Settings.Global.VT_IMS_ENABLED,
570 ImsConfig.FeatureValueConstants.ON);
571 return (enabled == 1) ? true : false;
572 }
573
574 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800575 * Returns the user configuration of VT setting per slot.
576 */
577 public boolean isVtEnabledByUserForSlot() {
578 int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
579 android.provider.Settings.Global.VT_IMS_ENABLED,
580 ImsConfig.FeatureValueConstants.ON);
581 return (enabled == 1);
582 }
583
584 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700585 * Change persistent VT enabled setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800586 *
587 * @deprecated Does not support MSIM devices. Please use
588 * {@link #setVtSettingForSlot} instead.
Etan Cohena7d32e82015-05-04 18:02:09 -0700589 */
590 public static void setVtSetting(Context context, boolean enabled) {
591 int value = enabled ? 1 : 0;
592 android.provider.Settings.Global.putInt(context.getContentResolver(),
593 android.provider.Settings.Global.VT_IMS_ENABLED, value);
594
595 ImsManager imsManager = ImsManager.getInstance(context,
596 SubscriptionManager.getDefaultVoicePhoneId());
597 if (imsManager != null) {
598 try {
599 ImsConfig config = imsManager.getConfigInterface();
600 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
601 TelephonyManager.NETWORK_TYPE_LTE,
602 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800603 : ImsConfig.FeatureValueConstants.OFF,
604 imsManager.mImsConfigListener);
Etan Cohena7d32e82015-05-04 18:02:09 -0700605
606 if (enabled) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700607 log("setVtSetting() : turnOnIms");
Etan Cohena7d32e82015-05-04 18:02:09 -0700608 imsManager.turnOnIms();
Meng Wang9352c432016-06-08 14:22:20 -0700609 } else if (isTurnOffImsAllowedByPlatform(context)
Pavel Zhamaitsiak4ca0cde2015-12-22 16:51:57 -0800610 && (!isVolteEnabledByPlatform(context)
Etan Cohena7d32e82015-05-04 18:02:09 -0700611 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
612 log("setVtSetting() : imsServiceAllowTurnOff -> turnOffIms");
613 imsManager.turnOffIms();
614 }
615 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700616 loge("setVtSetting(): ", e);
Etan Cohena7d32e82015-05-04 18:02:09 -0700617 }
618 }
619 }
620
Brad Ebinger16417b42017-03-07 13:48:50 -0800621 /**
622 * Change persistent VT enabled setting for slot.
623 */
624 public void setVtSettingForSlot(boolean enabled) {
625 int value = enabled ? 1 : 0;
626 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
627 android.provider.Settings.Global.VT_IMS_ENABLED, value);
628
629 try {
630 ImsConfig config = getConfigInterface();
631 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
632 TelephonyManager.NETWORK_TYPE_LTE,
633 enabled ? ImsConfig.FeatureValueConstants.ON
634 : ImsConfig.FeatureValueConstants.OFF,
635 mImsConfigListener);
636
637 if (enabled) {
638 log("setVtSettingForSlot() : turnOnIms");
639 turnOnIms();
640 } else if (isVolteEnabledByPlatformForSlot()
641 && (!isVolteEnabledByPlatformForSlot()
642 || !isEnhanced4gLteModeSettingEnabledByUserForSlot())) {
643 log("setVtSettingForSlot() : imsServiceAllowTurnOff -> turnOffIms");
644 turnOffIms();
645 }
646 } catch (ImsException e) {
647 loge("setVtSettingForSlot(): ", e);
648 }
649 }
650
651 /**
Meng Wang9352c432016-06-08 14:22:20 -0700652 * Returns whether turning off ims is allowed by platform.
653 * The platform property may override the carrier config.
Brad Ebinger16417b42017-03-07 13:48:50 -0800654 *
655 * @deprecated Does not support MSIM devices. Please use
656 * {@link #isTurnOffImsAllowedByPlatformForSlot} instead.
Meng Wang9352c432016-06-08 14:22:20 -0700657 */
658 private static boolean isTurnOffImsAllowedByPlatform(Context context) {
659 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
660 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
661 return true;
662 }
663 return getBooleanCarrierConfig(context,
664 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
665 }
666
Etan Cohena7d32e82015-05-04 18:02:09 -0700667 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800668 * Returns whether turning off ims is allowed by platform.
669 * The platform property may override the carrier config.
670 */
671 private boolean isTurnOffImsAllowedByPlatformForSlot() {
672 if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
673 PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
674 return true;
675 }
676 return getBooleanCarrierConfigForSlot(
677 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
678 }
679
680 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800681 * Returns the user configuration of WFC setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800682 *
683 * @deprecated Does not support MSIM devices. Please use
684 * {@link #isTurnOffImsAllowedByPlatformForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800685 */
686 public static boolean isWfcEnabledByUser(Context context) {
687 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
688 android.provider.Settings.Global.WFC_IMS_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800689 getBooleanCarrierConfig(context,
690 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
691 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800692 return (enabled == 1) ? true : false;
693 }
694
695 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800696 * Returns the user configuration of WFC setting for slot.
697 */
698 public boolean isWfcEnabledByUserForSlot() {
699 int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
700 android.provider.Settings.Global.WFC_IMS_ENABLED,
701 getBooleanCarrierConfigForSlot(
702 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
703 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
704 return enabled == 1;
705 }
706
707 /**
708 * Change persistent WFC enabled setting.
709 * @deprecated Does not support MSIM devices. Please use
710 * {@link #setWfcSettingForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800711 */
712 public static void setWfcSetting(Context context, boolean enabled) {
713 int value = enabled ? 1 : 0;
714 android.provider.Settings.Global.putInt(context.getContentResolver(),
715 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
716
717 ImsManager imsManager = ImsManager.getInstance(context,
718 SubscriptionManager.getDefaultVoicePhoneId());
719 if (imsManager != null) {
720 try {
721 ImsConfig config = imsManager.getConfigInterface();
Etan Cohena00c9192014-12-23 15:02:29 -0800722 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
Nathan Harold3a99f782015-07-24 15:02:34 -0700723 TelephonyManager.NETWORK_TYPE_IWLAN,
Etan Cohena00c9192014-12-23 15:02:29 -0800724 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800725 : ImsConfig.FeatureValueConstants.OFF,
726 imsManager.mImsConfigListener);
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800727
728 if (enabled) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700729 log("setWfcSetting() : turnOnIms");
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800730 imsManager.turnOnIms();
Meng Wang9352c432016-06-08 14:22:20 -0700731 } else if (isTurnOffImsAllowedByPlatform(context)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800732 && (!isVolteEnabledByPlatform(context)
733 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
734 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
735 imsManager.turnOffIms();
736 }
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700737
Meng Wang663aa122016-11-14 21:04:19 -0800738 TelephonyManager tm = (TelephonyManager) context
739 .getSystemService(Context.TELEPHONY_SERVICE);
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700740 setWfcModeInternal(context, enabled
Meng Wang663aa122016-11-14 21:04:19 -0800741 // Choose wfc mode per current roaming preference
742 ? getWfcMode(context, tm.isNetworkRoaming())
743 // Force IMS to register over LTE when turning off WFC
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700744 : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED);
Etan Cohena00c9192014-12-23 15:02:29 -0800745 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -0700746 loge("setWfcSetting(): ", e);
Etan Cohena00c9192014-12-23 15:02:29 -0800747 }
748 }
749 }
750
751 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800752 * Change persistent WFC enabled setting for slot.
753 */
754 public void setWfcSettingForSlot(boolean enabled) {
755 int value = enabled ? 1 : 0;
756 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
757 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
758
Meng Wang51c09072017-03-27 10:47:45 -0700759 setWfcNonPersistentForSlot(enabled, getWfcModeForSlot());
760 }
761
762 /**
763 * Non-persistently change WFC enabled setting and WFC mode for slot
764 *
765 * @param wfcMode The WFC preference if WFC is enabled
766 */
767 public void setWfcNonPersistentForSlot(boolean enabled, int wfcMode) {
768 int imsFeatureValue =
769 enabled ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF;
770 // Force IMS to register over LTE when turning off WFC
771 int imsWfcModeFeatureValue =
772 enabled ? wfcMode : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
773
Brad Ebinger16417b42017-03-07 13:48:50 -0800774 try {
775 ImsConfig config = getConfigInterface();
776 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
777 TelephonyManager.NETWORK_TYPE_IWLAN,
Meng Wang51c09072017-03-27 10:47:45 -0700778 imsFeatureValue,
Brad Ebinger16417b42017-03-07 13:48:50 -0800779 mImsConfigListener);
780
781 if (enabled) {
782 log("setWfcSettingForSlot() : turnOnIms");
783 turnOnIms();
784 } else if (isTurnOffImsAllowedByPlatformForSlot()
785 && (!isVolteEnabledByPlatformForSlot()
786 || !isEnhanced4gLteModeSettingEnabledByUserForSlot())) {
787 log("setWfcSettingForSlot() : imsServiceAllowTurnOff -> turnOffIms");
788 turnOffIms();
789 }
790
Meng Wang51c09072017-03-27 10:47:45 -0700791 setWfcModeInternalForSlot(imsWfcModeFeatureValue);
Brad Ebinger16417b42017-03-07 13:48:50 -0800792 } catch (ImsException e) {
793 loge("setWfcSettingForSlot(): ", e);
794 }
795 }
796
797 /**
798 * Returns the user configuration of WFC preference setting.
799 *
800 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcModeForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800801 */
802 public static int getWfcMode(Context context) {
803 int setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
fionaxu5803ef02016-03-08 11:48:48 -0800804 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context,
805 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
Etan Cohena00c9192014-12-23 15:02:29 -0800806 if (DBG) log("getWfcMode - setting=" + setting);
807 return setting;
808 }
809
810 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800811 * Returns the user configuration of WFC preference setting
812 */
813 public int getWfcModeForSlot() {
814 int setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
815 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfigForSlot(
816 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
817 if (DBG) log("getWfcMode - setting=" + setting);
818 return setting;
819 }
820
821 /**
822 * Change persistent WFC preference setting.
823 *
824 * @deprecated Doesn't support MSIM devices. Use {@link #setWfcModeForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800825 */
826 public static void setWfcMode(Context context, int wfcMode) {
827 if (DBG) log("setWfcMode - setting=" + wfcMode);
828 android.provider.Settings.Global.putInt(context.getContentResolver(),
829 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
830
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700831 setWfcModeInternal(context, wfcMode);
832 }
833
Meng Wang37477012016-09-20 09:59:56 -0700834 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800835 * Change persistent WFC preference setting for slot.
836 */
837 public void setWfcModeForSlot(int wfcMode) {
838 if (DBG) log("setWfcModeForSlot - setting=" + wfcMode);
839 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
840 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
841
842 setWfcModeInternalForSlot(wfcMode);
843 }
844
845 /**
Meng Wang37477012016-09-20 09:59:56 -0700846 * Returns the user configuration of WFC preference setting
847 *
848 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800849 *
850 * @deprecated Doesn't support MSIM devices. Use {@link #getWfcModeForSlot} instead.
Meng Wang37477012016-09-20 09:59:56 -0700851 */
852 public static int getWfcMode(Context context, boolean roaming) {
853 int setting = 0;
854 if (!roaming) {
855 setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
856 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context,
857 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
858 if (DBG) log("getWfcMode - setting=" + setting);
859 } else {
860 setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
861 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE,
862 getIntCarrierConfig(context,
863 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT));
864 if (DBG) log("getWfcMode (roaming) - setting=" + setting);
865 }
866 return setting;
867 }
868
869 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800870 * Returns the user configuration of WFC preference setting for slot
871 *
872 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
873 */
874 public int getWfcModeForSlot(boolean roaming) {
875 int setting = 0;
876 if (!roaming) {
877 setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
878 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfigForSlot(
879 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
880 if (DBG) log("getWfcModeForSlot - setting=" + setting);
881 } else {
882 setting = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
883 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE,
884 getIntCarrierConfigForSlot(
885 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT));
886 if (DBG) log("getWfcModeForSlot (roaming) - setting=" + setting);
887 }
888 return setting;
889 }
890
891 /**
Meng Wang37477012016-09-20 09:59:56 -0700892 * Change persistent WFC preference setting
893 *
894 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800895 *
896 * @deprecated Doesn't support MSIM devices. Please use {@link #setWfcModeForSlot} instead.
Meng Wang37477012016-09-20 09:59:56 -0700897 */
898 public static void setWfcMode(Context context, int wfcMode, boolean roaming) {
899 if (!roaming) {
900 if (DBG) log("setWfcMode - setting=" + wfcMode);
901 android.provider.Settings.Global.putInt(context.getContentResolver(),
902 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
903 } else {
904 if (DBG) log("setWfcMode (roaming) - setting=" + wfcMode);
905 android.provider.Settings.Global.putInt(context.getContentResolver(),
906 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, wfcMode);
907 }
908
909 TelephonyManager tm = (TelephonyManager)
910 context.getSystemService(Context.TELEPHONY_SERVICE);
911 if (roaming == tm.isNetworkRoaming()) {
912 setWfcModeInternal(context, wfcMode);
913 }
914 }
915
Brad Ebinger16417b42017-03-07 13:48:50 -0800916 /**
917 * Change persistent WFC preference setting
918 *
919 * @param roaming {@code false} for home network setting, {@code true} for roaming setting
920 */
921 public void setWfcModeForSlot(int wfcMode, boolean roaming) {
922 if (!roaming) {
923 if (DBG) log("setWfcModeForSlot - setting=" + wfcMode);
924 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
925 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
926 } else {
927 if (DBG) log("setWfcModeForSlot (roaming) - setting=" + wfcMode);
928 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
929 android.provider.Settings.Global.WFC_IMS_ROAMING_MODE, wfcMode);
930 }
931
932 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
933 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
934 if (subIds != null && subIds.length >= 1) {
935 subId = subIds[0];
936 }
937 TelephonyManager tm = (TelephonyManager)
938 mContext.getSystemService(Context.TELEPHONY_SERVICE);
939 if (roaming == tm.isNetworkRoaming(subId)) {
940 setWfcModeInternalForSlot(wfcMode);
941 }
942 }
943
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700944 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800945 final ImsManager imsManager = ImsManager.getInstance(context,
946 SubscriptionManager.getDefaultVoicePhoneId());
947 if (imsManager != null) {
948 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700949 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800950 public void run() {
951 try {
952 imsManager.getConfigInterface().setProvisionedValue(
953 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
954 value);
955 } catch (ImsException e) {
956 // do nothing
957 }
958 }
959 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700960 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800961 }
962 }
963
Brad Ebinger16417b42017-03-07 13:48:50 -0800964 private void setWfcModeInternalForSlot(int wfcMode) {
965 final int value = wfcMode;
966 Thread thread = new Thread(() -> {
967 try {
968 getConfigInterface().setProvisionedValue(
969 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
970 value);
971 } catch (ImsException e) {
972 // do nothing
973 }
974 });
975 thread.start();
976 }
977
Etan Cohena00c9192014-12-23 15:02:29 -0800978 /**
979 * Returns the user configuration of WFC roaming setting
Brad Ebinger16417b42017-03-07 13:48:50 -0800980 *
981 * @deprecated Does not support MSIM devices. Please use
982 * {@link #isWfcRoamingEnabledByUserForSlot} instead.
Etan Cohena00c9192014-12-23 15:02:29 -0800983 */
984 public static boolean isWfcRoamingEnabledByUser(Context context) {
985 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
986 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800987 getBooleanCarrierConfig(context,
988 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
989 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800990 return (enabled == 1) ? true : false;
991 }
992
993 /**
Brad Ebinger16417b42017-03-07 13:48:50 -0800994 * Returns the user configuration of WFC roaming setting for slot
995 */
996 public boolean isWfcRoamingEnabledByUserForSlot() {
997 int enabled = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
998 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
999 getBooleanCarrierConfigForSlot(
1000 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
1001 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
1002 return (enabled == 1);
1003 }
1004
1005 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001006 * Change persistent WFC roaming enabled setting
1007 */
1008 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Etan Cohena00c9192014-12-23 15:02:29 -08001009 android.provider.Settings.Global.putInt(context.getContentResolver(),
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001010 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08001011 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001012 : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -08001013
1014 final ImsManager imsManager = ImsManager.getInstance(context,
1015 SubscriptionManager.getDefaultVoicePhoneId());
1016 if (imsManager != null) {
Brad Ebinger16417b42017-03-07 13:48:50 -08001017 imsManager.setWfcRoamingSettingInternal(enabled);
Etan Cohena00c9192014-12-23 15:02:29 -08001018 }
1019 }
1020
1021 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001022 * Change persistent WFC roaming enabled setting
1023 */
1024 public void setWfcRoamingSettingForSlot(boolean enabled) {
1025 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
1026 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
1027 enabled ? ImsConfig.FeatureValueConstants.ON
1028 : ImsConfig.FeatureValueConstants.OFF);
1029
1030 setWfcRoamingSettingInternal(enabled);
1031 }
1032
1033 private void setWfcRoamingSettingInternal(boolean enabled) {
1034 final int value = enabled
1035 ? ImsConfig.FeatureValueConstants.ON
1036 : ImsConfig.FeatureValueConstants.OFF;
1037 Thread thread = new Thread(() -> {
1038 try {
1039 getConfigInterface().setProvisionedValue(
1040 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING,
1041 value);
1042 } catch (ImsException e) {
1043 // do nothing
1044 }
1045 });
1046 thread.start();
1047 }
1048
1049 /**
Etan Cohena00c9192014-12-23 15:02:29 -08001050 * Returns a platform configuration for WFC which may override the user
1051 * setting. Note: WFC presumes that VoLTE is enabled (these are
1052 * configuration settings which must be done correctly).
Brad Ebinger16417b42017-03-07 13:48:50 -08001053 *
1054 * @deprecated Doesn't work for MSIM devices. Use {@link #isWfcEnabledByPlatformForSlot}
1055 * instead.
Etan Cohena00c9192014-12-23 15:02:29 -08001056 */
1057 public static boolean isWfcEnabledByPlatform(Context context) {
1058 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
1059 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
1060 return true;
1061 }
1062
1063 return
1064 context.getResources().getBoolean(
1065 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Junda Liue7663c02015-06-23 11:16:26 -07001066 getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001067 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
1068 isGbaValid(context);
1069 }
1070
1071 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001072 * Returns a platform configuration for WFC which may override the user
1073 * setting per slot. Note: WFC presumes that VoLTE is enabled (these are
1074 * configuration settings which must be done correctly).
1075 */
1076 public boolean isWfcEnabledByPlatformForSlot() {
1077 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
1078 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
1079 return true;
1080 }
1081
1082 return mContext.getResources().getBoolean(
1083 com.android.internal.R.bool.config_device_wfc_ims_available) &&
1084 getBooleanCarrierConfigForSlot(
1085 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
1086 isGbaValidForSlot();
1087 }
1088
1089 /**
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001090 * If carrier requires that IMS is only available if GBA capable SIM is used,
1091 * then this function checks GBA bit in EF IST.
1092 *
1093 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
Brad Ebinger16417b42017-03-07 13:48:50 -08001094 *
1095 * @deprecated Use {@link #isGbaValidForSlot} instead
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -07001096 */
1097 private static boolean isGbaValid(Context context) {
1098 if (getBooleanCarrierConfig(context,
1099 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
1100 final TelephonyManager telephonyManager = TelephonyManager.getDefault();
1101 String efIst = telephonyManager.getIsimIst();
1102 if (efIst == null) {
1103 loge("ISF is NULL");
1104 return true;
1105 }
1106 boolean result = efIst != null && efIst.length() > 1 &&
1107 (0x02 & (byte)efIst.charAt(1)) != 0;
1108 if (DBG) log("GBA capable=" + result + ", ISF=" + efIst);
1109 return result;
1110 }
1111 return true;
Etan Cohena00c9192014-12-23 15:02:29 -08001112 }
1113
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001114 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001115 * If carrier requires that IMS is only available if GBA capable SIM is used,
1116 * then this function checks GBA bit in EF IST.
1117 *
1118 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
1119 */
1120 private boolean isGbaValidForSlot() {
1121 if (getBooleanCarrierConfigForSlot(
1122 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
1123 final TelephonyManager telephonyManager = TelephonyManager.getDefault();
1124 String efIst = telephonyManager.getIsimIst();
1125 if (efIst == null) {
1126 loge("isGbaValidForSlot - ISF is NULL");
1127 return true;
1128 }
1129 boolean result = efIst != null && efIst.length() > 1 &&
1130 (0x02 & (byte)efIst.charAt(1)) != 0;
1131 if (DBG) log("isGbaValidForSlot - GBA capable=" + result + ", ISF=" + efIst);
1132 return result;
1133 }
1134 return true;
1135 }
1136
1137 /**
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001138 * This function should be called when ImsConfig.ACTION_IMS_CONFIG_CHANGED is received.
1139 *
1140 * We cannot register receiver in ImsManager because this would lead to resource leak.
1141 * ImsManager can be created in different processes and it is not notified when that process
1142 * is about to be terminated.
1143 *
1144 * @hide
1145 * */
1146 public static void onProvisionedValueChanged(Context context, int item, String value) {
Amit Mahajan24f7b162016-07-21 16:33:53 -07001147 if (DBG) Rlog.d(TAG, "onProvisionedValueChanged: item=" + item + " val=" + value);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001148 ImsManager mgr = ImsManager.getInstance(context,
1149 SubscriptionManager.getDefaultVoicePhoneId());
1150
1151 switch (item) {
1152 case ImsConfig.ConfigConstants.VLT_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001153 mgr.setVolteProvisionedProperty(value.equals("1"));
1154 if (DBG) Rlog.d(TAG,"isVoLteProvisioned = " + mgr.isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001155 break;
1156
1157 case ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001158 mgr.setWfcProvisionedProperty(value.equals("1"));
1159 if (DBG) Rlog.d(TAG,"isWfcProvisioned = " + mgr.isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001160 break;
1161
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001162 case ImsConfig.ConfigConstants.LVC_SETTING_ENABLED:
Amit Mahajan24f7b162016-07-21 16:33:53 -07001163 mgr.setVtProvisionedProperty(value.equals("1"));
1164 if (DBG) Rlog.d(TAG,"isVtProvisioned = " + mgr.isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001165 break;
1166
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001167 }
1168 }
1169
1170 private class AsyncUpdateProvisionedValues extends AsyncTask<Void, Void, Void> {
1171 @Override
1172 protected Void doInBackground(Void... params) {
1173 // disable on any error
Amit Mahajan24f7b162016-07-21 16:33:53 -07001174 setVolteProvisionedProperty(false);
1175 setWfcProvisionedProperty(false);
1176 setVtProvisionedProperty(false);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001177
1178 try {
1179 ImsConfig config = getConfigInterface();
1180 if (config != null) {
Amit Mahajan24f7b162016-07-21 16:33:53 -07001181 setVolteProvisionedProperty(getProvisionedBool(config,
1182 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED));
1183 if (DBG) Rlog.d(TAG, "isVoLteProvisioned = " + isVolteProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001184
Amit Mahajan24f7b162016-07-21 16:33:53 -07001185 setWfcProvisionedProperty(getProvisionedBool(config,
1186 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED));
1187 if (DBG) Rlog.d(TAG, "isWfcProvisioned = " + isWfcProvisioned());
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001188
Amit Mahajan24f7b162016-07-21 16:33:53 -07001189 setVtProvisionedProperty(getProvisionedBool(config,
1190 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED));
1191 if (DBG) Rlog.d(TAG, "isVtProvisioned = " + isVtProvisioned());
Nathan Harolda9fc7f12016-06-30 16:12:14 -07001192
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001193 }
1194 } catch (ImsException ie) {
Meng Wangca7d4c42016-06-30 22:05:24 -07001195 Rlog.e(TAG, "AsyncUpdateProvisionedValues error: ", ie);
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001196 }
1197
1198 return null;
1199 }
1200
1201 private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
1202 return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
1203 }
1204 }
1205
1206 /** Asynchronously get VoLTE, WFC, VT provisioning statuses */
1207 private void updateProvisionedValues() {
Brad Ebinger16417b42017-03-07 13:48:50 -08001208 if (getBooleanCarrierConfigForSlot(
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001209 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
1210
1211 new AsyncUpdateProvisionedValues().execute();
1212 }
1213 }
1214
1215 /**
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001216 * Sync carrier config and user settings with ImsConfig.
1217 *
1218 * @param context for the manager object
1219 * @param phoneId phone id
1220 * @param force update
Brad Ebinger16417b42017-03-07 13:48:50 -08001221 *
1222 * @deprecated Doesn't support MSIM devices. Use {@link #updateImsServiceConfigForSlot} instead.
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001223 */
1224 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -07001225 if (!force) {
1226 if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) {
1227 log("updateImsServiceConfig: SIM not ready");
1228 // Don't disable IMS if SIM is not ready
1229 return;
1230 }
1231 }
1232
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001233 final ImsManager imsManager = ImsManager.getInstance(context, phoneId);
1234 if (imsManager != null && (!imsManager.mConfigUpdated || force)) {
1235 try {
Pavel Zhamaitsiak002b2042016-06-03 16:05:31 -07001236 imsManager.updateProvisionedValues();
1237
Pavel Zhamaitsiakd46779c2016-06-03 10:39:51 -07001238 // TODO: Extend ImsConfig API and set all feature values in single function call.
1239
1240 // Note: currently the order of updates is set to produce different order of
1241 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
1242 // differentiate this code path from vendor code perspective.
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001243 boolean isImsUsed = imsManager.updateVolteFeatureValue();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001244 isImsUsed |= imsManager.updateWfcFeatureAndProvisionedValues();
Pavel Zhamaitsiakd46779c2016-06-03 10:39:51 -07001245 isImsUsed |= imsManager.updateVideoCallFeatureValue();
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001246
Meng Wang9352c432016-06-08 14:22:20 -07001247 if (isImsUsed || !isTurnOffImsAllowedByPlatform(context)) {
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001248 // Turn on IMS if it is used.
1249 // Also, if turning off is not allowed for current carrier,
1250 // we need to turn IMS on because it might be turned off before
1251 // phone switched to current carrier.
Meng Wangca7d4c42016-06-30 22:05:24 -07001252 log("updateImsServiceConfig: turnOnIms");
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001253 imsManager.turnOnIms();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001254 } else {
1255 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Meng Wangca7d4c42016-06-30 22:05:24 -07001256 log("updateImsServiceConfig: turnOffIms");
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001257 imsManager.turnOffIms();
1258 }
1259
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001260 imsManager.mConfigUpdated = true;
1261 } catch (ImsException e) {
Meng Wangca7d4c42016-06-30 22:05:24 -07001262 loge("updateImsServiceConfig: ", e);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001263 imsManager.mConfigUpdated = false;
1264 }
1265 }
1266 }
1267
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001268 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001269 * Sync carrier config and user settings with ImsConfig.
1270 *
1271 * @param context for the manager object
1272 * @param phoneId phone id
1273 * @param force update
1274 */
1275 public void updateImsServiceConfigForSlot(boolean force) {
1276 if (!force) {
1277 if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) {
1278 log("updateImsServiceConfigForSlot: SIM not ready");
1279 // Don't disable IMS if SIM is not ready
1280 return;
1281 }
1282 }
1283
1284 if (!mConfigUpdated || force) {
1285 try {
1286 updateProvisionedValues();
1287
1288 // TODO: Extend ImsConfig API and set all feature values in single function call.
1289
1290 // Note: currently the order of updates is set to produce different order of
1291 // setFeatureValue() function calls from setAdvanced4GMode(). This is done to
1292 // differentiate this code path from vendor code perspective.
1293 boolean isImsUsed = updateVolteFeatureValue();
1294 isImsUsed |= updateWfcFeatureAndProvisionedValues();
1295 isImsUsed |= updateVideoCallFeatureValue();
1296
1297 if (isImsUsed || !isTurnOffImsAllowedByPlatformForSlot()) {
1298 // Turn on IMS if it is used.
1299 // Also, if turning off is not allowed for current carrier,
1300 // we need to turn IMS on because it might be turned off before
1301 // phone switched to current carrier.
1302 log("updateImsServiceConfigForSlot: turnOnIms");
1303 turnOnIms();
1304 } else {
1305 // Turn off IMS if it is not used AND turning off is allowed for carrier.
1306 log("updateImsServiceConfigForSlot: turnOffIms");
1307 turnOffIms();
1308 }
1309
1310 mConfigUpdated = true;
1311 } catch (ImsException e) {
1312 loge("updateImsServiceConfigForSlot: ", e);
1313 mConfigUpdated = false;
1314 }
1315 }
1316 }
1317
1318 /**
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001319 * Update VoLTE config
1320 * @return whether feature is On
1321 * @throws ImsException
1322 */
1323 private boolean updateVolteFeatureValue() throws ImsException {
Brad Ebinger16417b42017-03-07 13:48:50 -08001324 boolean available = isVolteEnabledByPlatformForSlot();
1325 boolean enabled = isEnhanced4gLteModeSettingEnabledByUserForSlot();
1326 boolean isNonTty = isNonTtyOrTtyOnVolteEnabledForSlot();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001327 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001328
1329 log("updateVolteFeatureValue: available = " + available
1330 + ", enabled = " + enabled
1331 + ", nonTTY = " + isNonTty);
1332
1333 getConfigInterface().setFeatureValue(
1334 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
1335 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001336 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001337 ImsConfig.FeatureValueConstants.ON :
1338 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001339 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001340
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001341 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001342 }
1343
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001344 /**
Jack Yu643ffe42016-07-08 14:25:46 -07001345 * Update video call over LTE config
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001346 * @return whether feature is On
1347 * @throws ImsException
1348 */
1349 private boolean updateVideoCallFeatureValue() throws ImsException {
Brad Ebinger16417b42017-03-07 13:48:50 -08001350 boolean available = isVtEnabledByPlatformForSlot();
1351 boolean enabled = isVtEnabledByUserForSlot();
1352 boolean isNonTty = isNonTtyOrTtyOnVolteEnabledForSlot();
Amit Mahajan24f7b162016-07-21 16:33:53 -07001353 boolean isDataEnabled = isDataEnabled();
Jack Yu57781852016-11-16 17:20:38 -08001354 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext,
1355 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Jack Yu643ffe42016-07-08 14:25:46 -07001356
Jack Yu57781852016-11-16 17:20:38 -08001357 boolean isFeatureOn = available && enabled && isNonTty
1358 && (ignoreDataEnabledChanged || isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001359
1360 log("updateVideoCallFeatureValue: available = " + available
1361 + ", enabled = " + enabled
Jack Yu643ffe42016-07-08 14:25:46 -07001362 + ", nonTTY = " + isNonTty
Amit Mahajan24f7b162016-07-21 16:33:53 -07001363 + ", data enabled = " + isDataEnabled);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001364
1365 getConfigInterface().setFeatureValue(
1366 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1367 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001368 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001369 ImsConfig.FeatureValueConstants.ON :
1370 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001371 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001372
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001373 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001374 }
1375
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001376 /**
1377 * Update WFC config
1378 * @return whether feature is On
1379 * @throws ImsException
1380 */
1381 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
Meng Wang531a8b62016-10-06 11:29:46 -07001382 boolean isNetworkRoaming = TelephonyManager.getDefault().isNetworkRoaming();
Brad Ebinger16417b42017-03-07 13:48:50 -08001383 boolean available = isWfcEnabledByPlatformForSlot();
1384 boolean enabled = isWfcEnabledByUserForSlot();
1385 int mode = getWfcModeForSlot(isNetworkRoaming);
1386 boolean roaming = isWfcRoamingEnabledByUserForSlot();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001387 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001388
1389 log("updateWfcFeatureAndProvisionedValues: available = " + available
1390 + ", enabled = " + enabled
1391 + ", mode = " + mode
1392 + ", roaming = " + roaming);
1393
1394 getConfigInterface().setFeatureValue(
Pavel Zhamaitsiake6f99432015-09-11 10:29:30 -07001395 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
1396 TelephonyManager.NETWORK_TYPE_IWLAN,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001397 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001398 ImsConfig.FeatureValueConstants.ON :
1399 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001400 mImsConfigListener);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001401
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001402 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001403 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
1404 roaming = false;
1405 }
1406 setWfcModeInternal(mContext, mode);
Brad Ebinger16417b42017-03-07 13:48:50 -08001407 setWfcRoamingSettingInternal(roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -07001408
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -08001409 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -07001410 }
1411
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001412 /**
1413 * Do NOT use this directly, instead use {@link #getInstance}.
1414 */
1415 @VisibleForTesting
1416 public ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001417 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -07001418 mPhoneId = phoneId;
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001419 mConfigDynamicBind = mContext.getResources().getBoolean(
1420 com.android.internal.R.bool.config_dynamic_bind_ims);
Brad Ebinger16417b42017-03-07 13:48:50 -08001421 mConfigManager = (CarrierConfigManager) context.getSystemService(
1422 Context.CARRIER_CONFIG_SERVICE);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001423 createImsService();
1424 }
1425
1426 /**
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001427 * @return Whether or not ImsManager is configured to Dynamically bind or not to support legacy
1428 * devices.
1429 */
1430 public boolean isDynamicBinding() {
1431 return mConfigDynamicBind;
Wink Savilleef36ef62014-06-11 08:39:38 -07001432 }
1433
Etan Cohenf4311122015-02-26 17:47:13 -08001434 /*
Brad Ebingerff097922017-06-19 15:43:08 -07001435 * Returns a flag indicating whether the IMS service is available. If it is not available,
1436 * it will try to connect before reporting failure.
Etan Cohenf4311122015-02-26 17:47:13 -08001437 */
1438 public boolean isServiceAvailable() {
Brad Ebingerff097922017-06-19 15:43:08 -07001439 connectIfServiceIsAvailable();
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001440 // mImsServiceProxy will always create an ImsServiceProxy.
1441 return mImsServiceProxy.isBinderAlive();
Etan Cohenf4311122015-02-26 17:47:13 -08001442 }
1443
Brad Ebingerff097922017-06-19 15:43:08 -07001444 /**
1445 * If the service is available, try to reconnect.
1446 */
1447 public void connectIfServiceIsAvailable() {
1448 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
1449 createImsService();
1450 }
1451 }
1452
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001453 public void setImsConfigListener(ImsConfigListener listener) {
1454 mImsConfigListener = listener;
1455 }
1456
Brad Ebingerb10b61e2017-04-18 11:45:26 -07001457
1458 /**
1459 * Adds a callback for status changed events if the binder is already available. If it is not,
1460 * this method will throw an ImsException.
1461 */
1462 public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.INotifyStatusChanged c)
1463 throws ImsException {
1464 if (!mImsServiceProxy.isBinderAlive()) {
1465 throw new ImsException("Binder is not active!",
1466 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1467 }
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001468 if (c != null) {
1469 mStatusCallbacks.add(c);
1470 }
1471 }
1472
Wink Savilleef36ef62014-06-11 08:39:38 -07001473 /**
1474 * Opens the IMS service for making calls and/or receiving generic IMS calls.
1475 * The caller may make subsquent calls through {@link #makeCall}.
1476 * The IMS service will register the device to the operator's network with the credentials
1477 * (from ISIM) periodically in order to receive calls from the operator's network.
1478 * When the IMS service receives a new call, it will send out an intent with
1479 * the provided action string.
1480 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
1481 *
1482 * @param serviceClass a service class specified in {@link ImsServiceClass}
1483 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1484 * @param incomingCallPendingIntent When an incoming call is received,
1485 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
1486 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
1487 * as the result code and the intent to fill in the call ID; It cannot be null
1488 * @param listener To listen to IMS registration events; It cannot be null
1489 * @return identifier (greater than 0) for the specified service
1490 * @throws NullPointerException if {@code incomingCallPendingIntent}
1491 * or {@code listener} is null
1492 * @throws ImsException if calling the IMS service results in an error
1493 * @see #getCallId
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001494 * @see #getImsSessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001495 */
1496 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
1497 ImsConnectionStateListener listener) throws ImsException {
1498 checkAndThrowExceptionIfServiceUnavailable();
1499
1500 if (incomingCallPendingIntent == null) {
1501 throw new NullPointerException("incomingCallPendingIntent can't be null");
1502 }
1503
1504 if (listener == null) {
1505 throw new NullPointerException("listener can't be null");
1506 }
1507
1508 int result = 0;
1509
1510 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001511 result = mImsServiceProxy.startSession(incomingCallPendingIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -07001512 createRegistrationListenerProxy(serviceClass, listener));
1513 } catch (RemoteException e) {
1514 throw new ImsException("open()", e,
1515 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1516 }
1517
1518 if (result <= 0) {
1519 // If the return value is a minus value,
1520 // it means that an error occurred in the service.
1521 // So, it needs to convert to the reason code specified in ImsReasonInfo.
1522 throw new ImsException("open()", (result * (-1)));
1523 }
1524
1525 return result;
1526 }
1527
1528 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001529 * Adds registration listener to the IMS service.
1530 *
1531 * @param serviceClass a service class specified in {@link ImsServiceClass}
1532 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
1533 * @param listener To listen to IMS registration events; It cannot be null
1534 * @throws NullPointerException if {@code listener} is null
1535 * @throws ImsException if calling the IMS service results in an error
1536 */
1537 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
1538 throws ImsException {
1539 checkAndThrowExceptionIfServiceUnavailable();
1540
1541 if (listener == null) {
1542 throw new NullPointerException("listener can't be null");
1543 }
1544
1545 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001546 ImsRegistrationListenerProxy p = createRegistrationListenerProxy(serviceClass,
1547 listener);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001548 mRegistrationListeners.add(p);
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001549 mImsServiceProxy.addRegistrationListener(p);
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -07001550 } catch (RemoteException e) {
1551 throw new ImsException("addRegistrationListener()", e,
1552 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1553 }
1554 }
1555
1556 /**
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001557 * Removes the registration listener from the IMS service.
1558 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001559 * @param listener Previously registered listener that will be removed. Can not be null.
1560 * @throws NullPointerException if {@code listener} is null
1561 * @throws ImsException if calling the IMS service results in an error
1562 * instead.
1563 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001564 public void removeRegistrationListener(ImsConnectionStateListener listener)
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001565 throws ImsException {
1566 checkAndThrowExceptionIfServiceUnavailable();
1567
1568 if (listener == null) {
1569 throw new NullPointerException("listener can't be null");
1570 }
1571
1572 try {
1573 Optional<ImsRegistrationListenerProxy> optionalProxy = mRegistrationListeners.stream()
1574 .filter(l -> listener.equals(l.mListener)).findFirst();
1575 if(optionalProxy.isPresent()) {
1576 ImsRegistrationListenerProxy p = optionalProxy.get();
1577 mRegistrationListeners.remove(p);
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001578 mImsServiceProxy.removeRegistrationListener(p);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001579 }
1580 } catch (RemoteException e) {
1581 throw new ImsException("removeRegistrationListener()", e,
1582 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1583 }
1584 }
1585
1586 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001587 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
1588 * All the resources that were allocated to the service are also released.
1589 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001590 * @param sessionId a session id to be closed which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001591 * @throws ImsException if calling the IMS service results in an error
1592 */
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001593 public void close(int sessionId) throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001594 checkAndThrowExceptionIfServiceUnavailable();
1595
1596 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001597 mImsServiceProxy.endSession(sessionId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001598 } catch (RemoteException e) {
1599 throw new ImsException("close()", e,
1600 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1601 } finally {
1602 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001603 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001604 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001605 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001606 }
1607 }
1608
1609 /**
1610 * Gets the configuration interface to provision / withdraw the supplementary service settings.
1611 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001612 * @return the Ut interface instance
1613 * @throws ImsException if getting the Ut interface results in an error
1614 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001615 public ImsUtInterface getSupplementaryServiceConfiguration()
Wink Savilleef36ef62014-06-11 08:39:38 -07001616 throws ImsException {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001617 // FIXME: manage the multiple Ut interfaces based on the session id
Brad Ebinger138b4a62017-06-20 16:29:50 -07001618 if (mUt != null && mUt.isBinderAlive()) {
1619 return mUt;
Wink Savilleef36ef62014-06-11 08:39:38 -07001620 }
1621
Brad Ebinger138b4a62017-06-20 16:29:50 -07001622 checkAndThrowExceptionIfServiceUnavailable();
1623 try {
1624 IImsUt iUt = mImsServiceProxy.getUtInterface();
1625
1626 if (iUt == null) {
1627 throw new ImsException("getSupplementaryServiceConfiguration()",
1628 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
1629 }
1630
1631 mUt = new ImsUt(iUt);
1632 } catch (RemoteException e) {
1633 throw new ImsException("getSupplementaryServiceConfiguration()", e,
1634 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1635 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001636 return mUt;
1637 }
1638
1639 /**
1640 * Checks if the IMS service has successfully registered to the IMS network
1641 * with the specified service & call type.
1642 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001643 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1644 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1645 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1646 * @param callType a call type that is specified in {@link ImsCallProfile}
1647 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
1648 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1649 * {@link ImsCallProfile#CALL_TYPE_VT}
1650 * {@link ImsCallProfile#CALL_TYPE_VS}
1651 * @return true if the specified service id is connected to the IMS network;
1652 * false otherwise
1653 * @throws ImsException if calling the IMS service results in an error
1654 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001655 public boolean isConnected(int serviceType, int callType)
Wink Savilleef36ef62014-06-11 08:39:38 -07001656 throws ImsException {
1657 checkAndThrowExceptionIfServiceUnavailable();
1658
1659 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001660 return mImsServiceProxy.isConnected(serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001661 } catch (RemoteException e) {
1662 throw new ImsException("isServiceConnected()", e,
1663 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1664 }
1665 }
1666
1667 /**
1668 * Checks if the specified IMS service is opend.
1669 *
Wink Savilleef36ef62014-06-11 08:39:38 -07001670 * @return true if the specified service id is opened; false otherwise
1671 * @throws ImsException if calling the IMS service results in an error
1672 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001673 public boolean isOpened() throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001674 checkAndThrowExceptionIfServiceUnavailable();
1675
1676 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001677 return mImsServiceProxy.isOpened();
Wink Savilleef36ef62014-06-11 08:39:38 -07001678 } catch (RemoteException e) {
1679 throw new ImsException("isOpened()", e,
1680 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1681 }
1682 }
1683
1684 /**
1685 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
1686 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001687 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001688 * @param serviceType a service type that is specified in {@link ImsCallProfile}
1689 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
1690 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
1691 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
1692 * @param callType a call type that is specified in {@link ImsCallProfile}
1693 * {@link ImsCallProfile#CALL_TYPE_VOICE}
1694 * {@link ImsCallProfile#CALL_TYPE_VT}
1695 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
1696 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
1697 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
1698 * {@link ImsCallProfile#CALL_TYPE_VS}
1699 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
1700 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
1701 * @return a {@link ImsCallProfile} object
1702 * @throws ImsException if calling the IMS service results in an error
1703 */
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001704 public ImsCallProfile createCallProfile(int sessionId, int serviceType, int callType)
1705 throws ImsException {
Wink Savilleef36ef62014-06-11 08:39:38 -07001706 checkAndThrowExceptionIfServiceUnavailable();
1707
1708 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001709 return mImsServiceProxy.createCallProfile(sessionId, serviceType, callType);
Wink Savilleef36ef62014-06-11 08:39:38 -07001710 } catch (RemoteException e) {
1711 throw new ImsException("createCallProfile()", e,
1712 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1713 }
1714 }
1715
1716 /**
1717 * Creates a {@link ImsCall} to make a call.
1718 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001719 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001720 * @param profile a call profile to make the call
1721 * (it contains service type, call type, media information, etc.)
1722 * @param participants participants to invite the conference call
1723 * @param listener listen to the call events from {@link ImsCall}
1724 * @return a {@link ImsCall} object
1725 * @throws ImsException if calling the IMS service results in an error
1726 */
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001727 public ImsCall makeCall(int sessionId, ImsCallProfile profile, String[] callees,
Wink Savilleef36ef62014-06-11 08:39:38 -07001728 ImsCall.Listener listener) throws ImsException {
1729 if (DBG) {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001730 log("makeCall :: sessionId=" + sessionId
fionaxu7b3107c2016-07-06 14:04:06 -07001731 + ", profile=" + profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001732 }
1733
1734 checkAndThrowExceptionIfServiceUnavailable();
1735
1736 ImsCall call = new ImsCall(mContext, profile);
1737
1738 call.setListener(listener);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001739 ImsCallSession session = createCallSession(sessionId, profile);
Wink Savilleef36ef62014-06-11 08:39:38 -07001740
1741 if ((callees != null) && (callees.length == 1)) {
1742 call.start(session, callees[0]);
1743 } else {
1744 call.start(session, callees);
1745 }
1746
1747 return call;
1748 }
1749
1750 /**
1751 * Creates a {@link ImsCall} to take an incoming call.
1752 *
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001753 * @param sessionId a session id which is obtained from {@link ImsManager#open}
Wink Savilleef36ef62014-06-11 08:39:38 -07001754 * @param incomingCallIntent the incoming call broadcast intent
1755 * @param listener to listen to the call events from {@link ImsCall}
1756 * @return a {@link ImsCall} object
1757 * @throws ImsException if calling the IMS service results in an error
1758 */
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001759 public ImsCall takeCall(int sessionId, Intent incomingCallIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -07001760 ImsCall.Listener listener) throws ImsException {
1761 if (DBG) {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001762 log("takeCall :: sessionId=" + sessionId
Wink Savilleef36ef62014-06-11 08:39:38 -07001763 + ", incomingCall=" + incomingCallIntent);
1764 }
1765
1766 checkAndThrowExceptionIfServiceUnavailable();
1767
1768 if (incomingCallIntent == null) {
1769 throw new ImsException("Can't retrieve session with null intent",
1770 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1771 }
1772
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001773 int incomingServiceId = getImsSessionId(incomingCallIntent);
Wink Savilleef36ef62014-06-11 08:39:38 -07001774
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001775 if (sessionId != incomingServiceId) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001776 throw new ImsException("Service id is mismatched in the incoming call intent",
1777 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1778 }
1779
1780 String callId = getCallId(incomingCallIntent);
1781
1782 if (callId == null) {
1783 throw new ImsException("Call ID missing in the incoming call intent",
1784 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1785 }
1786
1787 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001788 IImsCallSession session = mImsServiceProxy.getPendingCallSession(sessionId, callId);
Wink Savilleef36ef62014-06-11 08:39:38 -07001789
1790 if (session == null) {
1791 throw new ImsException("No pending session for the call",
1792 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
1793 }
1794
1795 ImsCall call = new ImsCall(mContext, session.getCallProfile());
1796
1797 call.attachSession(new ImsCallSession(session));
1798 call.setListener(listener);
1799
1800 return call;
1801 } catch (Throwable t) {
1802 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
1803 }
1804 }
1805
1806 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001807 * Gets the config interface to get/set service/capability parameters.
1808 *
1809 * @return the ImsConfig instance.
1810 * @throws ImsException if getting the setting interface results in an error.
1811 */
1812 public ImsConfig getConfigInterface() throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07001813 if (mConfig != null && mConfig.isBinderAlive()) {
1814 return mConfig;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001815 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07001816
1817 checkAndThrowExceptionIfServiceUnavailable();
1818 try {
1819 IImsConfig config = mImsServiceProxy.getConfigInterface();
1820 if (config == null) {
1821 throw new ImsException("getConfigInterface()",
1822 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1823 }
1824 mConfig = new ImsConfig(config, mContext);
1825 } catch (RemoteException e) {
1826 throw new ImsException("getConfigInterface()", e,
1827 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1828 }
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001829 return mConfig;
1830 }
1831
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001832 public void setUiTTYMode(Context context, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301833 throws ImsException {
1834
Etan Cohen82f78122014-12-15 10:10:14 -08001835 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301836
Etan Cohen82f78122014-12-15 10:10:14 -08001837 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08001838 mImsServiceProxy.setUiTTYMode(uiTtyMode, onComplete);
Etan Cohen82f78122014-12-15 10:10:14 -08001839 } catch (RemoteException e) {
1840 throw new ImsException("setTTYMode()", e,
1841 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1842 }
1843
Brad Ebinger16417b42017-03-07 13:48:50 -08001844 if (!getBooleanCarrierConfigForSlot(
Junda Liue7663c02015-06-23 11:16:26 -07001845 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -08001846 setAdvanced4GMode((uiTtyMode == TelecomManager.TTY_MODE_OFF) &&
Brad Ebinger16417b42017-03-07 13:48:50 -08001847 isEnhanced4gLteModeSettingEnabledByUserForSlot());
Etan Cohen82f78122014-12-15 10:10:14 -08001848 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301849 }
1850
Naveen Kalla525c3a22017-02-06 14:46:42 -08001851 private ImsReasonInfo makeACopy(ImsReasonInfo imsReasonInfo) {
1852 Parcel p = Parcel.obtain();
1853 imsReasonInfo.writeToParcel(p, 0);
1854 p.setDataPosition(0);
1855 ImsReasonInfo clonedReasonInfo = ImsReasonInfo.CREATOR.createFromParcel(p);
1856 p.recycle();
1857 return clonedReasonInfo;
1858 }
1859
1860 /**
1861 * Get Recent IMS Disconnect Reasons.
1862 *
1863 * @return ArrayList of ImsReasonInfo objects. MAX size of the arraylist
1864 * is MAX_RECENT_DISCONNECT_REASONS. The objects are in the
1865 * chronological order.
1866 */
1867 public ArrayList<ImsReasonInfo> getRecentImsDisconnectReasons() {
1868 ArrayList<ImsReasonInfo> disconnectReasons = new ArrayList<>();
1869
1870 for (ImsReasonInfo reason : mRecentDisconnectReasons) {
1871 disconnectReasons.add(makeACopy(reason));
1872 }
1873 return disconnectReasons;
1874 }
Brad Ebinger16417b42017-03-07 13:48:50 -08001875
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001876 public int getImsServiceStatus() throws ImsException {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001877 return mImsServiceProxy.getFeatureStatus();
1878 }
Naveen Kalla525c3a22017-02-06 14:46:42 -08001879
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001880 /**
Junda Liue7663c02015-06-23 11:16:26 -07001881 * Get the boolean config from carrier config manager.
1882 *
1883 * @param context the context to get carrier service
1884 * @param key config key defined in CarrierConfigManager
1885 * @return boolean value of corresponding key.
Brad Ebinger16417b42017-03-07 13:48:50 -08001886 *
1887 * @deprecated Does not support MSIM devices. Use
1888 * {@link #getBooleanCarrierConfigForSlot(Context, String)} instead.
Junda Liue7663c02015-06-23 11:16:26 -07001889 */
1890 private static boolean getBooleanCarrierConfig(Context context, String key) {
1891 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
1892 Context.CARRIER_CONFIG_SERVICE);
Jonathan Basseri2acea6f2015-07-01 15:00:38 -07001893 PersistableBundle b = null;
Junda Liue7663c02015-06-23 11:16:26 -07001894 if (configManager != null) {
Jonathan Basseri2acea6f2015-07-01 15:00:38 -07001895 b = configManager.getConfig();
1896 }
1897 if (b != null) {
1898 return b.getBoolean(key);
Junda Liue7663c02015-06-23 11:16:26 -07001899 } else {
1900 // Return static default defined in CarrierConfigManager.
1901 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1902 }
1903 }
1904
1905 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001906 * Get the boolean config from carrier config manager.
1907 *
1908 * @param key config key defined in CarrierConfigManager
1909 * @return boolean value of corresponding key.
1910 */
1911 private boolean getBooleanCarrierConfigForSlot(String key) {
1912 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1913 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1914 if (subIds != null && subIds.length >= 1) {
1915 subId = subIds[0];
1916 }
1917 PersistableBundle b = null;
1918 if (mConfigManager != null) {
1919 // If an invalid subId is used, this bundle will contain default values.
1920 b = mConfigManager.getConfigForSubId(subId);
1921 }
1922 if (b != null) {
1923 return b.getBoolean(key);
1924 } else {
1925 // Return static default defined in CarrierConfigManager.
1926 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1927 }
1928 }
1929
1930 /**
fionaxu5803ef02016-03-08 11:48:48 -08001931 * Get the int config from carrier config manager.
1932 *
1933 * @param context the context to get carrier service
1934 * @param key config key defined in CarrierConfigManager
1935 * @return integer value of corresponding key.
Brad Ebinger16417b42017-03-07 13:48:50 -08001936 *
1937 * @deprecated Doesn't support MSIM devices. Use {@link #getIntCarrierConfigForSlot} instead.
fionaxu5803ef02016-03-08 11:48:48 -08001938 */
1939 private static int getIntCarrierConfig(Context context, String key) {
1940 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
1941 Context.CARRIER_CONFIG_SERVICE);
1942 PersistableBundle b = null;
1943 if (configManager != null) {
1944 b = configManager.getConfig();
1945 }
1946 if (b != null) {
1947 return b.getInt(key);
1948 } else {
1949 // Return static default defined in CarrierConfigManager.
1950 return CarrierConfigManager.getDefaultConfig().getInt(key);
1951 }
1952 }
1953
1954 /**
Brad Ebinger16417b42017-03-07 13:48:50 -08001955 * Get the int config from carrier config manager.
1956 *
1957 * @param key config key defined in CarrierConfigManager
1958 * @return integer value of corresponding key.
1959 */
1960 private int getIntCarrierConfigForSlot(String key) {
1961 int[] subIds = SubscriptionManager.getSubId(mPhoneId);
1962 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1963 if (subIds != null && subIds.length >= 1) {
1964 subId = subIds[0];
1965 }
1966 PersistableBundle b = null;
1967 if (mConfigManager != null) {
1968 // If an invalid subId is used, this bundle will contain default values.
1969 b = mConfigManager.getConfigForSubId(subId);
1970 }
1971 if (b != null) {
1972 return b.getInt(key);
1973 } else {
1974 // Return static default defined in CarrierConfigManager.
1975 return CarrierConfigManager.getDefaultConfig().getInt(key);
1976 }
1977 }
1978
1979 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001980 * Gets the call ID from the specified incoming call broadcast intent.
1981 *
1982 * @param incomingCallIntent the incoming call broadcast intent
1983 * @return the call ID or null if the intent does not contain it
1984 */
1985 private static String getCallId(Intent incomingCallIntent) {
1986 if (incomingCallIntent == null) {
1987 return null;
1988 }
1989
1990 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
1991 }
1992
1993 /**
1994 * Gets the service type from the specified incoming call broadcast intent.
1995 *
1996 * @param incomingCallIntent the incoming call broadcast intent
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001997 * @return the session identifier or -1 if the intent does not contain it
Wink Savilleef36ef62014-06-11 08:39:38 -07001998 */
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08001999 private static int getImsSessionId(Intent incomingCallIntent) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002000 if (incomingCallIntent == null) {
2001 return (-1);
2002 }
2003
2004 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
2005 }
2006
2007 /**
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002008 * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
2009 * connection again.
Wink Savilleef36ef62014-06-11 08:39:38 -07002010 */
2011 private void checkAndThrowExceptionIfServiceUnavailable()
2012 throws ImsException {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002013 if (mImsServiceProxy == null || !mImsServiceProxy.isBinderAlive()) {
2014 createImsService();
Wink Savilleef36ef62014-06-11 08:39:38 -07002015
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002016 if (mImsServiceProxy == null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002017 throw new ImsException("Service is unavailable",
2018 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2019 }
2020 }
2021 }
2022
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002023 /**
2024 * Binds the IMS service to make/receive the call. Supports two methods of exposing an
2025 * ImsService:
2026 * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
2027 * 2) android.telephony.ims.ImsService implementation through ImsResolver.
2028 */
2029 private void createImsService() {
2030 if (!mConfigDynamicBind) {
2031 // Old method of binding
2032 Rlog.i(TAG, "Creating ImsService using ServiceManager");
2033 mImsServiceProxy = getServiceProxyCompat();
2034 } else {
2035 Rlog.i(TAG, "Creating ImsService using ImsResolver");
2036 mImsServiceProxy = getServiceProxy();
2037 }
Etan Cohend7727462014-07-12 14:54:10 -07002038 }
2039
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002040 // Deprecated method of binding with the ImsService defined in the ServiceManager.
2041 private ImsServiceProxyCompat getServiceProxyCompat() {
2042 IBinder binder = ServiceManager.checkService(IMS_SERVICE);
Wink Savilleef36ef62014-06-11 08:39:38 -07002043
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002044 if (binder != null) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002045 try {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002046 binder.linkToDeath(mDeathRecipient, 0);
Wink Savilleef36ef62014-06-11 08:39:38 -07002047 } catch (RemoteException e) {
2048 }
2049 }
2050
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002051 return new ImsServiceProxyCompat(mPhoneId, binder);
2052 }
2053
2054 // New method of binding with the ImsResolver
2055 private ImsServiceProxy getServiceProxy() {
2056 TelephonyManager tm = (TelephonyManager)
2057 mContext.getSystemService(Context.TELEPHONY_SERVICE);
2058 ImsServiceProxy serviceProxy = new ImsServiceProxy(mPhoneId, ImsFeature.MMTEL);
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002059 serviceProxy.setStatusCallback(() -> mStatusCallbacks.forEach(
2060 ImsServiceProxy.INotifyStatusChanged::notifyStatusChanged));
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002061 // Returns null if the service is not available.
2062 IImsServiceController b = tm.getImsServiceControllerAndListen(mPhoneId,
2063 ImsFeature.MMTEL, serviceProxy.getListener());
2064 if (b != null) {
2065 serviceProxy.setBinder(b.asBinder());
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002066 // Trigger the cache to be updated for feature status.
2067 serviceProxy.getFeatureStatus();
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002068 } else {
2069 Rlog.w(TAG, "getServiceProxy: b is null! Phone Id: " + mPhoneId);
2070 }
2071 return serviceProxy;
Wink Savilleef36ef62014-06-11 08:39:38 -07002072 }
2073
2074 /**
2075 * Creates a {@link ImsCallSession} with the specified call profile.
2076 * Use other methods, if applicable, instead of interacting with
2077 * {@link ImsCallSession} directly.
2078 *
2079 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2080 * @param profile a call profile to make the call
2081 */
2082 private ImsCallSession createCallSession(int serviceId,
2083 ImsCallProfile profile) throws ImsException {
2084 try {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002085 // Throws an exception if the ImsService Feature is not ready to accept commands.
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002086 return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile, null));
Wink Savilleef36ef62014-06-11 08:39:38 -07002087 } catch (RemoteException e) {
Brad Ebingerb10b61e2017-04-18 11:45:26 -07002088 Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
2089 throw new ImsException("createCallSession()", e,
2090 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2091
Wink Savilleef36ef62014-06-11 08:39:38 -07002092 }
2093 }
2094
2095 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass,
2096 ImsConnectionStateListener listener) {
2097 ImsRegistrationListenerProxy proxy =
2098 new ImsRegistrationListenerProxy(serviceClass, listener);
2099 return proxy;
2100 }
2101
Etan Cohena00c9192014-12-23 15:02:29 -08002102 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002103 Rlog.d(TAG, s);
2104 }
2105
Etan Cohena00c9192014-12-23 15:02:29 -08002106 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002107 Rlog.e(TAG, s);
2108 }
2109
Etan Cohena00c9192014-12-23 15:02:29 -08002110 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07002111 Rlog.e(TAG, s, t);
2112 }
2113
2114 /**
ram7da5a112014-07-16 20:59:27 +05302115 * Used for turning on IMS.if its off already
2116 */
Etan Cohen82f78122014-12-15 10:10:14 -08002117 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002118 checkAndThrowExceptionIfServiceUnavailable();
2119
ram7da5a112014-07-16 20:59:27 +05302120 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002121 mImsServiceProxy.turnOnIms();
ram7da5a112014-07-16 20:59:27 +05302122 } catch (RemoteException e) {
2123 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2124 }
2125 }
2126
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002127 private boolean isImsTurnOffAllowed() {
Brad Ebinger16417b42017-03-07 13:48:50 -08002128 return isTurnOffImsAllowedByPlatformForSlot()
2129 && (!isWfcEnabledByPlatformForSlot()
2130 || !isWfcEnabledByUserForSlot());
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002131 }
2132
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002133 private void setLteFeatureValues(boolean turnOn) {
2134 log("setLteFeatureValues: " + turnOn);
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002135 try {
2136 ImsConfig config = getConfigInterface();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002137 if (config != null) {
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002138 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08002139 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002140
Brad Ebinger16417b42017-03-07 13:48:50 -08002141 if (isVolteEnabledByPlatformForSlot()) {
Jack Yu57781852016-11-16 17:20:38 -08002142 boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext,
2143 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
Brad Ebinger16417b42017-03-07 13:48:50 -08002144 boolean enableViLte = turnOn && isVtEnabledByUserForSlot() &&
Jack Yu57781852016-11-16 17:20:38 -08002145 (ignoreDataEnabledChanged || isDataEnabled());
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07002146 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
2147 TelephonyManager.NETWORK_TYPE_LTE,
2148 enableViLte ? 1 : 0,
2149 mImsConfigListener);
2150 }
Etan Cohenb651fa52014-10-22 10:51:29 -07002151 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07002152 } catch (ImsException e) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002153 loge("setLteFeatureValues: exception ", e);
Etan Cohencfc784d2014-08-07 18:40:31 -07002154 }
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002155 }
2156
2157 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
2158 checkAndThrowExceptionIfServiceUnavailable();
2159
2160 // if turnOn: first set feature values then call turnOnIms()
2161 // if turnOff: only set feature values if IMS turn off is not allowed. If turn off is
2162 // allowed, first call turnOffIms() then set feature values
Etan Cohencfc784d2014-08-07 18:40:31 -07002163 if (turnOn) {
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002164 setLteFeatureValues(turnOn);
2165 log("setAdvanced4GMode: turnOnIms");
Etan Cohencfc784d2014-08-07 18:40:31 -07002166 turnOnIms();
Amit Mahajan9cba36d2016-08-11 10:17:23 -07002167 } else {
2168 if (isImsTurnOffAllowed()) {
2169 log("setAdvanced4GMode: turnOffIms");
2170 turnOffIms();
2171 }
2172 setLteFeatureValues(turnOn);
Etan Cohencfc784d2014-08-07 18:40:31 -07002173 }
2174 }
2175
ram7da5a112014-07-16 20:59:27 +05302176 /**
2177 * Used for turning off IMS completely in order to make the device CSFB'ed.
2178 * Once turned off, all calls will be over CS.
2179 */
Etan Cohen82f78122014-12-15 10:10:14 -08002180 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07002181 checkAndThrowExceptionIfServiceUnavailable();
2182
ram7da5a112014-07-16 20:59:27 +05302183 try {
Brad Ebingerb5f30c72017-02-17 14:54:31 -08002184 mImsServiceProxy.turnOffIms();
ram7da5a112014-07-16 20:59:27 +05302185 } catch (RemoteException e) {
2186 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2187 }
2188 }
2189
Naveen Kalla525c3a22017-02-06 14:46:42 -08002190 private void addToRecentDisconnectReasons(ImsReasonInfo reason) {
2191 if (reason == null) return;
2192 while (mRecentDisconnectReasons.size() >= MAX_RECENT_DISCONNECT_REASONS) {
2193 mRecentDisconnectReasons.removeFirst();
2194 }
2195 mRecentDisconnectReasons.addLast(reason);
2196 }
2197
ram7da5a112014-07-16 20:59:27 +05302198 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07002199 * Death recipient class for monitoring IMS service.
2200 */
2201 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
2202 @Override
2203 public void binderDied() {
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002204 mImsServiceProxy = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002205 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05002206 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002207 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002208 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07002209 }
2210 }
2211
2212 /**
2213 * Adapter class for {@link IImsRegistrationListener}.
2214 */
Naveen Kalla0484b732017-02-14 14:55:24 -08002215 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
Wink Savilleef36ef62014-06-11 08:39:38 -07002216 private int mServiceClass;
2217 private ImsConnectionStateListener mListener;
2218
2219 public ImsRegistrationListenerProxy(int serviceClass,
2220 ImsConnectionStateListener listener) {
2221 mServiceClass = serviceClass;
2222 mListener = listener;
2223 }
2224
2225 public boolean isSameProxy(int serviceClass) {
2226 return (mServiceClass == serviceClass);
2227 }
2228
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002229 @Deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -07002230 public void registrationConnected() {
2231 if (DBG) {
2232 log("registrationConnected ::");
2233 }
2234
2235 if (mListener != null) {
2236 mListener.onImsConnected();
2237 }
2238 }
2239
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002240 @Deprecated
Rekha Kumar14631742015-02-04 10:47:00 -08002241 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07002242 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08002243 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07002244 }
2245
2246 if (mListener != null) {
Rekha Kumar14631742015-02-04 10:47:00 -08002247 mListener.onImsProgressing();
2248 }
2249 }
2250
2251 @Override
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002252 public void registrationConnectedWithRadioTech(int imsRadioTech) {
2253 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2254 // values in ServiceState.java.
2255 if (DBG) {
2256 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
2257 }
2258
2259 if (mListener != null) {
2260 mListener.onImsConnected();
Meng Wange4414152016-12-07 16:27:15 -08002261 mListener.onImsConnected(imsRadioTech);
Omkar Kolangadea7ced642015-05-04 17:55:13 -07002262 }
2263 }
2264
2265 @Override
2266 public void registrationProgressingWithRadioTech(int imsRadioTech) {
2267 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
2268 // values in ServiceState.java.
2269 if (DBG) {
2270 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
2271 }
2272
2273 if (mListener != null) {
2274 mListener.onImsProgressing();
2275 }
2276 }
2277
2278 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08002279 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
2280 if (DBG) {
2281 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
2282 }
2283
Naveen Kalla525c3a22017-02-06 14:46:42 -08002284 addToRecentDisconnectReasons(imsReasonInfo);
2285
Rekha Kumar14631742015-02-04 10:47:00 -08002286 if (mListener != null) {
2287 mListener.onImsDisconnected(imsReasonInfo);
Wink Savilleef36ef62014-06-11 08:39:38 -07002288 }
2289 }
2290
2291 @Override
2292 public void registrationResumed() {
2293 if (DBG) {
2294 log("registrationResumed ::");
2295 }
2296
2297 if (mListener != null) {
2298 mListener.onImsResumed();
2299 }
2300 }
2301
2302 @Override
2303 public void registrationSuspended() {
2304 if (DBG) {
2305 log("registrationSuspended ::");
2306 }
2307
2308 if (mListener != null) {
2309 mListener.onImsSuspended();
2310 }
2311 }
2312
2313 @Override
2314 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
2315 log("registrationServiceCapabilityChanged :: serviceClass=" +
2316 serviceClass + ", event=" + event);
2317
2318 if (mListener != null) {
2319 mListener.onImsConnected();
2320 }
2321 }
ram7da5a112014-07-16 20:59:27 +05302322
2323 @Override
2324 public void registrationFeatureCapabilityChanged(int serviceClass,
2325 int[] enabledFeatures, int[] disabledFeatures) {
2326 log("registrationFeatureCapabilityChanged :: serviceClass=" +
2327 serviceClass);
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05002328 if (mListener != null) {
2329 mListener.onFeatureCapabilityChanged(serviceClass,
2330 enabledFeatures, disabledFeatures);
2331 }
ram7da5a112014-07-16 20:59:27 +05302332 }
2333
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07002334 @Override
2335 public void voiceMessageCountUpdate(int count) {
2336 log("voiceMessageCountUpdate :: count=" + count);
2337
2338 if (mListener != null) {
2339 mListener.onVoiceMessageCountChanged(count);
2340 }
2341 }
2342
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08002343 @Override
2344 public void registrationAssociatedUriChanged(Uri[] uris) {
2345 if (DBG) log("registrationAssociatedUriChanged ::");
2346
2347 if (mListener != null) {
2348 mListener.registrationAssociatedUriChanged(uris);
2349 }
2350 }
Meng Wange4414152016-12-07 16:27:15 -08002351
2352 @Override
2353 public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo) {
2354 if (DBG) log("registrationChangeFailed :: targetAccessTech=" + targetAccessTech +
2355 ", imsReasonInfo=" + imsReasonInfo);
2356
2357 if (mListener != null) {
2358 mListener.onRegistrationChangeFailed(targetAccessTech, imsReasonInfo);
2359 }
2360 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002361 }
Tyler Gunn4d128b62016-04-13 15:44:38 -07002362
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002363 /**
2364 * Gets the ECBM interface to request ECBM exit.
2365 *
2366 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2367 * @return the ECBM interface instance
2368 * @throws ImsException if getting the ECBM interface results in an error
2369 */
2370 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002371 if (mEcbm != null && mEcbm.isBinderAlive()) {
2372 return mEcbm;
2373 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002374
Brad Ebinger138b4a62017-06-20 16:29:50 -07002375 checkAndThrowExceptionIfServiceUnavailable();
2376 try {
2377 IImsEcbm iEcbm = mImsServiceProxy.getEcbmInterface();
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002378
Brad Ebinger138b4a62017-06-20 16:29:50 -07002379 if (iEcbm == null) {
2380 throw new ImsException("getEcbmInterface()",
2381 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002382 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002383 mEcbm = new ImsEcbm(iEcbm);
2384 } catch (RemoteException e) {
2385 throw new ImsException("getEcbmInterface()", e,
2386 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07002387 }
2388 return mEcbm;
2389 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002390
2391 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07002392 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
2393 *
2394 * @param serviceId a service id which is obtained from {@link ImsManager#open}
2395 * @return the multi-endpoint interface instance
2396 * @throws ImsException if getting the multi-endpoint interface results in an error
2397 */
2398 public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
Brad Ebinger138b4a62017-06-20 16:29:50 -07002399 if (mMultiEndpoint != null && mMultiEndpoint.isBinderAlive()) {
2400 return mMultiEndpoint;
Tyler Gunn4d128b62016-04-13 15:44:38 -07002401 }
Brad Ebinger138b4a62017-06-20 16:29:50 -07002402
2403 checkAndThrowExceptionIfServiceUnavailable();
2404 try {
2405 IImsMultiEndpoint iImsMultiEndpoint = mImsServiceProxy.getMultiEndpointInterface();
2406
2407 if (iImsMultiEndpoint == null) {
2408 throw new ImsException("getMultiEndpointInterface()",
2409 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
2410 }
2411 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
2412 } catch (RemoteException e) {
2413 throw new ImsException("getMultiEndpointInterface()", e,
2414 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
2415 }
2416
Tyler Gunn4d128b62016-04-13 15:44:38 -07002417 return mMultiEndpoint;
2418 }
2419
2420 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002421 * Resets ImsManager settings back to factory defaults.
2422 *
Brad Ebinger16417b42017-03-07 13:48:50 -08002423 * @deprecated Doesn't support MSIM devices. Use {@link #factoryResetSlot()} instead.
2424 *
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002425 * @hide
2426 */
2427 public static void factoryReset(Context context) {
2428 // Set VoLTE to default
2429 android.provider.Settings.Global.putInt(context.getContentResolver(),
2430 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
2431 ImsConfig.FeatureValueConstants.ON);
2432
2433 // Set VoWiFi to default
2434 android.provider.Settings.Global.putInt(context.getContentResolver(),
2435 android.provider.Settings.Global.WFC_IMS_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08002436 getBooleanCarrierConfig(context,
2437 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
2438 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002439
2440 // Set VoWiFi mode to default
2441 android.provider.Settings.Global.putInt(context.getContentResolver(),
2442 android.provider.Settings.Global.WFC_IMS_MODE,
fionaxu5803ef02016-03-08 11:48:48 -08002443 getIntCarrierConfig(context,
2444 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002445
2446 // Set VoWiFi roaming to default
2447 android.provider.Settings.Global.putInt(context.getContentResolver(),
2448 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08002449 getBooleanCarrierConfig(context,
2450 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
2451 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002452
2453 // Set VT to default
Pavel Zhamaitsiak92b54b22016-04-01 15:55:47 -07002454 android.provider.Settings.Global.putInt(context.getContentResolver(),
2455 android.provider.Settings.Global.VT_IMS_ENABLED,
2456 ImsConfig.FeatureValueConstants.ON);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08002457
2458 // Push settings to ImsConfig
2459 ImsManager.updateImsServiceConfig(context,
2460 SubscriptionManager.getDefaultVoicePhoneId(), true);
2461 }
Jack Yu2f102bd2015-12-28 15:31:48 -08002462
Brad Ebinger16417b42017-03-07 13:48:50 -08002463 /**
2464 * Resets ImsManager settings back to factory defaults.
2465 *
2466 * @hide
2467 */
2468 public void factoryResetSlot() {
2469 // Set VoLTE to default
2470 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2471 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
2472 ImsConfig.FeatureValueConstants.ON);
2473
2474 // Set VoWiFi to default
2475 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2476 android.provider.Settings.Global.WFC_IMS_ENABLED,
2477 getBooleanCarrierConfigForSlot(
2478 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
2479 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
2480
2481 // Set VoWiFi mode to default
2482 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2483 android.provider.Settings.Global.WFC_IMS_MODE,
2484 getIntCarrierConfigForSlot(
2485 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
2486
2487 // Set VoWiFi roaming to default
2488 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2489 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
2490 getBooleanCarrierConfigForSlot(
2491 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
2492 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
2493
2494 // Set VT to default
2495 android.provider.Settings.Global.putInt(mContext.getContentResolver(),
2496 android.provider.Settings.Global.VT_IMS_ENABLED,
2497 ImsConfig.FeatureValueConstants.ON);
2498
2499 // Push settings to ImsConfig
2500 updateImsServiceConfigForSlot(true);
2501 }
2502
Amit Mahajan24f7b162016-07-21 16:33:53 -07002503 private boolean isDataEnabled() {
2504 return SystemProperties.getBoolean(DATA_ENABLED_PROP, true);
2505 }
2506
Jack Yu643ffe42016-07-08 14:25:46 -07002507 /**
2508 * Set data enabled/disabled flag.
2509 * @param enabled True if data is enabled, otherwise disabled.
2510 */
2511 public void setDataEnabled(boolean enabled) {
2512 log("setDataEnabled: " + enabled);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002513 SystemProperties.set(DATA_ENABLED_PROP, enabled ? TRUE : FALSE);
2514 }
2515
2516 private boolean isVolteProvisioned() {
2517 return SystemProperties.getBoolean(VOLTE_PROVISIONED_PROP, true);
2518 }
2519
2520 private void setVolteProvisionedProperty(boolean provisioned) {
2521 SystemProperties.set(VOLTE_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
2522 }
2523
2524 private boolean isWfcProvisioned() {
2525 return SystemProperties.getBoolean(WFC_PROVISIONED_PROP, true);
2526 }
2527
2528 private void setWfcProvisionedProperty(boolean provisioned) {
2529 SystemProperties.set(WFC_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
2530 }
2531
2532 private boolean isVtProvisioned() {
2533 return SystemProperties.getBoolean(VT_PROVISIONED_PROP, true);
2534 }
2535
2536 private void setVtProvisionedProperty(boolean provisioned) {
2537 SystemProperties.set(VT_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
Jack Yu643ffe42016-07-08 14:25:46 -07002538 }
2539
Jack Yu2f102bd2015-12-28 15:31:48 -08002540 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2541 pw.println("ImsManager:");
2542 pw.println(" mPhoneId = " + mPhoneId);
2543 pw.println(" mConfigUpdated = " + mConfigUpdated);
Brad Ebinger14b0a9e2017-01-26 11:18:21 -08002544 pw.println(" mImsServiceProxy = " + mImsServiceProxy);
Amit Mahajan24f7b162016-07-21 16:33:53 -07002545 pw.println(" mDataEnabled = " + isDataEnabled());
Jack Yu57781852016-11-16 17:20:38 -08002546 pw.println(" ignoreDataEnabledChanged = " + getBooleanCarrierConfig(mContext,
2547 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS));
Jack Yu2f102bd2015-12-28 15:31:48 -08002548
Brad Ebinger16417b42017-03-07 13:48:50 -08002549 pw.println(" isGbaValid = " + isGbaValidForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002550 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
Brad Ebinger16417b42017-03-07 13:48:50 -08002551 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabledForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002552
Brad Ebinger16417b42017-03-07 13:48:50 -08002553 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatformForSlot());
2554 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDeviceForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002555 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
Brad Ebinger16417b42017-03-07 13:48:50 -08002556 isEnhanced4gLteModeSettingEnabledByUserForSlot());
2557 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatformForSlot());
2558 pw.println(" isVtEnabledByUser = " + isVtEnabledByUserForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002559
Brad Ebinger16417b42017-03-07 13:48:50 -08002560 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatformForSlot());
2561 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUserForSlot());
2562 pw.println(" getWfcMode = " + getWfcModeForSlot());
2563 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUserForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002564
Brad Ebinger16417b42017-03-07 13:48:50 -08002565 pw.println(" isVtProvisionedOnDevice = " + isVtProvisionedOnDeviceForSlot());
2566 pw.println(" isWfcProvisionedOnDevice = " + isWfcProvisionedOnDeviceForSlot());
Jack Yu2f102bd2015-12-28 15:31:48 -08002567 pw.flush();
2568 }
Wink Savilleef36ef62014-06-11 08:39:38 -07002569}