blob: d898f9fda46e39d2c74362ce4577ab8a88a3f82d [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;
Etan Cohena00c9192014-12-23 15:02:29 -080020import android.app.QueuedWork;
Wink Savilleef36ef62014-06-11 08:39:38 -070021import android.content.Context;
22import android.content.Intent;
Wink Savilleef36ef62014-06-11 08:39:38 -070023import android.os.IBinder;
Wink Savilleef36ef62014-06-11 08:39:38 -070024import android.os.Message;
Wink Savilleef36ef62014-06-11 08:39:38 -070025import android.os.RemoteException;
26import android.os.ServiceManager;
Etan Cohenaf55a402014-09-04 22:34:41 -070027import android.os.SystemProperties;
Etan Cohen82f78122014-12-15 10:10:14 -080028import android.provider.Settings;
29import android.telecom.TelecomManager;
Junda Liue7663c02015-06-23 11:16:26 -070030import android.telephony.CarrierConfigManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070031import android.telephony.Rlog;
Etan Cohen82f78122014-12-15 10:10:14 -080032import android.telephony.SubscriptionManager;
Etan Cohencfc784d2014-08-07 18:40:31 -070033import android.telephony.TelephonyManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070034
35import com.android.ims.internal.IImsCallSession;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070036import com.android.ims.internal.IImsEcbm;
37import com.android.ims.internal.IImsEcbmListener;
Wink Savilleef36ef62014-06-11 08:39:38 -070038import com.android.ims.internal.IImsRegistrationListener;
39import com.android.ims.internal.IImsService;
40import com.android.ims.internal.IImsUt;
41import com.android.ims.internal.ImsCallSession;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050042import com.android.ims.internal.IImsConfig;
43
Etan Cohend7727462014-07-12 14:54:10 -070044import java.util.HashMap;
45
Wink Savilleef36ef62014-06-11 08:39:38 -070046/**
47 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
48 * the operator's IMS network. This class is the starting point for any IMS actions.
49 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
50 * <p>The APIs in this class allows you to:</p>
51 *
52 * @hide
53 */
54public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070055
Etan Cohenaf55a402014-09-04 22:34:41 -070056 /*
57 * Debug flag to override configuration flag
58 */
Etan Cohenb651fa52014-10-22 10:51:29 -070059 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
60 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070061 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
62 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080063 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
64 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070065
Wink Savilleef36ef62014-06-11 08:39:38 -070066 /**
67 * For accessing the IMS related service.
68 * Internal use only.
69 * @hide
70 */
Etan Cohend7727462014-07-12 14:54:10 -070071 private static final String IMS_SERVICE = "ims";
Wink Savilleef36ef62014-06-11 08:39:38 -070072
73 /**
74 * The result code to be sent back with the incoming call {@link PendingIntent}.
75 * @see #open(PendingIntent, ImsConnectionStateListener)
76 */
77 public static final int INCOMING_CALL_RESULT_CODE = 101;
78
79 /**
80 * Key to retrieve the call ID from an incoming call intent.
81 * @see #open(PendingIntent, ImsConnectionStateListener)
82 */
83 public static final String EXTRA_CALL_ID = "android:imsCallID";
84
85 /**
86 * Action to broadcast when ImsService is up.
87 * Internal use only.
88 * @hide
89 */
90 public static final String ACTION_IMS_SERVICE_UP =
91 "com.android.ims.IMS_SERVICE_UP";
92
93 /**
94 * Action to broadcast when ImsService is down.
95 * Internal use only.
96 * @hide
97 */
98 public static final String ACTION_IMS_SERVICE_DOWN =
99 "com.android.ims.IMS_SERVICE_DOWN";
100
101 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700102 * Action to broadcast when ImsService registration fails.
103 * Internal use only.
104 * @hide
105 */
106 public static final String ACTION_IMS_REGISTRATION_ERROR =
107 "com.android.ims.REGISTRATION_ERROR";
108
109 /**
Etan Cohend7727462014-07-12 14:54:10 -0700110 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700111 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700112 * Internal use only.
113 * @hide
114 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700115 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700116
117 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700118 * Action for the incoming call intent for the Phone app.
119 * Internal use only.
120 * @hide
121 */
122 public static final String ACTION_IMS_INCOMING_CALL =
123 "com.android.ims.IMS_INCOMING_CALL";
124
125 /**
126 * Part of the ACTION_IMS_INCOMING_CALL intents.
127 * An integer value; service identifier obtained from {@link ImsManager#open}.
128 * Internal use only.
129 * @hide
130 */
131 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
132
133 /**
134 * Part of the ACTION_IMS_INCOMING_CALL intents.
135 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
136 * The value "true" indicates that the incoming call is for USSD.
137 * Internal use only.
138 * @hide
139 */
140 public static final String EXTRA_USSD = "android:ussd";
141
Shriram Ganeshd3adfad2015-05-31 10:06:15 -0700142 /**
143 * Part of the ACTION_IMS_INCOMING_CALL intents.
144 * A boolean value; Flag to indicate whether the call is an unknown
145 * dialing call. Such calls are originated by sending commands (like
146 * AT commands) directly to modem without Android involvement.
147 * Even though they are not incoming calls, they are propagated
148 * to Phone app using same ACTION_IMS_INCOMING_CALL intent.
149 * Internal use only.
150 * @hide
151 */
152 public static final String EXTRA_IS_UNKNOWN_CALL = "codeaurora:isUnknown";
153
Wink Savilleef36ef62014-06-11 08:39:38 -0700154 private static final String TAG = "ImsManager";
155 private static final boolean DBG = true;
156
Wink Saville1e5a38a2014-10-23 10:24:46 -0700157 private static HashMap<Integer, ImsManager> sImsManagerInstances =
158 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700159
Wink Savilleef36ef62014-06-11 08:39:38 -0700160 private Context mContext;
Etan Cohenabbd7882014-09-26 22:35:35 -0700161 private int mPhoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700162 private IImsService mImsService = null;
163 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
164 // Ut interface for the supplementary service configuration
165 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500166 // Interface to get/set ims config items
167 private ImsConfig mConfig = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700168
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700169 // ECBM interface
170 private ImsEcbm mEcbm = null;
171
Wink Savilleef36ef62014-06-11 08:39:38 -0700172 /**
173 * Gets a manager instance.
174 *
175 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700176 * @param phoneId the phone ID for the IMS Service
177 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700178 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700179 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700180 synchronized (sImsManagerInstances) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700181 if (sImsManagerInstances.containsKey(phoneId))
182 return sImsManagerInstances.get(phoneId);
Wink Savilleef36ef62014-06-11 08:39:38 -0700183
Etan Cohenabbd7882014-09-26 22:35:35 -0700184 ImsManager mgr = new ImsManager(context, phoneId);
185 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700186
187 return mgr;
188 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700189 }
190
Etan Cohen45b5f312014-08-19 15:55:08 -0700191 /**
192 * Returns the user configuration of Enhanced 4G LTE Mode setting
193 */
194 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Libin.Tang@motorola.com8a6bf4b2014-10-10 15:02:41 -0500195 int enabled = android.provider.Settings.Global.getInt(
196 context.getContentResolver(),
Etan Cohenb651fa52014-10-22 10:51:29 -0700197 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
Etan Cohena00c9192014-12-23 15:02:29 -0800198 return (enabled == 1) ? true : false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700199 }
200
201 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800202 * Change persistent Enhanced 4G LTE Mode setting
203 */
204 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
205 int value = enabled ? 1 : 0;
206 android.provider.Settings.Global.putInt(
207 context.getContentResolver(),
208 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
209
210 if (isNonTtyOrTtyOnVolteEnabled(context)) {
211 ImsManager imsManager = ImsManager.getInstance(context,
212 SubscriptionManager.getDefaultVoicePhoneId());
213 if (imsManager != null) {
214 try {
215 imsManager.setAdvanced4GMode(enabled);
216 } catch (ImsException ie) {
217 // do nothing
218 }
219 }
220 }
221 }
222
223 /**
224 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
225 * supported.
226 */
227 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700228 if (getBooleanCarrierConfig(context,
229 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800230 return true;
231 }
232
233 return Settings.Secure.getInt(context.getContentResolver(),
234 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
235 == TelecomManager.TTY_MODE_OFF;
236 }
237
238 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700239 * Returns a platform configuration for VoLTE which may override the user setting.
Etan Cohen45b5f312014-08-19 15:55:08 -0700240 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700241 public static boolean isVolteEnabledByPlatform(Context context) {
Etan Cohenb651fa52014-10-22 10:51:29 -0700242 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
243 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
Etan Cohenaf55a402014-09-04 22:34:41 -0700244 return true;
245 }
246
Etan Cohend40d4a92014-11-24 11:18:33 -0800247 boolean disabledByGlobalSetting = android.provider.Settings.Global.getInt(
248 context.getContentResolver(),
249 android.provider.Settings.Global.VOLTE_FEATURE_DISABLED, 0) == 1;
250
Etan Cohenb5388a32014-11-26 11:57:47 -0800251 return context.getResources().getBoolean(
Junda Liue7663c02015-06-23 11:16:26 -0700252 com.android.internal.R.bool.config_device_volte_available)
253 && getBooleanCarrierConfig(context,
254 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Etan Cohenb5388a32014-11-26 11:57:47 -0800255 && !disabledByGlobalSetting;
256 }
257
258 /*
259 * Indicates whether VoLTE is provisioned on device
260 */
261 public static boolean isVolteProvisionedOnDevice(Context context) {
262 boolean isProvisioned = true;
Junda Liue7663c02015-06-23 11:16:26 -0700263 if (getBooleanCarrierConfig(context,
264 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Etan Cohenb5388a32014-11-26 11:57:47 -0800265 isProvisioned = false; // disable on any error
266 ImsManager mgr = ImsManager.getInstance(context,
Jonathan Basserid7133652015-04-07 19:54:24 -0700267 SubscriptionManager.getDefaultVoicePhoneId());
Etan Cohenb5388a32014-11-26 11:57:47 -0800268 if (mgr != null) {
269 try {
270 ImsConfig config = mgr.getConfigInterface();
271 if (config != null) {
272 isProvisioned = config.getVolteProvisioned();
273 }
274 } catch (ImsException ie) {
275 // do nothing
276 }
277 }
278 }
279
280 return isProvisioned;
Etan Cohenb651fa52014-10-22 10:51:29 -0700281 }
282
Etan Cohenea2b5832014-10-23 18:50:35 -0700283 /**
284 * Returns a platform configuration for VT which may override the user setting.
285 *
286 * Note: VT presumes that VoLTE is enabled (these are configuration settings
287 * which must be done correctly).
288 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700289 public static boolean isVtEnabledByPlatform(Context context) {
Etan Cohenea2b5832014-10-23 18:50:35 -0700290 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
291 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
292 return true;
293 }
294
Etan Cohenb651fa52014-10-22 10:51:29 -0700295 return
296 context.getResources().getBoolean(
297 com.android.internal.R.bool.config_device_vt_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700298 getBooleanCarrierConfig(context,
299 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL);
Etan Cohen45b5f312014-08-19 15:55:08 -0700300 }
301
Etan Cohena00c9192014-12-23 15:02:29 -0800302 /**
303 * Returns the user configuration of WFC setting
304 */
305 public static boolean isWfcEnabledByUser(Context context) {
306 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
307 android.provider.Settings.Global.WFC_IMS_ENABLED,
Pavel Zhamaitsiakeb13a592015-04-27 09:44:33 -0700308 ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800309 return (enabled == 1) ? true : false;
310 }
311
312 /**
313 * Change persistent WFC enabled setting
314 */
315 public static void setWfcSetting(Context context, boolean enabled) {
316 int value = enabled ? 1 : 0;
317 android.provider.Settings.Global.putInt(context.getContentResolver(),
318 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
319
320 ImsManager imsManager = ImsManager.getInstance(context,
321 SubscriptionManager.getDefaultVoicePhoneId());
322 if (imsManager != null) {
323 try {
324 ImsConfig config = imsManager.getConfigInterface();
325 // FIXME: replace NETWORK_TYPE_LTE with NETWORK_TYPE_IWLAN
326 // when available
327 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
328 TelephonyManager.NETWORK_TYPE_LTE,
329 enabled ? ImsConfig.FeatureValueConstants.ON
330 : ImsConfig.FeatureValueConstants.OFF, null);
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800331
332 if (enabled) {
333 imsManager.turnOnIms();
Junda Liue7663c02015-06-23 11:16:26 -0700334 } else if (getBooleanCarrierConfig(context,
335 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800336 && (!isVolteEnabledByPlatform(context)
337 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
338 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
339 imsManager.turnOffIms();
340 }
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700341
342 // Force IMS to register over LTE when turning off WFC
343 setWfcModeInternal(context, enabled
344 ? getWfcMode(context)
345 : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED);
Etan Cohena00c9192014-12-23 15:02:29 -0800346 } catch (ImsException e) {
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800347 loge("setWfcSetting(): " + e);
Etan Cohena00c9192014-12-23 15:02:29 -0800348 }
349 }
350 }
351
352 /**
353 * Returns the user configuration of WFC modem setting
354 */
355 public static int getWfcMode(Context context) {
356 int setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
357 android.provider.Settings.Global.WFC_IMS_MODE,
358 ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED);
359 if (DBG) log("getWfcMode - setting=" + setting);
360 return setting;
361 }
362
363 /**
364 * Returns the user configuration of WFC modem setting
365 */
366 public static void setWfcMode(Context context, int wfcMode) {
367 if (DBG) log("setWfcMode - setting=" + wfcMode);
368 android.provider.Settings.Global.putInt(context.getContentResolver(),
369 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
370
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700371 setWfcModeInternal(context, wfcMode);
372 }
373
374 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800375 final ImsManager imsManager = ImsManager.getInstance(context,
376 SubscriptionManager.getDefaultVoicePhoneId());
377 if (imsManager != null) {
378 final int value = wfcMode;
379 QueuedWork.singleThreadExecutor().submit(new Runnable() {
380 public void run() {
381 try {
382 imsManager.getConfigInterface().setProvisionedValue(
383 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
384 value);
385 } catch (ImsException e) {
386 // do nothing
387 }
388 }
389 });
390 }
391 }
392
393 /**
394 * Returns the user configuration of WFC roaming setting
395 */
396 public static boolean isWfcRoamingEnabledByUser(Context context) {
397 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
398 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
Pavel Zhamaitsiak28c84002015-03-10 16:42:01 -0700399 ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800400 return (enabled == 1) ? true : false;
401 }
402
403 /**
404 * Change persistent WFC roaming enabled setting
405 */
406 public static void setWfcRoamingSetting(Context context, boolean enabled) {
407 final int value = enabled
408 ? ImsConfig.FeatureValueConstants.ON
409 : ImsConfig.FeatureValueConstants.OFF;
410 android.provider.Settings.Global.putInt(context.getContentResolver(),
411 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, value);
412
413 final ImsManager imsManager = ImsManager.getInstance(context,
414 SubscriptionManager.getDefaultVoicePhoneId());
415 if (imsManager != null) {
416 QueuedWork.singleThreadExecutor().submit(new Runnable() {
417 public void run() {
418 try {
419 imsManager.getConfigInterface().setProvisionedValue(
420 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING,
421 value);
422 } catch (ImsException e) {
423 // do nothing
424 }
425 }
426 });
427 }
428 }
429
430 /**
431 * Returns a platform configuration for WFC which may override the user
432 * setting. Note: WFC presumes that VoLTE is enabled (these are
433 * configuration settings which must be done correctly).
434 */
435 public static boolean isWfcEnabledByPlatform(Context context) {
436 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
437 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
438 return true;
439 }
440
441 return
442 context.getResources().getBoolean(
443 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700444 getBooleanCarrierConfig(context,
445 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL);
Etan Cohena00c9192014-12-23 15:02:29 -0800446 }
447
Etan Cohenabbd7882014-09-26 22:35:35 -0700448 private ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700449 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -0700450 mPhoneId = phoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700451 createImsService(true);
452 }
453
Etan Cohenf4311122015-02-26 17:47:13 -0800454 /*
455 * Returns a flag indicating whether the IMS service is available.
456 */
457 public boolean isServiceAvailable() {
458 if (mImsService != null) {
459 return true;
460 }
461
462 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
463 if (binder != null) {
464 return true;
465 }
466
467 return false;
468 }
469
Wink Savilleef36ef62014-06-11 08:39:38 -0700470 /**
471 * Opens the IMS service for making calls and/or receiving generic IMS calls.
472 * The caller may make subsquent calls through {@link #makeCall}.
473 * The IMS service will register the device to the operator's network with the credentials
474 * (from ISIM) periodically in order to receive calls from the operator's network.
475 * When the IMS service receives a new call, it will send out an intent with
476 * the provided action string.
477 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
478 *
479 * @param serviceClass a service class specified in {@link ImsServiceClass}
480 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
481 * @param incomingCallPendingIntent When an incoming call is received,
482 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
483 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
484 * as the result code and the intent to fill in the call ID; It cannot be null
485 * @param listener To listen to IMS registration events; It cannot be null
486 * @return identifier (greater than 0) for the specified service
487 * @throws NullPointerException if {@code incomingCallPendingIntent}
488 * or {@code listener} is null
489 * @throws ImsException if calling the IMS service results in an error
490 * @see #getCallId
491 * @see #getServiceId
492 */
493 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
494 ImsConnectionStateListener listener) throws ImsException {
495 checkAndThrowExceptionIfServiceUnavailable();
496
497 if (incomingCallPendingIntent == null) {
498 throw new NullPointerException("incomingCallPendingIntent can't be null");
499 }
500
501 if (listener == null) {
502 throw new NullPointerException("listener can't be null");
503 }
504
505 int result = 0;
506
507 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700508 result = mImsService.open(mPhoneId, serviceClass, incomingCallPendingIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -0700509 createRegistrationListenerProxy(serviceClass, listener));
510 } catch (RemoteException e) {
511 throw new ImsException("open()", e,
512 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
513 }
514
515 if (result <= 0) {
516 // If the return value is a minus value,
517 // it means that an error occurred in the service.
518 // So, it needs to convert to the reason code specified in ImsReasonInfo.
519 throw new ImsException("open()", (result * (-1)));
520 }
521
522 return result;
523 }
524
525 /**
526 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
527 * All the resources that were allocated to the service are also released.
528 *
529 * @param serviceId a service id to be closed which is obtained from {@link ImsManager#open}
530 * @throws ImsException if calling the IMS service results in an error
531 */
532 public void close(int serviceId) throws ImsException {
533 checkAndThrowExceptionIfServiceUnavailable();
534
535 try {
536 mImsService.close(serviceId);
537 } catch (RemoteException e) {
538 throw new ImsException("close()", e,
539 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
540 } finally {
541 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500542 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700543 mEcbm = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700544 }
545 }
546
547 /**
548 * Gets the configuration interface to provision / withdraw the supplementary service settings.
549 *
550 * @param serviceId a service id which is obtained from {@link ImsManager#open}
551 * @return the Ut interface instance
552 * @throws ImsException if getting the Ut interface results in an error
553 */
554 public ImsUtInterface getSupplementaryServiceConfiguration(int serviceId)
555 throws ImsException {
556 // FIXME: manage the multiple Ut interfaces based on the service id
557 if (mUt == null) {
558 checkAndThrowExceptionIfServiceUnavailable();
559
560 try {
561 IImsUt iUt = mImsService.getUtInterface(serviceId);
562
563 if (iUt == null) {
564 throw new ImsException("getSupplementaryServiceConfiguration()",
565 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
566 }
567
568 mUt = new ImsUt(iUt);
569 } catch (RemoteException e) {
570 throw new ImsException("getSupplementaryServiceConfiguration()", e,
571 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
572 }
573 }
574
575 return mUt;
576 }
577
578 /**
579 * Checks if the IMS service has successfully registered to the IMS network
580 * with the specified service & call type.
581 *
582 * @param serviceId a service id which is obtained from {@link ImsManager#open}
583 * @param serviceType a service type that is specified in {@link ImsCallProfile}
584 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
585 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
586 * @param callType a call type that is specified in {@link ImsCallProfile}
587 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
588 * {@link ImsCallProfile#CALL_TYPE_VOICE}
589 * {@link ImsCallProfile#CALL_TYPE_VT}
590 * {@link ImsCallProfile#CALL_TYPE_VS}
591 * @return true if the specified service id is connected to the IMS network;
592 * false otherwise
593 * @throws ImsException if calling the IMS service results in an error
594 */
595 public boolean isConnected(int serviceId, int serviceType, int callType)
596 throws ImsException {
597 checkAndThrowExceptionIfServiceUnavailable();
598
599 try {
600 return mImsService.isConnected(serviceId, serviceType, callType);
601 } catch (RemoteException e) {
602 throw new ImsException("isServiceConnected()", e,
603 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
604 }
605 }
606
607 /**
608 * Checks if the specified IMS service is opend.
609 *
610 * @param serviceId a service id which is obtained from {@link ImsManager#open}
611 * @return true if the specified service id is opened; false otherwise
612 * @throws ImsException if calling the IMS service results in an error
613 */
614 public boolean isOpened(int serviceId) throws ImsException {
615 checkAndThrowExceptionIfServiceUnavailable();
616
617 try {
618 return mImsService.isOpened(serviceId);
619 } catch (RemoteException e) {
620 throw new ImsException("isOpened()", e,
621 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
622 }
623 }
624
625 /**
626 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
627 *
628 * @param serviceId a service id which is obtained from {@link ImsManager#open}
629 * @param serviceType a service type that is specified in {@link ImsCallProfile}
630 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
631 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
632 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
633 * @param callType a call type that is specified in {@link ImsCallProfile}
634 * {@link ImsCallProfile#CALL_TYPE_VOICE}
635 * {@link ImsCallProfile#CALL_TYPE_VT}
636 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
637 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
638 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
639 * {@link ImsCallProfile#CALL_TYPE_VS}
640 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
641 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
642 * @return a {@link ImsCallProfile} object
643 * @throws ImsException if calling the IMS service results in an error
644 */
645 public ImsCallProfile createCallProfile(int serviceId,
646 int serviceType, int callType) throws ImsException {
647 checkAndThrowExceptionIfServiceUnavailable();
648
649 try {
650 return mImsService.createCallProfile(serviceId, serviceType, callType);
651 } catch (RemoteException e) {
652 throw new ImsException("createCallProfile()", e,
653 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
654 }
655 }
656
657 /**
658 * Creates a {@link ImsCall} to make a call.
659 *
660 * @param serviceId a service id which is obtained from {@link ImsManager#open}
661 * @param profile a call profile to make the call
662 * (it contains service type, call type, media information, etc.)
663 * @param participants participants to invite the conference call
664 * @param listener listen to the call events from {@link ImsCall}
665 * @return a {@link ImsCall} object
666 * @throws ImsException if calling the IMS service results in an error
667 */
668 public ImsCall makeCall(int serviceId, ImsCallProfile profile, String[] callees,
669 ImsCall.Listener listener) throws ImsException {
670 if (DBG) {
671 log("makeCall :: serviceId=" + serviceId
672 + ", profile=" + profile + ", callees=" + callees);
673 }
674
675 checkAndThrowExceptionIfServiceUnavailable();
676
677 ImsCall call = new ImsCall(mContext, profile);
678
679 call.setListener(listener);
680 ImsCallSession session = createCallSession(serviceId, profile);
681
682 if ((callees != null) && (callees.length == 1)) {
683 call.start(session, callees[0]);
684 } else {
685 call.start(session, callees);
686 }
687
688 return call;
689 }
690
691 /**
692 * Creates a {@link ImsCall} to take an incoming call.
693 *
694 * @param serviceId a service id which is obtained from {@link ImsManager#open}
695 * @param incomingCallIntent the incoming call broadcast intent
696 * @param listener to listen to the call events from {@link ImsCall}
697 * @return a {@link ImsCall} object
698 * @throws ImsException if calling the IMS service results in an error
699 */
700 public ImsCall takeCall(int serviceId, Intent incomingCallIntent,
701 ImsCall.Listener listener) throws ImsException {
702 if (DBG) {
703 log("takeCall :: serviceId=" + serviceId
704 + ", incomingCall=" + incomingCallIntent);
705 }
706
707 checkAndThrowExceptionIfServiceUnavailable();
708
709 if (incomingCallIntent == null) {
710 throw new ImsException("Can't retrieve session with null intent",
711 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
712 }
713
714 int incomingServiceId = getServiceId(incomingCallIntent);
715
716 if (serviceId != incomingServiceId) {
717 throw new ImsException("Service id is mismatched in the incoming call intent",
718 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
719 }
720
721 String callId = getCallId(incomingCallIntent);
722
723 if (callId == null) {
724 throw new ImsException("Call ID missing in the incoming call intent",
725 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
726 }
727
728 try {
729 IImsCallSession session = mImsService.getPendingCallSession(serviceId, callId);
730
731 if (session == null) {
732 throw new ImsException("No pending session for the call",
733 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
734 }
735
736 ImsCall call = new ImsCall(mContext, session.getCallProfile());
737
738 call.attachSession(new ImsCallSession(session));
739 call.setListener(listener);
740
741 return call;
742 } catch (Throwable t) {
743 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
744 }
745 }
746
747 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500748 * Gets the config interface to get/set service/capability parameters.
749 *
750 * @return the ImsConfig instance.
751 * @throws ImsException if getting the setting interface results in an error.
752 */
753 public ImsConfig getConfigInterface() throws ImsException {
754
755 if (mConfig == null) {
756 checkAndThrowExceptionIfServiceUnavailable();
757
758 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700759 IImsConfig config = mImsService.getConfigInterface(mPhoneId);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500760 if (config == null) {
761 throw new ImsException("getConfigInterface()",
762 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
763 }
Libin.Tang@motorola.com54953c72014-08-07 15:02:08 -0500764 mConfig = new ImsConfig(config, mContext);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500765 } catch (RemoteException e) {
766 throw new ImsException("getConfigInterface()", e,
767 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
768 }
769 }
770 if (DBG) log("getConfigInterface(), mConfig= " + mConfig);
771 return mConfig;
772 }
773
Etan Cohen82f78122014-12-15 10:10:14 -0800774 public void setUiTTYMode(Context context, int serviceId, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530775 throws ImsException {
776
Etan Cohen82f78122014-12-15 10:10:14 -0800777 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530778
Etan Cohen82f78122014-12-15 10:10:14 -0800779 try {
780 mImsService.setUiTTYMode(serviceId, uiTtyMode, onComplete);
781 } catch (RemoteException e) {
782 throw new ImsException("setTTYMode()", e,
783 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
784 }
785
Junda Liue7663c02015-06-23 11:16:26 -0700786 if (!getBooleanCarrierConfig(context,
787 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800788 setAdvanced4GMode((uiTtyMode == TelecomManager.TTY_MODE_OFF) &&
789 isEnhanced4gLteModeSettingEnabledByUser(context));
790 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530791 }
792
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500793 /**
Junda Liue7663c02015-06-23 11:16:26 -0700794 * Get the boolean config from carrier config manager.
795 *
796 * @param context the context to get carrier service
797 * @param key config key defined in CarrierConfigManager
798 * @return boolean value of corresponding key.
799 */
800 private static boolean getBooleanCarrierConfig(Context context, String key) {
801 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
802 Context.CARRIER_CONFIG_SERVICE);
803 if (configManager != null) {
804 return configManager.getConfig().getBoolean(key);
805 } else {
806 // Return static default defined in CarrierConfigManager.
807 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
808 }
809 }
810
811 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700812 * Gets the call ID from the specified incoming call broadcast intent.
813 *
814 * @param incomingCallIntent the incoming call broadcast intent
815 * @return the call ID or null if the intent does not contain it
816 */
817 private static String getCallId(Intent incomingCallIntent) {
818 if (incomingCallIntent == null) {
819 return null;
820 }
821
822 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
823 }
824
825 /**
826 * Gets the service type from the specified incoming call broadcast intent.
827 *
828 * @param incomingCallIntent the incoming call broadcast intent
829 * @return the service identifier or -1 if the intent does not contain it
830 */
831 private static int getServiceId(Intent incomingCallIntent) {
832 if (incomingCallIntent == null) {
833 return (-1);
834 }
835
836 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
837 }
838
839 /**
840 * Binds the IMS service only if the service is not created.
841 */
842 private void checkAndThrowExceptionIfServiceUnavailable()
843 throws ImsException {
844 if (mImsService == null) {
845 createImsService(true);
846
847 if (mImsService == null) {
848 throw new ImsException("Service is unavailable",
849 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
850 }
851 }
852 }
853
Etan Cohenabbd7882014-09-26 22:35:35 -0700854 private static String getImsServiceName(int phoneId) {
855 // TODO: MSIM implementation needs to decide on service name as a function of phoneId
Etan Cohend7727462014-07-12 14:54:10 -0700856 return IMS_SERVICE;
857 }
858
Wink Savilleef36ef62014-06-11 08:39:38 -0700859 /**
860 * Binds the IMS service to make/receive the call.
861 */
862 private void createImsService(boolean checkService) {
863 if (checkService) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700864 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -0700865
866 if (binder == null) {
867 return;
868 }
869 }
870
Etan Cohenabbd7882014-09-26 22:35:35 -0700871 IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -0700872
873 if (b != null) {
874 try {
875 b.linkToDeath(mDeathRecipient, 0);
876 } catch (RemoteException e) {
877 }
878 }
879
880 mImsService = IImsService.Stub.asInterface(b);
881 }
882
883 /**
884 * Creates a {@link ImsCallSession} with the specified call profile.
885 * Use other methods, if applicable, instead of interacting with
886 * {@link ImsCallSession} directly.
887 *
888 * @param serviceId a service id which is obtained from {@link ImsManager#open}
889 * @param profile a call profile to make the call
890 */
891 private ImsCallSession createCallSession(int serviceId,
892 ImsCallProfile profile) throws ImsException {
893 try {
894 return new ImsCallSession(mImsService.createCallSession(serviceId, profile, null));
895 } catch (RemoteException e) {
896 return null;
897 }
898 }
899
900 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass,
901 ImsConnectionStateListener listener) {
902 ImsRegistrationListenerProxy proxy =
903 new ImsRegistrationListenerProxy(serviceClass, listener);
904 return proxy;
905 }
906
Etan Cohena00c9192014-12-23 15:02:29 -0800907 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700908 Rlog.d(TAG, s);
909 }
910
Etan Cohena00c9192014-12-23 15:02:29 -0800911 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700912 Rlog.e(TAG, s);
913 }
914
Etan Cohena00c9192014-12-23 15:02:29 -0800915 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700916 Rlog.e(TAG, s, t);
917 }
918
919 /**
ram7da5a112014-07-16 20:59:27 +0530920 * Used for turning on IMS.if its off already
921 */
Etan Cohen82f78122014-12-15 10:10:14 -0800922 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -0700923 checkAndThrowExceptionIfServiceUnavailable();
924
ram7da5a112014-07-16 20:59:27 +0530925 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700926 mImsService.turnOnIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +0530927 } catch (RemoteException e) {
928 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
929 }
930 }
931
Etan Cohen82f78122014-12-15 10:10:14 -0800932 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
Etan Cohencfc784d2014-08-07 18:40:31 -0700933 checkAndThrowExceptionIfServiceUnavailable();
934
935 ImsConfig config = getConfigInterface();
936 if (config != null) {
937 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
938 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
Etan Cohenb651fa52014-10-22 10:51:29 -0700939 if (isVtEnabledByPlatform(mContext)) {
940 // TODO: once VT is available on platform replace the '1' with the current
941 // user configuration of VT.
942 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
943 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
944 }
Etan Cohencfc784d2014-08-07 18:40:31 -0700945 }
946
947 if (turnOn) {
948 turnOnIms();
Junda Liue7663c02015-06-23 11:16:26 -0700949 } else if (getBooleanCarrierConfig(mContext,
950 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800951 && (!isWfcEnabledByPlatform(mContext)
952 || !isWfcEnabledByUser(mContext))) {
Etan Cohencfc784d2014-08-07 18:40:31 -0700953 log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms");
954 turnOffIms();
955 }
956 }
957
ram7da5a112014-07-16 20:59:27 +0530958 /**
959 * Used for turning off IMS completely in order to make the device CSFB'ed.
960 * Once turned off, all calls will be over CS.
961 */
Etan Cohen82f78122014-12-15 10:10:14 -0800962 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -0700963 checkAndThrowExceptionIfServiceUnavailable();
964
ram7da5a112014-07-16 20:59:27 +0530965 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700966 mImsService.turnOffIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +0530967 } catch (RemoteException e) {
968 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
969 }
970 }
971
972 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700973 * Death recipient class for monitoring IMS service.
974 */
975 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
976 @Override
977 public void binderDied() {
978 mImsService = null;
979 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500980 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700981 mEcbm = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700982
983 if (mContext != null) {
Etan Cohend7727462014-07-12 14:54:10 -0700984 Intent intent = new Intent(ACTION_IMS_SERVICE_DOWN);
Etan Cohenabbd7882014-09-26 22:35:35 -0700985 intent.putExtra(EXTRA_PHONE_ID, mPhoneId);
Etan Cohend7727462014-07-12 14:54:10 -0700986 mContext.sendBroadcast(new Intent(intent));
Wink Savilleef36ef62014-06-11 08:39:38 -0700987 }
988 }
989 }
990
991 /**
992 * Adapter class for {@link IImsRegistrationListener}.
993 */
994 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
995 private int mServiceClass;
996 private ImsConnectionStateListener mListener;
997
998 public ImsRegistrationListenerProxy(int serviceClass,
999 ImsConnectionStateListener listener) {
1000 mServiceClass = serviceClass;
1001 mListener = listener;
1002 }
1003
1004 public boolean isSameProxy(int serviceClass) {
1005 return (mServiceClass == serviceClass);
1006 }
1007
1008 @Override
1009 public void registrationConnected() {
1010 if (DBG) {
1011 log("registrationConnected ::");
1012 }
1013
1014 if (mListener != null) {
1015 mListener.onImsConnected();
1016 }
1017 }
1018
1019 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08001020 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07001021 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08001022 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07001023 }
1024
1025 if (mListener != null) {
Rekha Kumar14631742015-02-04 10:47:00 -08001026 mListener.onImsProgressing();
1027 }
1028 }
1029
1030 @Override
1031 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
1032 if (DBG) {
1033 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
1034 }
1035
1036 if (mListener != null) {
1037 mListener.onImsDisconnected(imsReasonInfo);
Wink Savilleef36ef62014-06-11 08:39:38 -07001038 }
1039 }
1040
1041 @Override
1042 public void registrationResumed() {
1043 if (DBG) {
1044 log("registrationResumed ::");
1045 }
1046
1047 if (mListener != null) {
1048 mListener.onImsResumed();
1049 }
1050 }
1051
1052 @Override
1053 public void registrationSuspended() {
1054 if (DBG) {
1055 log("registrationSuspended ::");
1056 }
1057
1058 if (mListener != null) {
1059 mListener.onImsSuspended();
1060 }
1061 }
1062
1063 @Override
1064 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
1065 log("registrationServiceCapabilityChanged :: serviceClass=" +
1066 serviceClass + ", event=" + event);
1067
1068 if (mListener != null) {
1069 mListener.onImsConnected();
1070 }
1071 }
ram7da5a112014-07-16 20:59:27 +05301072
1073 @Override
1074 public void registrationFeatureCapabilityChanged(int serviceClass,
1075 int[] enabledFeatures, int[] disabledFeatures) {
1076 log("registrationFeatureCapabilityChanged :: serviceClass=" +
1077 serviceClass);
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05001078 if (mListener != null) {
1079 mListener.onFeatureCapabilityChanged(serviceClass,
1080 enabledFeatures, disabledFeatures);
1081 }
ram7da5a112014-07-16 20:59:27 +05301082 }
1083
Shriram Ganeshd3adfad2015-05-31 10:06:15 -07001084 @Override
1085 public void voiceMessageCountUpdate(int count) {
1086 log("voiceMessageCountUpdate :: count=" + count);
1087
1088 if (mListener != null) {
1089 mListener.onVoiceMessageCountChanged(count);
1090 }
1091 }
1092
Wink Savilleef36ef62014-06-11 08:39:38 -07001093 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001094 /**
1095 * Gets the ECBM interface to request ECBM exit.
1096 *
1097 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1098 * @return the ECBM interface instance
1099 * @throws ImsException if getting the ECBM interface results in an error
1100 */
1101 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
1102 if (mEcbm == null) {
1103 checkAndThrowExceptionIfServiceUnavailable();
1104
1105 try {
1106 IImsEcbm iEcbm = mImsService.getEcbmInterface(serviceId);
1107
1108 if (iEcbm == null) {
1109 throw new ImsException("getEcbmInterface()",
1110 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
1111 }
1112 mEcbm = new ImsEcbm(iEcbm);
1113 } catch (RemoteException e) {
1114 throw new ImsException("getEcbmInterface()", e,
1115 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1116 }
1117 }
1118 return mEcbm;
1119 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001120}