blob: ec70757c0e57f1ea0eeb994aac0ab4163686d19f [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;
Wink Savilleef36ef62014-06-11 08:39:38 -070023import android.os.IBinder;
Wink Savilleef36ef62014-06-11 08:39:38 -070024import android.os.Message;
Jonathan Basseri2acea6f2015-07-01 15:00:38 -070025import android.os.PersistableBundle;
Wink Savilleef36ef62014-06-11 08:39:38 -070026import android.os.RemoteException;
27import android.os.ServiceManager;
Etan Cohenaf55a402014-09-04 22:34:41 -070028import android.os.SystemProperties;
Etan Cohen82f78122014-12-15 10:10:14 -080029import android.provider.Settings;
30import android.telecom.TelecomManager;
Junda Liue7663c02015-06-23 11:16:26 -070031import android.telephony.CarrierConfigManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070032import android.telephony.Rlog;
Etan Cohen82f78122014-12-15 10:10:14 -080033import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070034import android.telephony.TelephonyManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070035
36import com.android.ims.internal.IImsCallSession;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070037import com.android.ims.internal.IImsEcbm;
38import com.android.ims.internal.IImsEcbmListener;
Tyler Gunn4d128b62016-04-13 15:44:38 -070039import com.android.ims.internal.IImsMultiEndpoint;
Wink Savilleef36ef62014-06-11 08:39:38 -070040import com.android.ims.internal.IImsRegistrationListener;
41import com.android.ims.internal.IImsService;
42import com.android.ims.internal.IImsUt;
43import com.android.ims.internal.ImsCallSession;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050044import com.android.ims.internal.IImsConfig;
45
Jack Yu2f102bd2015-12-28 15:31:48 -080046import java.io.FileDescriptor;
47import java.io.PrintWriter;
Etan Cohend7727462014-07-12 14:54:10 -070048import java.util.HashMap;
49
Wink Savilleef36ef62014-06-11 08:39:38 -070050/**
51 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
52 * the operator's IMS network. This class is the starting point for any IMS actions.
53 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
54 * <p>The APIs in this class allows you to:</p>
55 *
56 * @hide
57 */
58public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070059
Etan Cohenaf55a402014-09-04 22:34:41 -070060 /*
61 * Debug flag to override configuration flag
62 */
Etan Cohenb651fa52014-10-22 10:51:29 -070063 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
64 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070065 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
66 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080067 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
68 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070069
Wink Savilleef36ef62014-06-11 08:39:38 -070070 /**
71 * For accessing the IMS related service.
72 * Internal use only.
73 * @hide
74 */
Etan Cohend7727462014-07-12 14:54:10 -070075 private static final String IMS_SERVICE = "ims";
Wink Savilleef36ef62014-06-11 08:39:38 -070076
77 /**
78 * The result code to be sent back with the incoming call {@link PendingIntent}.
79 * @see #open(PendingIntent, ImsConnectionStateListener)
80 */
81 public static final int INCOMING_CALL_RESULT_CODE = 101;
82
83 /**
84 * Key to retrieve the call ID from an incoming call intent.
85 * @see #open(PendingIntent, ImsConnectionStateListener)
86 */
87 public static final String EXTRA_CALL_ID = "android:imsCallID";
88
89 /**
90 * Action to broadcast when ImsService is up.
91 * Internal use only.
92 * @hide
93 */
94 public static final String ACTION_IMS_SERVICE_UP =
95 "com.android.ims.IMS_SERVICE_UP";
96
97 /**
98 * Action to broadcast when ImsService is down.
99 * Internal use only.
100 * @hide
101 */
102 public static final String ACTION_IMS_SERVICE_DOWN =
103 "com.android.ims.IMS_SERVICE_DOWN";
104
105 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700106 * Action to broadcast when ImsService registration fails.
107 * Internal use only.
108 * @hide
109 */
110 public static final String ACTION_IMS_REGISTRATION_ERROR =
111 "com.android.ims.REGISTRATION_ERROR";
112
113 /**
Etan Cohend7727462014-07-12 14:54:10 -0700114 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700115 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700116 * Internal use only.
117 * @hide
118 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700119 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700120
121 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700122 * Action for the incoming call intent for the Phone app.
123 * Internal use only.
124 * @hide
125 */
126 public static final String ACTION_IMS_INCOMING_CALL =
127 "com.android.ims.IMS_INCOMING_CALL";
128
129 /**
130 * Part of the ACTION_IMS_INCOMING_CALL intents.
131 * An integer value; service identifier obtained from {@link ImsManager#open}.
132 * Internal use only.
133 * @hide
134 */
135 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
136
137 /**
138 * Part of the ACTION_IMS_INCOMING_CALL intents.
139 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
140 * The value "true" indicates that the incoming call is for USSD.
141 * Internal use only.
142 * @hide
143 */
144 public static final String EXTRA_USSD = "android:ussd";
145
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700146 /**
147 * Part of the ACTION_IMS_INCOMING_CALL intents.
148 * A boolean value; Flag to indicate whether the call is an unknown
149 * dialing call. Such calls are originated by sending commands (like
150 * AT commands) directly to modem without Android involvement.
151 * Even though they are not incoming calls, they are propagated
152 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
153 * Internal use only.
154 * @hide
155 */
Anju Mathapati9c033792015-06-16 16:33:16 -0700156 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700157
Wink Savilleef36ef62014-06-11 08:39:38 -0700158 private static final String TAG = "ImsManager";
159 private static final boolean DBG = true;
160
Wink Saville1e5a38a2014-10-23 10:24:46 -0700161 private static HashMap<Integer, ImsManager> sImsManagerInstances =
162 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700163
Wink Savilleef36ef62014-06-11 08:39:38 -0700164 private Context mContext;
Etan Cohenabbd7882014-09-26 22:35:35 -0700165 private int mPhoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700166 private IImsService mImsService = null;
167 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
168 // Ut interface for the supplementary service configuration
169 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500170 // Interface to get/set ims config items
171 private ImsConfig mConfig = null;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700172 private boolean mConfigUpdated = false;
Wink Savilleef36ef62014-06-11 08:39:38 -0700173
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800174 private ImsConfigListener mImsConfigListener;
175
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700176 // ECBM interface
177 private ImsEcbm mEcbm = null;
178
Tyler Gunn4d128b62016-04-13 15:44:38 -0700179 private ImsMultiEndpoint mMultiEndpoint = null;
180
Wink Savilleef36ef62014-06-11 08:39:38 -0700181 /**
182 * Gets a manager instance.
183 *
184 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700185 * @param phoneId the phone ID for the IMS Service
186 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700187 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700188 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700189 synchronized (sImsManagerInstances) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700190 if (sImsManagerInstances.containsKey(phoneId))
191 return sImsManagerInstances.get(phoneId);
Wink Savilleef36ef62014-06-11 08:39:38 -0700192
Etan Cohenabbd7882014-09-26 22:35:35 -0700193 ImsManager mgr = new ImsManager(context, phoneId);
194 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700195
196 return mgr;
197 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700198 }
199
Etan Cohen45b5f312014-08-19 15:55:08 -0700200 /**
201 * Returns the user configuration of Enhanced 4G LTE Mode setting
202 */
203 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Sungmin Choi2f1af952016-02-01 17:15:35 +0900204 // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true.
205 // If user changes SIM from editable mode to uneditable mode, need to return true.
206 if (!getBooleanCarrierConfig(context,
207 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) {
208 return true;
209 }
Libin.Tang@motorola.com8a6bf4b2014-10-10 15:02:41 -0500210 int enabled = android.provider.Settings.Global.getInt(
211 context.getContentResolver(),
Etan Cohenb651fa52014-10-22 10:51:29 -0700212 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
Etan Cohena00c9192014-12-23 15:02:29 -0800213 return (enabled == 1) ? true : false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700214 }
215
216 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800217 * Change persistent Enhanced 4G LTE Mode setting
218 */
219 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
220 int value = enabled ? 1 : 0;
221 android.provider.Settings.Global.putInt(
222 context.getContentResolver(),
223 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
224
225 if (isNonTtyOrTtyOnVolteEnabled(context)) {
226 ImsManager imsManager = ImsManager.getInstance(context,
227 SubscriptionManager.getDefaultVoicePhoneId());
228 if (imsManager != null) {
229 try {
230 imsManager.setAdvanced4GMode(enabled);
231 } catch (ImsException ie) {
232 // do nothing
233 }
234 }
235 }
236 }
237
238 /**
239 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
240 * supported.
241 */
242 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700243 if (getBooleanCarrierConfig(context,
fionaxu5803ef02016-03-08 11:48:48 -0800244 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800245 return true;
246 }
247
248 return Settings.Secure.getInt(context.getContentResolver(),
249 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
250 == TelecomManager.TTY_MODE_OFF;
251 }
252
253 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700254 * Returns a platform configuration for VoLTE which may override the user setting.
Etan Cohen45b5f312014-08-19 15:55:08 -0700255 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700256 public static boolean isVolteEnabledByPlatform(Context context) {
Etan Cohenb651fa52014-10-22 10:51:29 -0700257 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
258 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
Etan Cohenaf55a402014-09-04 22:34:41 -0700259 return true;
260 }
261
Etan Cohenb5388a32014-11-26 11:57:47 -0800262 return context.getResources().getBoolean(
Junda Liue7663c02015-06-23 11:16:26 -0700263 com.android.internal.R.bool.config_device_volte_available)
264 && getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700265 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
266 && isGbaValid(context);
Etan Cohenb5388a32014-11-26 11:57:47 -0800267 }
268
269 /*
270 * Indicates whether VoLTE is provisioned on device
271 */
272 public static boolean isVolteProvisionedOnDevice(Context context) {
273 boolean isProvisioned = true;
Junda Liue7663c02015-06-23 11:16:26 -0700274 if (getBooleanCarrierConfig(context,
275 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Etan Cohenb5388a32014-11-26 11:57:47 -0800276 isProvisioned = false; // disable on any error
277 ImsManager mgr = ImsManager.getInstance(context,
Jonathan Basserid7133652015-04-07 19:54:24 -0700278 SubscriptionManager.getDefaultVoicePhoneId());
Etan Cohenb5388a32014-11-26 11:57:47 -0800279 if (mgr != null) {
280 try {
281 ImsConfig config = mgr.getConfigInterface();
282 if (config != null) {
283 isProvisioned = config.getVolteProvisioned();
284 }
285 } catch (ImsException ie) {
286 // do nothing
287 }
288 }
289 }
290
291 return isProvisioned;
Etan Cohenb651fa52014-10-22 10:51:29 -0700292 }
293
Etan Cohenea2b5832014-10-23 18:50:35 -0700294 /**
295 * Returns a platform configuration for VT which may override the user setting.
296 *
297 * Note: VT presumes that VoLTE is enabled (these are configuration settings
298 * which must be done correctly).
299 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700300 public static boolean isVtEnabledByPlatform(Context context) {
Etan Cohenea2b5832014-10-23 18:50:35 -0700301 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
302 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
303 return true;
304 }
305
Etan Cohenb651fa52014-10-22 10:51:29 -0700306 return
307 context.getResources().getBoolean(
308 com.android.internal.R.bool.config_device_vt_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700309 getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700310 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) &&
311 isGbaValid(context);
Etan Cohen45b5f312014-08-19 15:55:08 -0700312 }
313
Etan Cohena00c9192014-12-23 15:02:29 -0800314 /**
Etan Cohena7d32e82015-05-04 18:02:09 -0700315 * Returns the user configuration of VT setting
316 */
317 public static boolean isVtEnabledByUser(Context context) {
318 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
319 android.provider.Settings.Global.VT_IMS_ENABLED,
320 ImsConfig.FeatureValueConstants.ON);
321 return (enabled == 1) ? true : false;
322 }
323
324 /**
325 * Change persistent VT enabled setting
326 */
327 public static void setVtSetting(Context context, boolean enabled) {
328 int value = enabled ? 1 : 0;
329 android.provider.Settings.Global.putInt(context.getContentResolver(),
330 android.provider.Settings.Global.VT_IMS_ENABLED, value);
331
332 ImsManager imsManager = ImsManager.getInstance(context,
333 SubscriptionManager.getDefaultVoicePhoneId());
334 if (imsManager != null) {
335 try {
336 ImsConfig config = imsManager.getConfigInterface();
337 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
338 TelephonyManager.NETWORK_TYPE_LTE,
339 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800340 : ImsConfig.FeatureValueConstants.OFF,
341 imsManager.mImsConfigListener);
Etan Cohena7d32e82015-05-04 18:02:09 -0700342
343 if (enabled) {
344 imsManager.turnOnIms();
Pavel Zhamaitsiak4ca0cde2015-12-22 16:51:57 -0800345 } else if (getBooleanCarrierConfig(context,
346 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
347 && (!isVolteEnabledByPlatform(context)
Etan Cohena7d32e82015-05-04 18:02:09 -0700348 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
349 log("setVtSetting() : imsServiceAllowTurnOff -> turnOffIms");
350 imsManager.turnOffIms();
351 }
352 } catch (ImsException e) {
353 loge("setVtSetting(): " + e);
354 }
355 }
356 }
357
358 /**
Etan Cohena00c9192014-12-23 15:02:29 -0800359 * Returns the user configuration of WFC setting
360 */
361 public static boolean isWfcEnabledByUser(Context context) {
362 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
363 android.provider.Settings.Global.WFC_IMS_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800364 getBooleanCarrierConfig(context,
365 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
366 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800367 return (enabled == 1) ? true : false;
368 }
369
370 /**
371 * Change persistent WFC enabled setting
372 */
373 public static void setWfcSetting(Context context, boolean enabled) {
374 int value = enabled ? 1 : 0;
375 android.provider.Settings.Global.putInt(context.getContentResolver(),
376 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
377
378 ImsManager imsManager = ImsManager.getInstance(context,
379 SubscriptionManager.getDefaultVoicePhoneId());
380 if (imsManager != null) {
381 try {
382 ImsConfig config = imsManager.getConfigInterface();
Etan Cohena00c9192014-12-23 15:02:29 -0800383 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
Nathan Harold3a99f782015-07-24 15:02:34 -0700384 TelephonyManager.NETWORK_TYPE_IWLAN,
Etan Cohena00c9192014-12-23 15:02:29 -0800385 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800386 : ImsConfig.FeatureValueConstants.OFF,
387 imsManager.mImsConfigListener);
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800388
389 if (enabled) {
390 imsManager.turnOnIms();
Junda Liue7663c02015-06-23 11:16:26 -0700391 } else if (getBooleanCarrierConfig(context,
392 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800393 && (!isVolteEnabledByPlatform(context)
394 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
395 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
396 imsManager.turnOffIms();
397 }
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700398
399 // Force IMS to register over LTE when turning off WFC
400 setWfcModeInternal(context, enabled
401 ? getWfcMode(context)
402 : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED);
Etan Cohena00c9192014-12-23 15:02:29 -0800403 } catch (ImsException e) {
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800404 loge("setWfcSetting(): " + e);
Etan Cohena00c9192014-12-23 15:02:29 -0800405 }
406 }
407 }
408
409 /**
410 * Returns the user configuration of WFC modem setting
411 */
412 public static int getWfcMode(Context context) {
413 int setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
fionaxu5803ef02016-03-08 11:48:48 -0800414 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context,
415 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
Etan Cohena00c9192014-12-23 15:02:29 -0800416 if (DBG) log("getWfcMode - setting=" + setting);
417 return setting;
418 }
419
420 /**
421 * Returns the user configuration of WFC modem setting
422 */
423 public static void setWfcMode(Context context, int wfcMode) {
424 if (DBG) log("setWfcMode - setting=" + wfcMode);
425 android.provider.Settings.Global.putInt(context.getContentResolver(),
426 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
427
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700428 setWfcModeInternal(context, wfcMode);
429 }
430
431 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800432 final ImsManager imsManager = ImsManager.getInstance(context,
433 SubscriptionManager.getDefaultVoicePhoneId());
434 if (imsManager != null) {
435 final int value = wfcMode;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700436 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800437 public void run() {
438 try {
439 imsManager.getConfigInterface().setProvisionedValue(
440 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
441 value);
442 } catch (ImsException e) {
443 // do nothing
444 }
445 }
446 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700447 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800448 }
449 }
450
451 /**
452 * Returns the user configuration of WFC roaming setting
453 */
454 public static boolean isWfcRoamingEnabledByUser(Context context) {
455 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
456 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800457 getBooleanCarrierConfig(context,
458 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
459 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800460 return (enabled == 1) ? true : false;
461 }
462
463 /**
464 * Change persistent WFC roaming enabled setting
465 */
466 public static void setWfcRoamingSetting(Context context, boolean enabled) {
Etan Cohena00c9192014-12-23 15:02:29 -0800467 android.provider.Settings.Global.putInt(context.getContentResolver(),
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700468 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -0800469 enabled ? ImsConfig.FeatureValueConstants.ON
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700470 : ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800471
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700472 setWfcRoamingSettingInternal(context, enabled);
473 }
474
475 private static void setWfcRoamingSettingInternal(Context context, boolean enabled) {
Etan Cohena00c9192014-12-23 15:02:29 -0800476 final ImsManager imsManager = ImsManager.getInstance(context,
477 SubscriptionManager.getDefaultVoicePhoneId());
478 if (imsManager != null) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700479 final int value = enabled
480 ? ImsConfig.FeatureValueConstants.ON
481 : ImsConfig.FeatureValueConstants.OFF;
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700482 Thread thread = new Thread(new Runnable() {
Etan Cohena00c9192014-12-23 15:02:29 -0800483 public void run() {
484 try {
485 imsManager.getConfigInterface().setProvisionedValue(
486 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING,
487 value);
488 } catch (ImsException e) {
489 // do nothing
490 }
491 }
492 });
Pavel Zhamaitsiak47aeacf2016-03-30 18:54:55 -0700493 thread.start();
Etan Cohena00c9192014-12-23 15:02:29 -0800494 }
495 }
496
497 /**
498 * Returns a platform configuration for WFC which may override the user
499 * setting. Note: WFC presumes that VoLTE is enabled (these are
500 * configuration settings which must be done correctly).
501 */
502 public static boolean isWfcEnabledByPlatform(Context context) {
503 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
504 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
505 return true;
506 }
507
508 return
509 context.getResources().getBoolean(
510 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700511 getBooleanCarrierConfig(context,
Pavel Zhamaitsiak57911d12015-10-20 14:26:34 -0700512 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) &&
513 isGbaValid(context);
514 }
515
516 /**
517 * If carrier requires that IMS is only available if GBA capable SIM is used,
518 * then this function checks GBA bit in EF IST.
519 *
520 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7).
521 */
522 private static boolean isGbaValid(Context context) {
523 if (getBooleanCarrierConfig(context,
524 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) {
525 final TelephonyManager telephonyManager = TelephonyManager.getDefault();
526 String efIst = telephonyManager.getIsimIst();
527 if (efIst == null) {
528 loge("ISF is NULL");
529 return true;
530 }
531 boolean result = efIst != null && efIst.length() > 1 &&
532 (0x02 & (byte)efIst.charAt(1)) != 0;
533 if (DBG) log("GBA capable=" + result + ", ISF=" + efIst);
534 return result;
535 }
536 return true;
Etan Cohena00c9192014-12-23 15:02:29 -0800537 }
538
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700539 /**
540 * Sync carrier config and user settings with ImsConfig.
541 *
542 * @param context for the manager object
543 * @param phoneId phone id
544 * @param force update
545 */
546 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) {
Pavel Zhamaitsiakfc202992016-03-29 18:07:38 -0700547 if (!force) {
548 if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) {
549 log("updateImsServiceConfig: SIM not ready");
550 // Don't disable IMS if SIM is not ready
551 return;
552 }
553 }
554
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700555 final ImsManager imsManager = ImsManager.getInstance(context, phoneId);
556 if (imsManager != null && (!imsManager.mConfigUpdated || force)) {
557 try {
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800558 boolean isImsUsed = imsManager.updateVolteFeatureValue();
559 isImsUsed |= imsManager.updateVideoCallFeatureValue();
560 isImsUsed |= imsManager.updateWfcFeatureAndProvisionedValues();
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700561
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800562 if (isImsUsed || !getBooleanCarrierConfig(context,
563 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)) {
564 // Turn on IMS if it is used.
565 // Also, if turning off is not allowed for current carrier,
566 // we need to turn IMS on because it might be turned off before
567 // phone switched to current carrier.
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700568 imsManager.turnOnIms();
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800569 } else {
570 // Turn off IMS if it is not used AND turning off is allowed for carrier.
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700571 imsManager.turnOffIms();
572 }
573
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700574 imsManager.mConfigUpdated = true;
575 } catch (ImsException e) {
576 loge("updateImsServiceConfig: " + e);
577 imsManager.mConfigUpdated = false;
578 }
579 }
580 }
581
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700582 /**
583 * Update VoLTE config
584 * @return whether feature is On
585 * @throws ImsException
586 */
587 private boolean updateVolteFeatureValue() throws ImsException {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700588 boolean available = isVolteEnabledByPlatform(mContext);
589 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(mContext);
590 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(mContext);
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800591 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700592
593 log("updateVolteFeatureValue: available = " + available
594 + ", enabled = " + enabled
595 + ", nonTTY = " + isNonTty);
596
597 getConfigInterface().setFeatureValue(
598 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
599 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800600 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700601 ImsConfig.FeatureValueConstants.ON :
602 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800603 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700604
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800605 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700606 }
607
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700608 /**
609 * Update VC config
610 * @return whether feature is On
611 * @throws ImsException
612 */
613 private boolean updateVideoCallFeatureValue() throws ImsException {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700614 boolean available = isVtEnabledByPlatform(mContext);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700615 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(mContext) &&
Pavel Zhamaitsiak92b54b22016-04-01 15:55:47 -0700616 isVtEnabledByUser(mContext);
Omkar Kolangadec0f450d2016-02-11 20:59:48 +0530617 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(mContext);
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800618 boolean isFeatureOn = available && enabled && isNonTty;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700619
620 log("updateVideoCallFeatureValue: available = " + available
621 + ", enabled = " + enabled
622 + ", nonTTY = " + isNonTty);
623
624 getConfigInterface().setFeatureValue(
625 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
626 TelephonyManager.NETWORK_TYPE_LTE,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800627 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700628 ImsConfig.FeatureValueConstants.ON :
629 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800630 mImsConfigListener);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700631
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800632 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700633 }
634
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700635 /**
636 * Update WFC config
637 * @return whether feature is On
638 * @throws ImsException
639 */
640 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700641 boolean available = isWfcEnabledByPlatform(mContext);
642 boolean enabled = isWfcEnabledByUser(mContext);
643 int mode = getWfcMode(mContext);
644 boolean roaming = isWfcRoamingEnabledByUser(mContext);
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800645 boolean isFeatureOn = available && enabled;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700646
647 log("updateWfcFeatureAndProvisionedValues: available = " + available
648 + ", enabled = " + enabled
649 + ", mode = " + mode
650 + ", roaming = " + roaming);
651
652 getConfigInterface().setFeatureValue(
Pavel Zhamaitsiake6f99432015-09-11 10:29:30 -0700653 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
654 TelephonyManager.NETWORK_TYPE_IWLAN,
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800655 isFeatureOn ?
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700656 ImsConfig.FeatureValueConstants.ON :
657 ImsConfig.FeatureValueConstants.OFF,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800658 mImsConfigListener);
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700659
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800660 if (!isFeatureOn) {
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700661 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
662 roaming = false;
663 }
664 setWfcModeInternal(mContext, mode);
665 setWfcRoamingSettingInternal(mContext, roaming);
Pavel Zhamaitsiakdc16e452015-09-08 17:12:06 -0700666
Pavel Zhamaitsiak9510b1c2015-12-18 11:30:49 -0800667 return isFeatureOn;
Pavel Zhamaitsiak8ca52ff2015-09-04 17:08:35 -0700668 }
669
Etan Cohenabbd7882014-09-26 22:35:35 -0700670 private ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700671 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -0700672 mPhoneId = phoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700673 createImsService(true);
674 }
675
Etan Cohenf4311122015-02-26 17:47:13 -0800676 /*
677 * Returns a flag indicating whether the IMS service is available.
678 */
679 public boolean isServiceAvailable() {
680 if (mImsService != null) {
681 return true;
682 }
683
684 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
685 if (binder != null) {
686 return true;
687 }
688
689 return false;
690 }
691
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -0800692 public void setImsConfigListener(ImsConfigListener listener) {
693 mImsConfigListener = listener;
694 }
695
Wink Savilleef36ef62014-06-11 08:39:38 -0700696 /**
697 * Opens the IMS service for making calls and/or receiving generic IMS calls.
698 * The caller may make subsquent calls through {@link #makeCall}.
699 * The IMS service will register the device to the operator's network with the credentials
700 * (from ISIM) periodically in order to receive calls from the operator's network.
701 * When the IMS service receives a new call, it will send out an intent with
702 * the provided action string.
703 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
704 *
705 * @param serviceClass a service class specified in {@link ImsServiceClass}
706 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
707 * @param incomingCallPendingIntent When an incoming call is received,
708 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
709 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
710 * as the result code and the intent to fill in the call ID; It cannot be null
711 * @param listener To listen to IMS registration events; It cannot be null
712 * @return identifier (greater than 0) for the specified service
713 * @throws NullPointerException if {@code incomingCallPendingIntent}
714 * or {@code listener} is null
715 * @throws ImsException if calling the IMS service results in an error
716 * @see #getCallId
717 * @see #getServiceId
718 */
719 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
720 ImsConnectionStateListener listener) throws ImsException {
721 checkAndThrowExceptionIfServiceUnavailable();
722
723 if (incomingCallPendingIntent == null) {
724 throw new NullPointerException("incomingCallPendingIntent can't be null");
725 }
726
727 if (listener == null) {
728 throw new NullPointerException("listener can't be null");
729 }
730
731 int result = 0;
732
733 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700734 result = mImsService.open(mPhoneId, serviceClass, incomingCallPendingIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -0700735 createRegistrationListenerProxy(serviceClass, listener));
736 } catch (RemoteException e) {
737 throw new ImsException("open()", e,
738 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
739 }
740
741 if (result <= 0) {
742 // If the return value is a minus value,
743 // it means that an error occurred in the service.
744 // So, it needs to convert to the reason code specified in ImsReasonInfo.
745 throw new ImsException("open()", (result * (-1)));
746 }
747
748 return result;
749 }
750
751 /**
Pavel Zhamaitsiakce410172016-04-15 10:55:56 -0700752 * Adds registration listener to the IMS service.
753 *
754 * @param serviceClass a service class specified in {@link ImsServiceClass}
755 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
756 * @param listener To listen to IMS registration events; It cannot be null
757 * @throws NullPointerException if {@code listener} is null
758 * @throws ImsException if calling the IMS service results in an error
759 */
760 public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener)
761 throws ImsException {
762 checkAndThrowExceptionIfServiceUnavailable();
763
764 if (listener == null) {
765 throw new NullPointerException("listener can't be null");
766 }
767
768 try {
769 mImsService.addRegistrationListener(mPhoneId, serviceClass,
770 createRegistrationListenerProxy(serviceClass, listener));
771 } catch (RemoteException e) {
772 throw new ImsException("addRegistrationListener()", e,
773 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
774 }
775 }
776
777 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700778 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
779 * All the resources that were allocated to the service are also released.
780 *
781 * @param serviceId a service id to be closed which is obtained from {@link ImsManager#open}
782 * @throws ImsException if calling the IMS service results in an error
783 */
784 public void close(int serviceId) throws ImsException {
785 checkAndThrowExceptionIfServiceUnavailable();
786
787 try {
788 mImsService.close(serviceId);
789 } catch (RemoteException e) {
790 throw new ImsException("close()", e,
791 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
792 } finally {
793 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500794 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700795 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -0700796 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700797 }
798 }
799
800 /**
801 * Gets the configuration interface to provision / withdraw the supplementary service settings.
802 *
803 * @param serviceId a service id which is obtained from {@link ImsManager#open}
804 * @return the Ut interface instance
805 * @throws ImsException if getting the Ut interface results in an error
806 */
807 public ImsUtInterface getSupplementaryServiceConfiguration(int serviceId)
808 throws ImsException {
809 // FIXME: manage the multiple Ut interfaces based on the service id
810 if (mUt == null) {
811 checkAndThrowExceptionIfServiceUnavailable();
812
813 try {
814 IImsUt iUt = mImsService.getUtInterface(serviceId);
815
816 if (iUt == null) {
817 throw new ImsException("getSupplementaryServiceConfiguration()",
818 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
819 }
820
821 mUt = new ImsUt(iUt);
822 } catch (RemoteException e) {
823 throw new ImsException("getSupplementaryServiceConfiguration()", e,
824 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
825 }
826 }
827
828 return mUt;
829 }
830
831 /**
832 * Checks if the IMS service has successfully registered to the IMS network
833 * with the specified service & call type.
834 *
835 * @param serviceId a service id which is obtained from {@link ImsManager#open}
836 * @param serviceType a service type that is specified in {@link ImsCallProfile}
837 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
838 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
839 * @param callType a call type that is specified in {@link ImsCallProfile}
840 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
841 * {@link ImsCallProfile#CALL_TYPE_VOICE}
842 * {@link ImsCallProfile#CALL_TYPE_VT}
843 * {@link ImsCallProfile#CALL_TYPE_VS}
844 * @return true if the specified service id is connected to the IMS network;
845 * false otherwise
846 * @throws ImsException if calling the IMS service results in an error
847 */
848 public boolean isConnected(int serviceId, int serviceType, int callType)
849 throws ImsException {
850 checkAndThrowExceptionIfServiceUnavailable();
851
852 try {
853 return mImsService.isConnected(serviceId, serviceType, callType);
854 } catch (RemoteException e) {
855 throw new ImsException("isServiceConnected()", e,
856 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
857 }
858 }
859
860 /**
861 * Checks if the specified IMS service is opend.
862 *
863 * @param serviceId a service id which is obtained from {@link ImsManager#open}
864 * @return true if the specified service id is opened; false otherwise
865 * @throws ImsException if calling the IMS service results in an error
866 */
867 public boolean isOpened(int serviceId) throws ImsException {
868 checkAndThrowExceptionIfServiceUnavailable();
869
870 try {
871 return mImsService.isOpened(serviceId);
872 } catch (RemoteException e) {
873 throw new ImsException("isOpened()", e,
874 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
875 }
876 }
877
878 /**
879 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
880 *
881 * @param serviceId a service id which is obtained from {@link ImsManager#open}
882 * @param serviceType a service type that is specified in {@link ImsCallProfile}
883 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
884 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
885 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
886 * @param callType a call type that is specified in {@link ImsCallProfile}
887 * {@link ImsCallProfile#CALL_TYPE_VOICE}
888 * {@link ImsCallProfile#CALL_TYPE_VT}
889 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
890 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
891 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
892 * {@link ImsCallProfile#CALL_TYPE_VS}
893 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
894 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
895 * @return a {@link ImsCallProfile} object
896 * @throws ImsException if calling the IMS service results in an error
897 */
898 public ImsCallProfile createCallProfile(int serviceId,
899 int serviceType, int callType) throws ImsException {
900 checkAndThrowExceptionIfServiceUnavailable();
901
902 try {
903 return mImsService.createCallProfile(serviceId, serviceType, callType);
904 } catch (RemoteException e) {
905 throw new ImsException("createCallProfile()", e,
906 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
907 }
908 }
909
910 /**
911 * Creates a {@link ImsCall} to make a call.
912 *
913 * @param serviceId a service id which is obtained from {@link ImsManager#open}
914 * @param profile a call profile to make the call
915 * (it contains service type, call type, media information, etc.)
916 * @param participants participants to invite the conference call
917 * @param listener listen to the call events from {@link ImsCall}
918 * @return a {@link ImsCall} object
919 * @throws ImsException if calling the IMS service results in an error
920 */
921 public ImsCall makeCall(int serviceId, ImsCallProfile profile, String[] callees,
922 ImsCall.Listener listener) throws ImsException {
923 if (DBG) {
924 log("makeCall :: serviceId=" + serviceId
925 + ", profile=" + profile + ", callees=" + callees);
926 }
927
928 checkAndThrowExceptionIfServiceUnavailable();
929
930 ImsCall call = new ImsCall(mContext, profile);
931
932 call.setListener(listener);
933 ImsCallSession session = createCallSession(serviceId, profile);
934
935 if ((callees != null) && (callees.length == 1)) {
936 call.start(session, callees[0]);
937 } else {
938 call.start(session, callees);
939 }
940
941 return call;
942 }
943
944 /**
945 * Creates a {@link ImsCall} to take an incoming call.
946 *
947 * @param serviceId a service id which is obtained from {@link ImsManager#open}
948 * @param incomingCallIntent the incoming call broadcast intent
949 * @param listener to listen to the call events from {@link ImsCall}
950 * @return a {@link ImsCall} object
951 * @throws ImsException if calling the IMS service results in an error
952 */
953 public ImsCall takeCall(int serviceId, Intent incomingCallIntent,
954 ImsCall.Listener listener) throws ImsException {
955 if (DBG) {
956 log("takeCall :: serviceId=" + serviceId
957 + ", incomingCall=" + incomingCallIntent);
958 }
959
960 checkAndThrowExceptionIfServiceUnavailable();
961
962 if (incomingCallIntent == null) {
963 throw new ImsException("Can't retrieve session with null intent",
964 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
965 }
966
967 int incomingServiceId = getServiceId(incomingCallIntent);
968
969 if (serviceId != incomingServiceId) {
970 throw new ImsException("Service id is mismatched in the incoming call intent",
971 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
972 }
973
974 String callId = getCallId(incomingCallIntent);
975
976 if (callId == null) {
977 throw new ImsException("Call ID missing in the incoming call intent",
978 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
979 }
980
981 try {
982 IImsCallSession session = mImsService.getPendingCallSession(serviceId, callId);
983
984 if (session == null) {
985 throw new ImsException("No pending session for the call",
986 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
987 }
988
989 ImsCall call = new ImsCall(mContext, session.getCallProfile());
990
991 call.attachSession(new ImsCallSession(session));
992 call.setListener(listener);
993
994 return call;
995 } catch (Throwable t) {
996 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
997 }
998 }
999
1000 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001001 * Gets the config interface to get/set service/capability parameters.
1002 *
1003 * @return the ImsConfig instance.
1004 * @throws ImsException if getting the setting interface results in an error.
1005 */
1006 public ImsConfig getConfigInterface() throws ImsException {
1007
1008 if (mConfig == null) {
1009 checkAndThrowExceptionIfServiceUnavailable();
1010
1011 try {
Etan Cohenabbd7882014-09-26 22:35:35 -07001012 IImsConfig config = mImsService.getConfigInterface(mPhoneId);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001013 if (config == null) {
1014 throw new ImsException("getConfigInterface()",
1015 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
1016 }
Libin.Tang@motorola.com54953c72014-08-07 15:02:08 -05001017 mConfig = new ImsConfig(config, mContext);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001018 } catch (RemoteException e) {
1019 throw new ImsException("getConfigInterface()", e,
1020 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1021 }
1022 }
1023 if (DBG) log("getConfigInterface(), mConfig= " + mConfig);
1024 return mConfig;
1025 }
1026
Etan Cohen82f78122014-12-15 10:10:14 -08001027 public void setUiTTYMode(Context context, int serviceId, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301028 throws ImsException {
1029
Etan Cohen82f78122014-12-15 10:10:14 -08001030 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301031
Etan Cohen82f78122014-12-15 10:10:14 -08001032 try {
1033 mImsService.setUiTTYMode(serviceId, uiTtyMode, onComplete);
1034 } catch (RemoteException e) {
1035 throw new ImsException("setTTYMode()", e,
1036 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1037 }
1038
Junda Liue7663c02015-06-23 11:16:26 -07001039 if (!getBooleanCarrierConfig(context,
1040 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -08001041 setAdvanced4GMode((uiTtyMode == TelecomManager.TTY_MODE_OFF) &&
1042 isEnhanced4gLteModeSettingEnabledByUser(context));
1043 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +05301044 }
1045
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001046 /**
Junda Liue7663c02015-06-23 11:16:26 -07001047 * Get the boolean config from carrier config manager.
1048 *
1049 * @param context the context to get carrier service
1050 * @param key config key defined in CarrierConfigManager
1051 * @return boolean value of corresponding key.
1052 */
1053 private static boolean getBooleanCarrierConfig(Context context, String key) {
1054 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
1055 Context.CARRIER_CONFIG_SERVICE);
Jonathan Basseri2acea6f2015-07-01 15:00:38 -07001056 PersistableBundle b = null;
Junda Liue7663c02015-06-23 11:16:26 -07001057 if (configManager != null) {
Jonathan Basseri2acea6f2015-07-01 15:00:38 -07001058 b = configManager.getConfig();
1059 }
1060 if (b != null) {
1061 return b.getBoolean(key);
Junda Liue7663c02015-06-23 11:16:26 -07001062 } else {
1063 // Return static default defined in CarrierConfigManager.
1064 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
1065 }
1066 }
1067
1068 /**
fionaxu5803ef02016-03-08 11:48:48 -08001069 * Get the int config from carrier config manager.
1070 *
1071 * @param context the context to get carrier service
1072 * @param key config key defined in CarrierConfigManager
1073 * @return integer value of corresponding key.
1074 */
1075 private static int getIntCarrierConfig(Context context, String key) {
1076 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
1077 Context.CARRIER_CONFIG_SERVICE);
1078 PersistableBundle b = null;
1079 if (configManager != null) {
1080 b = configManager.getConfig();
1081 }
1082 if (b != null) {
1083 return b.getInt(key);
1084 } else {
1085 // Return static default defined in CarrierConfigManager.
1086 return CarrierConfigManager.getDefaultConfig().getInt(key);
1087 }
1088 }
1089
1090 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001091 * Gets the call ID from the specified incoming call broadcast intent.
1092 *
1093 * @param incomingCallIntent the incoming call broadcast intent
1094 * @return the call ID or null if the intent does not contain it
1095 */
1096 private static String getCallId(Intent incomingCallIntent) {
1097 if (incomingCallIntent == null) {
1098 return null;
1099 }
1100
1101 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
1102 }
1103
1104 /**
1105 * Gets the service type from the specified incoming call broadcast intent.
1106 *
1107 * @param incomingCallIntent the incoming call broadcast intent
1108 * @return the service identifier or -1 if the intent does not contain it
1109 */
1110 private static int getServiceId(Intent incomingCallIntent) {
1111 if (incomingCallIntent == null) {
1112 return (-1);
1113 }
1114
1115 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
1116 }
1117
1118 /**
1119 * Binds the IMS service only if the service is not created.
1120 */
1121 private void checkAndThrowExceptionIfServiceUnavailable()
1122 throws ImsException {
1123 if (mImsService == null) {
1124 createImsService(true);
1125
1126 if (mImsService == null) {
1127 throw new ImsException("Service is unavailable",
1128 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1129 }
1130 }
1131 }
1132
Etan Cohenabbd7882014-09-26 22:35:35 -07001133 private static String getImsServiceName(int phoneId) {
1134 // TODO: MSIM implementation needs to decide on service name as a function of phoneId
Etan Cohend7727462014-07-12 14:54:10 -07001135 return IMS_SERVICE;
1136 }
1137
Wink Savilleef36ef62014-06-11 08:39:38 -07001138 /**
1139 * Binds the IMS service to make/receive the call.
1140 */
1141 private void createImsService(boolean checkService) {
1142 if (checkService) {
Etan Cohenabbd7882014-09-26 22:35:35 -07001143 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -07001144
1145 if (binder == null) {
1146 return;
1147 }
1148 }
1149
Etan Cohenabbd7882014-09-26 22:35:35 -07001150 IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -07001151
1152 if (b != null) {
1153 try {
1154 b.linkToDeath(mDeathRecipient, 0);
1155 } catch (RemoteException e) {
1156 }
1157 }
1158
1159 mImsService = IImsService.Stub.asInterface(b);
1160 }
1161
1162 /**
1163 * Creates a {@link ImsCallSession} with the specified call profile.
1164 * Use other methods, if applicable, instead of interacting with
1165 * {@link ImsCallSession} directly.
1166 *
1167 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1168 * @param profile a call profile to make the call
1169 */
1170 private ImsCallSession createCallSession(int serviceId,
1171 ImsCallProfile profile) throws ImsException {
1172 try {
1173 return new ImsCallSession(mImsService.createCallSession(serviceId, profile, null));
1174 } catch (RemoteException e) {
1175 return null;
1176 }
1177 }
1178
1179 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass,
1180 ImsConnectionStateListener listener) {
1181 ImsRegistrationListenerProxy proxy =
1182 new ImsRegistrationListenerProxy(serviceClass, listener);
1183 return proxy;
1184 }
1185
Etan Cohena00c9192014-12-23 15:02:29 -08001186 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001187 Rlog.d(TAG, s);
1188 }
1189
Etan Cohena00c9192014-12-23 15:02:29 -08001190 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001191 Rlog.e(TAG, s);
1192 }
1193
Etan Cohena00c9192014-12-23 15:02:29 -08001194 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -07001195 Rlog.e(TAG, s, t);
1196 }
1197
1198 /**
ram7da5a112014-07-16 20:59:27 +05301199 * Used for turning on IMS.if its off already
1200 */
Etan Cohen82f78122014-12-15 10:10:14 -08001201 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07001202 checkAndThrowExceptionIfServiceUnavailable();
1203
ram7da5a112014-07-16 20:59:27 +05301204 try {
Etan Cohenabbd7882014-09-26 22:35:35 -07001205 mImsService.turnOnIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05301206 } catch (RemoteException e) {
1207 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1208 }
1209 }
1210
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001211 private boolean isImsTurnOffAllowed() {
1212 return getBooleanCarrierConfig(mContext,
1213 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
1214 && (!isWfcEnabledByPlatform(mContext)
1215 || !isWfcEnabledByUser(mContext));
1216 }
1217
Etan Cohen82f78122014-12-15 10:10:14 -08001218 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
Etan Cohencfc784d2014-08-07 18:40:31 -07001219 checkAndThrowExceptionIfServiceUnavailable();
1220
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001221 try {
1222 ImsConfig config = getConfigInterface();
1223 if (config != null && (turnOn || !isImsTurnOffAllowed())) {
1224 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Pavel Zhamaitsiakf4b90322016-01-26 14:34:09 -08001225 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
Pavel Zhamaitsiakff29b9d2016-04-15 12:16:57 -07001226
1227 if (isVtEnabledByPlatform(mContext)) {
1228 boolean enableViLte = turnOn && isVtEnabledByUser(mContext);
1229 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
1230 TelephonyManager.NETWORK_TYPE_LTE,
1231 enableViLte ? 1 : 0,
1232 mImsConfigListener);
1233 }
Etan Cohenb651fa52014-10-22 10:51:29 -07001234 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001235 } catch (ImsException e) {
1236 log("setAdvanced4GMode() : " + e);
Etan Cohencfc784d2014-08-07 18:40:31 -07001237 }
Etan Cohencfc784d2014-08-07 18:40:31 -07001238 if (turnOn) {
1239 turnOnIms();
Omkar Kolangade75f3ca32014-10-24 11:10:52 -07001240 } else if (isImsTurnOffAllowed()) {
Etan Cohencfc784d2014-08-07 18:40:31 -07001241 log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms");
1242 turnOffIms();
1243 }
1244 }
1245
ram7da5a112014-07-16 20:59:27 +05301246 /**
1247 * Used for turning off IMS completely in order to make the device CSFB'ed.
1248 * Once turned off, all calls will be over CS.
1249 */
Etan Cohen82f78122014-12-15 10:10:14 -08001250 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -07001251 checkAndThrowExceptionIfServiceUnavailable();
1252
ram7da5a112014-07-16 20:59:27 +05301253 try {
Etan Cohenabbd7882014-09-26 22:35:35 -07001254 mImsService.turnOffIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +05301255 } catch (RemoteException e) {
1256 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1257 }
1258 }
1259
1260 /**
Wink Savilleef36ef62014-06-11 08:39:38 -07001261 * Death recipient class for monitoring IMS service.
1262 */
1263 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
1264 @Override
1265 public void binderDied() {
1266 mImsService = null;
1267 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -05001268 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001269 mEcbm = null;
Tyler Gunn4d128b62016-04-13 15:44:38 -07001270 mMultiEndpoint = null;
Wink Savilleef36ef62014-06-11 08:39:38 -07001271
1272 if (mContext != null) {
Etan Cohend7727462014-07-12 14:54:10 -07001273 Intent intent = new Intent(ACTION_IMS_SERVICE_DOWN);
Etan Cohenabbd7882014-09-26 22:35:35 -07001274 intent.putExtra(EXTRA_PHONE_ID, mPhoneId);
Etan Cohend7727462014-07-12 14:54:10 -07001275 mContext.sendBroadcast(new Intent(intent));
Wink Savilleef36ef62014-06-11 08:39:38 -07001276 }
1277 }
1278 }
1279
1280 /**
1281 * Adapter class for {@link IImsRegistrationListener}.
1282 */
1283 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
1284 private int mServiceClass;
1285 private ImsConnectionStateListener mListener;
1286
1287 public ImsRegistrationListenerProxy(int serviceClass,
1288 ImsConnectionStateListener listener) {
1289 mServiceClass = serviceClass;
1290 mListener = listener;
1291 }
1292
1293 public boolean isSameProxy(int serviceClass) {
1294 return (mServiceClass == serviceClass);
1295 }
1296
Omkar Kolangadea7ced642015-05-04 17:55:13 -07001297 @Deprecated
Wink Savilleef36ef62014-06-11 08:39:38 -07001298 public void registrationConnected() {
1299 if (DBG) {
1300 log("registrationConnected ::");
1301 }
1302
1303 if (mListener != null) {
1304 mListener.onImsConnected();
1305 }
1306 }
1307
Omkar Kolangadea7ced642015-05-04 17:55:13 -07001308 @Deprecated
Rekha Kumar14631742015-02-04 10:47:00 -08001309 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07001310 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08001311 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07001312 }
1313
1314 if (mListener != null) {
Rekha Kumar14631742015-02-04 10:47:00 -08001315 mListener.onImsProgressing();
1316 }
1317 }
1318
1319 @Override
Omkar Kolangadea7ced642015-05-04 17:55:13 -07001320 public void registrationConnectedWithRadioTech(int imsRadioTech) {
1321 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
1322 // values in ServiceState.java.
1323 if (DBG) {
1324 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech);
1325 }
1326
1327 if (mListener != null) {
1328 mListener.onImsConnected();
1329 }
1330 }
1331
1332 @Override
1333 public void registrationProgressingWithRadioTech(int imsRadioTech) {
1334 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY
1335 // values in ServiceState.java.
1336 if (DBG) {
1337 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech);
1338 }
1339
1340 if (mListener != null) {
1341 mListener.onImsProgressing();
1342 }
1343 }
1344
1345 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08001346 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
1347 if (DBG) {
1348 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
1349 }
1350
1351 if (mListener != null) {
1352 mListener.onImsDisconnected(imsReasonInfo);
Wink Savilleef36ef62014-06-11 08:39:38 -07001353 }
1354 }
1355
1356 @Override
1357 public void registrationResumed() {
1358 if (DBG) {
1359 log("registrationResumed ::");
1360 }
1361
1362 if (mListener != null) {
1363 mListener.onImsResumed();
1364 }
1365 }
1366
1367 @Override
1368 public void registrationSuspended() {
1369 if (DBG) {
1370 log("registrationSuspended ::");
1371 }
1372
1373 if (mListener != null) {
1374 mListener.onImsSuspended();
1375 }
1376 }
1377
1378 @Override
1379 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
1380 log("registrationServiceCapabilityChanged :: serviceClass=" +
1381 serviceClass + ", event=" + event);
1382
1383 if (mListener != null) {
1384 mListener.onImsConnected();
1385 }
1386 }
ram7da5a112014-07-16 20:59:27 +05301387
1388 @Override
1389 public void registrationFeatureCapabilityChanged(int serviceClass,
1390 int[] enabledFeatures, int[] disabledFeatures) {
1391 log("registrationFeatureCapabilityChanged :: serviceClass=" +
1392 serviceClass);
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05001393 if (mListener != null) {
1394 mListener.onFeatureCapabilityChanged(serviceClass,
1395 enabledFeatures, disabledFeatures);
1396 }
ram7da5a112014-07-16 20:59:27 +05301397 }
1398
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07001399 @Override
1400 public void voiceMessageCountUpdate(int count) {
1401 log("voiceMessageCountUpdate :: count=" + count);
1402
1403 if (mListener != null) {
1404 mListener.onVoiceMessageCountChanged(count);
1405 }
1406 }
1407
Pavel Zhamaitsiak4de9cbb2016-02-11 17:21:05 -08001408 @Override
1409 public void registrationAssociatedUriChanged(Uri[] uris) {
1410 if (DBG) log("registrationAssociatedUriChanged ::");
1411
1412 if (mListener != null) {
1413 mListener.registrationAssociatedUriChanged(uris);
1414 }
1415 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001416 }
Tyler Gunn4d128b62016-04-13 15:44:38 -07001417
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001418 /**
1419 * Gets the ECBM interface to request ECBM exit.
1420 *
1421 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1422 * @return the ECBM interface instance
1423 * @throws ImsException if getting the ECBM interface results in an error
1424 */
1425 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
1426 if (mEcbm == null) {
1427 checkAndThrowExceptionIfServiceUnavailable();
1428
1429 try {
1430 IImsEcbm iEcbm = mImsService.getEcbmInterface(serviceId);
1431
1432 if (iEcbm == null) {
1433 throw new ImsException("getEcbmInterface()",
1434 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
1435 }
1436 mEcbm = new ImsEcbm(iEcbm);
1437 } catch (RemoteException e) {
1438 throw new ImsException("getEcbmInterface()", e,
1439 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1440 }
1441 }
1442 return mEcbm;
1443 }
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001444
1445 /**
Tyler Gunn4d128b62016-04-13 15:44:38 -07001446 * Gets the Multi-Endpoint interface to subscribe to multi-enpoint notifications..
1447 *
1448 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1449 * @return the multi-endpoint interface instance
1450 * @throws ImsException if getting the multi-endpoint interface results in an error
1451 */
1452 public ImsMultiEndpoint getMultiEndpointInterface(int serviceId) throws ImsException {
1453 if (mMultiEndpoint == null) {
1454 checkAndThrowExceptionIfServiceUnavailable();
1455
1456 try {
1457 IImsMultiEndpoint iImsMultiEndpoint = mImsService.getMultiEndpointInterface(
1458 serviceId);
1459
1460 if (iImsMultiEndpoint == null) {
1461 throw new ImsException("getMultiEndpointInterface()",
1462 ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED);
1463 }
1464 mMultiEndpoint = new ImsMultiEndpoint(iImsMultiEndpoint);
1465 } catch (RemoteException e) {
1466 throw new ImsException("getMultiEndpointInterface()", e,
1467 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1468 }
1469 }
1470 return mMultiEndpoint;
1471 }
1472
1473 /**
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001474 * Resets ImsManager settings back to factory defaults.
1475 *
1476 * @hide
1477 */
1478 public static void factoryReset(Context context) {
1479 // Set VoLTE to default
1480 android.provider.Settings.Global.putInt(context.getContentResolver(),
1481 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED,
1482 ImsConfig.FeatureValueConstants.ON);
1483
1484 // Set VoWiFi to default
1485 android.provider.Settings.Global.putInt(context.getContentResolver(),
1486 android.provider.Settings.Global.WFC_IMS_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08001487 getBooleanCarrierConfig(context,
1488 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ?
1489 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001490
1491 // Set VoWiFi mode to default
1492 android.provider.Settings.Global.putInt(context.getContentResolver(),
1493 android.provider.Settings.Global.WFC_IMS_MODE,
fionaxu5803ef02016-03-08 11:48:48 -08001494 getIntCarrierConfig(context,
1495 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT));
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001496
1497 // Set VoWiFi roaming to default
1498 android.provider.Settings.Global.putInt(context.getContentResolver(),
1499 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
fionaxu5803ef02016-03-08 11:48:48 -08001500 getBooleanCarrierConfig(context,
1501 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ?
1502 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001503
1504 // Set VT to default
Pavel Zhamaitsiak92b54b22016-04-01 15:55:47 -07001505 android.provider.Settings.Global.putInt(context.getContentResolver(),
1506 android.provider.Settings.Global.VT_IMS_ENABLED,
1507 ImsConfig.FeatureValueConstants.ON);
Pavel Zhamaitsiak8c065f52015-11-10 14:36:44 -08001508
1509 // Push settings to ImsConfig
1510 ImsManager.updateImsServiceConfig(context,
1511 SubscriptionManager.getDefaultVoicePhoneId(), true);
1512 }
Jack Yu2f102bd2015-12-28 15:31:48 -08001513
1514 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1515 pw.println("ImsManager:");
1516 pw.println(" mPhoneId = " + mPhoneId);
1517 pw.println(" mConfigUpdated = " + mConfigUpdated);
1518 pw.println(" mImsService = " + mImsService);
1519
1520 pw.println(" isGbaValid = " + isGbaValid(mContext));
1521 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed());
1522 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled(mContext));
1523
1524 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform(mContext));
1525 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice(mContext));
1526 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " +
1527 isEnhanced4gLteModeSettingEnabledByUser(mContext));
1528 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform(mContext));
1529 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser(mContext));
1530
1531 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform(mContext));
1532 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser(mContext));
1533 pw.println(" getWfcMode = " + getWfcMode(mContext));
1534 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser(mContext));
1535
1536 pw.flush();
1537 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001538}