blob: f8f2bf6f156cdc3e72d017aedd82525e380afbb0 [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
Wink Savilleef36ef62014-06-11 08:39:38 -0700142 private static final String TAG = "ImsManager";
143 private static final boolean DBG = true;
144
Wink Saville1e5a38a2014-10-23 10:24:46 -0700145 private static HashMap<Integer, ImsManager> sImsManagerInstances =
146 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700147
Wink Savilleef36ef62014-06-11 08:39:38 -0700148 private Context mContext;
Etan Cohenabbd7882014-09-26 22:35:35 -0700149 private int mPhoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700150 private IImsService mImsService = null;
151 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
152 // Ut interface for the supplementary service configuration
153 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500154 // Interface to get/set ims config items
155 private ImsConfig mConfig = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700156
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700157 // ECBM interface
158 private ImsEcbm mEcbm = null;
159
Wink Savilleef36ef62014-06-11 08:39:38 -0700160 /**
161 * Gets a manager instance.
162 *
163 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700164 * @param phoneId the phone ID for the IMS Service
165 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700166 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700167 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700168 synchronized (sImsManagerInstances) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700169 if (sImsManagerInstances.containsKey(phoneId))
170 return sImsManagerInstances.get(phoneId);
Wink Savilleef36ef62014-06-11 08:39:38 -0700171
Etan Cohenabbd7882014-09-26 22:35:35 -0700172 ImsManager mgr = new ImsManager(context, phoneId);
173 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700174
175 return mgr;
176 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700177 }
178
Etan Cohen45b5f312014-08-19 15:55:08 -0700179 /**
180 * Returns the user configuration of Enhanced 4G LTE Mode setting
181 */
182 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Libin.Tang@motorola.com8a6bf4b2014-10-10 15:02:41 -0500183 int enabled = android.provider.Settings.Global.getInt(
184 context.getContentResolver(),
Etan Cohenb651fa52014-10-22 10:51:29 -0700185 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
Etan Cohena00c9192014-12-23 15:02:29 -0800186 return (enabled == 1) ? true : false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700187 }
188
189 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800190 * Change persistent Enhanced 4G LTE Mode setting
191 */
192 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
193 int value = enabled ? 1 : 0;
194 android.provider.Settings.Global.putInt(
195 context.getContentResolver(),
196 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
197
198 if (isNonTtyOrTtyOnVolteEnabled(context)) {
199 ImsManager imsManager = ImsManager.getInstance(context,
200 SubscriptionManager.getDefaultVoicePhoneId());
201 if (imsManager != null) {
202 try {
203 imsManager.setAdvanced4GMode(enabled);
204 } catch (ImsException ie) {
205 // do nothing
206 }
207 }
208 }
209 }
210
211 /**
212 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
213 * supported.
214 */
215 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700216 if (getBooleanCarrierConfig(context,
217 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800218 return true;
219 }
220
221 return Settings.Secure.getInt(context.getContentResolver(),
222 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
223 == TelecomManager.TTY_MODE_OFF;
224 }
225
226 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700227 * Returns a platform configuration for VoLTE which may override the user setting.
Etan Cohen45b5f312014-08-19 15:55:08 -0700228 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700229 public static boolean isVolteEnabledByPlatform(Context context) {
Etan Cohenb651fa52014-10-22 10:51:29 -0700230 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
231 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
Etan Cohenaf55a402014-09-04 22:34:41 -0700232 return true;
233 }
234
Etan Cohend40d4a92014-11-24 11:18:33 -0800235 boolean disabledByGlobalSetting = android.provider.Settings.Global.getInt(
236 context.getContentResolver(),
237 android.provider.Settings.Global.VOLTE_FEATURE_DISABLED, 0) == 1;
238
Etan Cohenb5388a32014-11-26 11:57:47 -0800239 return context.getResources().getBoolean(
Junda Liue7663c02015-06-23 11:16:26 -0700240 com.android.internal.R.bool.config_device_volte_available)
241 && getBooleanCarrierConfig(context,
242 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
Etan Cohenb5388a32014-11-26 11:57:47 -0800243 && !disabledByGlobalSetting;
244 }
245
246 /*
247 * Indicates whether VoLTE is provisioned on device
248 */
249 public static boolean isVolteProvisionedOnDevice(Context context) {
250 boolean isProvisioned = true;
Junda Liue7663c02015-06-23 11:16:26 -0700251 if (getBooleanCarrierConfig(context,
252 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Etan Cohenb5388a32014-11-26 11:57:47 -0800253 isProvisioned = false; // disable on any error
254 ImsManager mgr = ImsManager.getInstance(context,
Jonathan Basserid7133652015-04-07 19:54:24 -0700255 SubscriptionManager.getDefaultVoicePhoneId());
Etan Cohenb5388a32014-11-26 11:57:47 -0800256 if (mgr != null) {
257 try {
258 ImsConfig config = mgr.getConfigInterface();
259 if (config != null) {
260 isProvisioned = config.getVolteProvisioned();
261 }
262 } catch (ImsException ie) {
263 // do nothing
264 }
265 }
266 }
267
268 return isProvisioned;
Etan Cohenb651fa52014-10-22 10:51:29 -0700269 }
270
Etan Cohenea2b5832014-10-23 18:50:35 -0700271 /**
272 * Returns a platform configuration for VT which may override the user setting.
273 *
274 * Note: VT presumes that VoLTE is enabled (these are configuration settings
275 * which must be done correctly).
276 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700277 public static boolean isVtEnabledByPlatform(Context context) {
Etan Cohenea2b5832014-10-23 18:50:35 -0700278 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
279 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
280 return true;
281 }
282
Etan Cohenb651fa52014-10-22 10:51:29 -0700283 return
284 context.getResources().getBoolean(
285 com.android.internal.R.bool.config_device_vt_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700286 getBooleanCarrierConfig(context,
287 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL);
Etan Cohen45b5f312014-08-19 15:55:08 -0700288 }
289
Etan Cohena00c9192014-12-23 15:02:29 -0800290 /**
291 * Returns the user configuration of WFC setting
292 */
293 public static boolean isWfcEnabledByUser(Context context) {
294 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
295 android.provider.Settings.Global.WFC_IMS_ENABLED,
Pavel Zhamaitsiakeb13a592015-04-27 09:44:33 -0700296 ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800297 return (enabled == 1) ? true : false;
298 }
299
300 /**
301 * Change persistent WFC enabled setting
302 */
303 public static void setWfcSetting(Context context, boolean enabled) {
304 int value = enabled ? 1 : 0;
305 android.provider.Settings.Global.putInt(context.getContentResolver(),
306 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
307
308 ImsManager imsManager = ImsManager.getInstance(context,
309 SubscriptionManager.getDefaultVoicePhoneId());
310 if (imsManager != null) {
311 try {
312 ImsConfig config = imsManager.getConfigInterface();
313 // FIXME: replace NETWORK_TYPE_LTE with NETWORK_TYPE_IWLAN
314 // when available
315 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
316 TelephonyManager.NETWORK_TYPE_LTE,
317 enabled ? ImsConfig.FeatureValueConstants.ON
318 : ImsConfig.FeatureValueConstants.OFF, null);
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800319
320 if (enabled) {
321 imsManager.turnOnIms();
Junda Liue7663c02015-06-23 11:16:26 -0700322 } else if (getBooleanCarrierConfig(context,
323 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800324 && (!isVolteEnabledByPlatform(context)
325 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
326 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
327 imsManager.turnOffIms();
328 }
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700329
330 // Force IMS to register over LTE when turning off WFC
331 setWfcModeInternal(context, enabled
332 ? getWfcMode(context)
333 : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED);
Etan Cohena00c9192014-12-23 15:02:29 -0800334 } catch (ImsException e) {
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800335 loge("setWfcSetting(): " + e);
Etan Cohena00c9192014-12-23 15:02:29 -0800336 }
337 }
338 }
339
340 /**
341 * Returns the user configuration of WFC modem setting
342 */
343 public static int getWfcMode(Context context) {
344 int setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
345 android.provider.Settings.Global.WFC_IMS_MODE,
346 ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED);
347 if (DBG) log("getWfcMode - setting=" + setting);
348 return setting;
349 }
350
351 /**
352 * Returns the user configuration of WFC modem setting
353 */
354 public static void setWfcMode(Context context, int wfcMode) {
355 if (DBG) log("setWfcMode - setting=" + wfcMode);
356 android.provider.Settings.Global.putInt(context.getContentResolver(),
357 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
358
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700359 setWfcModeInternal(context, wfcMode);
360 }
361
362 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800363 final ImsManager imsManager = ImsManager.getInstance(context,
364 SubscriptionManager.getDefaultVoicePhoneId());
365 if (imsManager != null) {
366 final int value = wfcMode;
367 QueuedWork.singleThreadExecutor().submit(new Runnable() {
368 public void run() {
369 try {
370 imsManager.getConfigInterface().setProvisionedValue(
371 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
372 value);
373 } catch (ImsException e) {
374 // do nothing
375 }
376 }
377 });
378 }
379 }
380
381 /**
382 * Returns the user configuration of WFC roaming setting
383 */
384 public static boolean isWfcRoamingEnabledByUser(Context context) {
385 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
386 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
Pavel Zhamaitsiak28c84002015-03-10 16:42:01 -0700387 ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800388 return (enabled == 1) ? true : false;
389 }
390
391 /**
392 * Change persistent WFC roaming enabled setting
393 */
394 public static void setWfcRoamingSetting(Context context, boolean enabled) {
395 final int value = enabled
396 ? ImsConfig.FeatureValueConstants.ON
397 : ImsConfig.FeatureValueConstants.OFF;
398 android.provider.Settings.Global.putInt(context.getContentResolver(),
399 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, value);
400
401 final ImsManager imsManager = ImsManager.getInstance(context,
402 SubscriptionManager.getDefaultVoicePhoneId());
403 if (imsManager != null) {
404 QueuedWork.singleThreadExecutor().submit(new Runnable() {
405 public void run() {
406 try {
407 imsManager.getConfigInterface().setProvisionedValue(
408 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING,
409 value);
410 } catch (ImsException e) {
411 // do nothing
412 }
413 }
414 });
415 }
416 }
417
418 /**
419 * Returns a platform configuration for WFC which may override the user
420 * setting. Note: WFC presumes that VoLTE is enabled (these are
421 * configuration settings which must be done correctly).
422 */
423 public static boolean isWfcEnabledByPlatform(Context context) {
424 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
425 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
426 return true;
427 }
428
429 return
430 context.getResources().getBoolean(
431 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700432 getBooleanCarrierConfig(context,
433 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL);
Etan Cohena00c9192014-12-23 15:02:29 -0800434 }
435
Etan Cohenabbd7882014-09-26 22:35:35 -0700436 private ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700437 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -0700438 mPhoneId = phoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700439 createImsService(true);
440 }
441
Etan Cohenf4311122015-02-26 17:47:13 -0800442 /*
443 * Returns a flag indicating whether the IMS service is available.
444 */
445 public boolean isServiceAvailable() {
446 if (mImsService != null) {
447 return true;
448 }
449
450 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
451 if (binder != null) {
452 return true;
453 }
454
455 return false;
456 }
457
Wink Savilleef36ef62014-06-11 08:39:38 -0700458 /**
459 * Opens the IMS service for making calls and/or receiving generic IMS calls.
460 * The caller may make subsquent calls through {@link #makeCall}.
461 * The IMS service will register the device to the operator's network with the credentials
462 * (from ISIM) periodically in order to receive calls from the operator's network.
463 * When the IMS service receives a new call, it will send out an intent with
464 * the provided action string.
465 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
466 *
467 * @param serviceClass a service class specified in {@link ImsServiceClass}
468 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
469 * @param incomingCallPendingIntent When an incoming call is received,
470 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
471 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
472 * as the result code and the intent to fill in the call ID; It cannot be null
473 * @param listener To listen to IMS registration events; It cannot be null
474 * @return identifier (greater than 0) for the specified service
475 * @throws NullPointerException if {@code incomingCallPendingIntent}
476 * or {@code listener} is null
477 * @throws ImsException if calling the IMS service results in an error
478 * @see #getCallId
479 * @see #getServiceId
480 */
481 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
482 ImsConnectionStateListener listener) throws ImsException {
483 checkAndThrowExceptionIfServiceUnavailable();
484
485 if (incomingCallPendingIntent == null) {
486 throw new NullPointerException("incomingCallPendingIntent can't be null");
487 }
488
489 if (listener == null) {
490 throw new NullPointerException("listener can't be null");
491 }
492
493 int result = 0;
494
495 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700496 result = mImsService.open(mPhoneId, serviceClass, incomingCallPendingIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -0700497 createRegistrationListenerProxy(serviceClass, listener));
498 } catch (RemoteException e) {
499 throw new ImsException("open()", e,
500 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
501 }
502
503 if (result <= 0) {
504 // If the return value is a minus value,
505 // it means that an error occurred in the service.
506 // So, it needs to convert to the reason code specified in ImsReasonInfo.
507 throw new ImsException("open()", (result * (-1)));
508 }
509
510 return result;
511 }
512
513 /**
514 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
515 * All the resources that were allocated to the service are also released.
516 *
517 * @param serviceId a service id to be closed which is obtained from {@link ImsManager#open}
518 * @throws ImsException if calling the IMS service results in an error
519 */
520 public void close(int serviceId) throws ImsException {
521 checkAndThrowExceptionIfServiceUnavailable();
522
523 try {
524 mImsService.close(serviceId);
525 } catch (RemoteException e) {
526 throw new ImsException("close()", e,
527 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
528 } finally {
529 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500530 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700531 mEcbm = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700532 }
533 }
534
535 /**
536 * Gets the configuration interface to provision / withdraw the supplementary service settings.
537 *
538 * @param serviceId a service id which is obtained from {@link ImsManager#open}
539 * @return the Ut interface instance
540 * @throws ImsException if getting the Ut interface results in an error
541 */
542 public ImsUtInterface getSupplementaryServiceConfiguration(int serviceId)
543 throws ImsException {
544 // FIXME: manage the multiple Ut interfaces based on the service id
545 if (mUt == null) {
546 checkAndThrowExceptionIfServiceUnavailable();
547
548 try {
549 IImsUt iUt = mImsService.getUtInterface(serviceId);
550
551 if (iUt == null) {
552 throw new ImsException("getSupplementaryServiceConfiguration()",
553 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
554 }
555
556 mUt = new ImsUt(iUt);
557 } catch (RemoteException e) {
558 throw new ImsException("getSupplementaryServiceConfiguration()", e,
559 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
560 }
561 }
562
563 return mUt;
564 }
565
566 /**
567 * Checks if the IMS service has successfully registered to the IMS network
568 * with the specified service & call type.
569 *
570 * @param serviceId a service id which is obtained from {@link ImsManager#open}
571 * @param serviceType a service type that is specified in {@link ImsCallProfile}
572 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
573 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
574 * @param callType a call type that is specified in {@link ImsCallProfile}
575 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
576 * {@link ImsCallProfile#CALL_TYPE_VOICE}
577 * {@link ImsCallProfile#CALL_TYPE_VT}
578 * {@link ImsCallProfile#CALL_TYPE_VS}
579 * @return true if the specified service id is connected to the IMS network;
580 * false otherwise
581 * @throws ImsException if calling the IMS service results in an error
582 */
583 public boolean isConnected(int serviceId, int serviceType, int callType)
584 throws ImsException {
585 checkAndThrowExceptionIfServiceUnavailable();
586
587 try {
588 return mImsService.isConnected(serviceId, serviceType, callType);
589 } catch (RemoteException e) {
590 throw new ImsException("isServiceConnected()", e,
591 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
592 }
593 }
594
595 /**
596 * Checks if the specified IMS service is opend.
597 *
598 * @param serviceId a service id which is obtained from {@link ImsManager#open}
599 * @return true if the specified service id is opened; false otherwise
600 * @throws ImsException if calling the IMS service results in an error
601 */
602 public boolean isOpened(int serviceId) throws ImsException {
603 checkAndThrowExceptionIfServiceUnavailable();
604
605 try {
606 return mImsService.isOpened(serviceId);
607 } catch (RemoteException e) {
608 throw new ImsException("isOpened()", e,
609 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
610 }
611 }
612
613 /**
614 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
615 *
616 * @param serviceId a service id which is obtained from {@link ImsManager#open}
617 * @param serviceType a service type that is specified in {@link ImsCallProfile}
618 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
619 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
620 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
621 * @param callType a call type that is specified in {@link ImsCallProfile}
622 * {@link ImsCallProfile#CALL_TYPE_VOICE}
623 * {@link ImsCallProfile#CALL_TYPE_VT}
624 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
625 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
626 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
627 * {@link ImsCallProfile#CALL_TYPE_VS}
628 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
629 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
630 * @return a {@link ImsCallProfile} object
631 * @throws ImsException if calling the IMS service results in an error
632 */
633 public ImsCallProfile createCallProfile(int serviceId,
634 int serviceType, int callType) throws ImsException {
635 checkAndThrowExceptionIfServiceUnavailable();
636
637 try {
638 return mImsService.createCallProfile(serviceId, serviceType, callType);
639 } catch (RemoteException e) {
640 throw new ImsException("createCallProfile()", e,
641 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
642 }
643 }
644
645 /**
646 * Creates a {@link ImsCall} to make a call.
647 *
648 * @param serviceId a service id which is obtained from {@link ImsManager#open}
649 * @param profile a call profile to make the call
650 * (it contains service type, call type, media information, etc.)
651 * @param participants participants to invite the conference call
652 * @param listener listen to the call events from {@link ImsCall}
653 * @return a {@link ImsCall} object
654 * @throws ImsException if calling the IMS service results in an error
655 */
656 public ImsCall makeCall(int serviceId, ImsCallProfile profile, String[] callees,
657 ImsCall.Listener listener) throws ImsException {
658 if (DBG) {
659 log("makeCall :: serviceId=" + serviceId
660 + ", profile=" + profile + ", callees=" + callees);
661 }
662
663 checkAndThrowExceptionIfServiceUnavailable();
664
665 ImsCall call = new ImsCall(mContext, profile);
666
667 call.setListener(listener);
668 ImsCallSession session = createCallSession(serviceId, profile);
669
670 if ((callees != null) && (callees.length == 1)) {
671 call.start(session, callees[0]);
672 } else {
673 call.start(session, callees);
674 }
675
676 return call;
677 }
678
679 /**
680 * Creates a {@link ImsCall} to take an incoming call.
681 *
682 * @param serviceId a service id which is obtained from {@link ImsManager#open}
683 * @param incomingCallIntent the incoming call broadcast intent
684 * @param listener to listen to the call events from {@link ImsCall}
685 * @return a {@link ImsCall} object
686 * @throws ImsException if calling the IMS service results in an error
687 */
688 public ImsCall takeCall(int serviceId, Intent incomingCallIntent,
689 ImsCall.Listener listener) throws ImsException {
690 if (DBG) {
691 log("takeCall :: serviceId=" + serviceId
692 + ", incomingCall=" + incomingCallIntent);
693 }
694
695 checkAndThrowExceptionIfServiceUnavailable();
696
697 if (incomingCallIntent == null) {
698 throw new ImsException("Can't retrieve session with null intent",
699 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
700 }
701
702 int incomingServiceId = getServiceId(incomingCallIntent);
703
704 if (serviceId != incomingServiceId) {
705 throw new ImsException("Service id is mismatched in the incoming call intent",
706 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
707 }
708
709 String callId = getCallId(incomingCallIntent);
710
711 if (callId == null) {
712 throw new ImsException("Call ID missing in the incoming call intent",
713 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
714 }
715
716 try {
717 IImsCallSession session = mImsService.getPendingCallSession(serviceId, callId);
718
719 if (session == null) {
720 throw new ImsException("No pending session for the call",
721 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
722 }
723
724 ImsCall call = new ImsCall(mContext, session.getCallProfile());
725
726 call.attachSession(new ImsCallSession(session));
727 call.setListener(listener);
728
729 return call;
730 } catch (Throwable t) {
731 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
732 }
733 }
734
735 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500736 * Gets the config interface to get/set service/capability parameters.
737 *
738 * @return the ImsConfig instance.
739 * @throws ImsException if getting the setting interface results in an error.
740 */
741 public ImsConfig getConfigInterface() throws ImsException {
742
743 if (mConfig == null) {
744 checkAndThrowExceptionIfServiceUnavailable();
745
746 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700747 IImsConfig config = mImsService.getConfigInterface(mPhoneId);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500748 if (config == null) {
749 throw new ImsException("getConfigInterface()",
750 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
751 }
Libin.Tang@motorola.com54953c72014-08-07 15:02:08 -0500752 mConfig = new ImsConfig(config, mContext);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500753 } catch (RemoteException e) {
754 throw new ImsException("getConfigInterface()", e,
755 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
756 }
757 }
758 if (DBG) log("getConfigInterface(), mConfig= " + mConfig);
759 return mConfig;
760 }
761
Etan Cohen82f78122014-12-15 10:10:14 -0800762 public void setUiTTYMode(Context context, int serviceId, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530763 throws ImsException {
764
Etan Cohen82f78122014-12-15 10:10:14 -0800765 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530766
Etan Cohen82f78122014-12-15 10:10:14 -0800767 try {
768 mImsService.setUiTTYMode(serviceId, uiTtyMode, onComplete);
769 } catch (RemoteException e) {
770 throw new ImsException("setTTYMode()", e,
771 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
772 }
773
Junda Liue7663c02015-06-23 11:16:26 -0700774 if (!getBooleanCarrierConfig(context,
775 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800776 setAdvanced4GMode((uiTtyMode == TelecomManager.TTY_MODE_OFF) &&
777 isEnhanced4gLteModeSettingEnabledByUser(context));
778 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530779 }
780
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500781 /**
Junda Liue7663c02015-06-23 11:16:26 -0700782 * Get the boolean config from carrier config manager.
783 *
784 * @param context the context to get carrier service
785 * @param key config key defined in CarrierConfigManager
786 * @return boolean value of corresponding key.
787 */
788 private static boolean getBooleanCarrierConfig(Context context, String key) {
789 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
790 Context.CARRIER_CONFIG_SERVICE);
791 if (configManager != null) {
792 return configManager.getConfig().getBoolean(key);
793 } else {
794 // Return static default defined in CarrierConfigManager.
795 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
796 }
797 }
798
799 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700800 * Gets the call ID from the specified incoming call broadcast intent.
801 *
802 * @param incomingCallIntent the incoming call broadcast intent
803 * @return the call ID or null if the intent does not contain it
804 */
805 private static String getCallId(Intent incomingCallIntent) {
806 if (incomingCallIntent == null) {
807 return null;
808 }
809
810 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
811 }
812
813 /**
814 * Gets the service type from the specified incoming call broadcast intent.
815 *
816 * @param incomingCallIntent the incoming call broadcast intent
817 * @return the service identifier or -1 if the intent does not contain it
818 */
819 private static int getServiceId(Intent incomingCallIntent) {
820 if (incomingCallIntent == null) {
821 return (-1);
822 }
823
824 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
825 }
826
827 /**
828 * Binds the IMS service only if the service is not created.
829 */
830 private void checkAndThrowExceptionIfServiceUnavailable()
831 throws ImsException {
832 if (mImsService == null) {
833 createImsService(true);
834
835 if (mImsService == null) {
836 throw new ImsException("Service is unavailable",
837 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
838 }
839 }
840 }
841
Etan Cohenabbd7882014-09-26 22:35:35 -0700842 private static String getImsServiceName(int phoneId) {
843 // TODO: MSIM implementation needs to decide on service name as a function of phoneId
Etan Cohend7727462014-07-12 14:54:10 -0700844 return IMS_SERVICE;
845 }
846
Wink Savilleef36ef62014-06-11 08:39:38 -0700847 /**
848 * Binds the IMS service to make/receive the call.
849 */
850 private void createImsService(boolean checkService) {
851 if (checkService) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700852 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -0700853
854 if (binder == null) {
855 return;
856 }
857 }
858
Etan Cohenabbd7882014-09-26 22:35:35 -0700859 IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -0700860
861 if (b != null) {
862 try {
863 b.linkToDeath(mDeathRecipient, 0);
864 } catch (RemoteException e) {
865 }
866 }
867
868 mImsService = IImsService.Stub.asInterface(b);
869 }
870
871 /**
872 * Creates a {@link ImsCallSession} with the specified call profile.
873 * Use other methods, if applicable, instead of interacting with
874 * {@link ImsCallSession} directly.
875 *
876 * @param serviceId a service id which is obtained from {@link ImsManager#open}
877 * @param profile a call profile to make the call
878 */
879 private ImsCallSession createCallSession(int serviceId,
880 ImsCallProfile profile) throws ImsException {
881 try {
882 return new ImsCallSession(mImsService.createCallSession(serviceId, profile, null));
883 } catch (RemoteException e) {
884 return null;
885 }
886 }
887
888 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass,
889 ImsConnectionStateListener listener) {
890 ImsRegistrationListenerProxy proxy =
891 new ImsRegistrationListenerProxy(serviceClass, listener);
892 return proxy;
893 }
894
Etan Cohena00c9192014-12-23 15:02:29 -0800895 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700896 Rlog.d(TAG, s);
897 }
898
Etan Cohena00c9192014-12-23 15:02:29 -0800899 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700900 Rlog.e(TAG, s);
901 }
902
Etan Cohena00c9192014-12-23 15:02:29 -0800903 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700904 Rlog.e(TAG, s, t);
905 }
906
907 /**
ram7da5a112014-07-16 20:59:27 +0530908 * Used for turning on IMS.if its off already
909 */
Etan Cohen82f78122014-12-15 10:10:14 -0800910 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -0700911 checkAndThrowExceptionIfServiceUnavailable();
912
ram7da5a112014-07-16 20:59:27 +0530913 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700914 mImsService.turnOnIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +0530915 } catch (RemoteException e) {
916 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
917 }
918 }
919
Etan Cohen82f78122014-12-15 10:10:14 -0800920 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
Etan Cohencfc784d2014-08-07 18:40:31 -0700921 checkAndThrowExceptionIfServiceUnavailable();
922
923 ImsConfig config = getConfigInterface();
924 if (config != null) {
925 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
926 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
Etan Cohenb651fa52014-10-22 10:51:29 -0700927 if (isVtEnabledByPlatform(mContext)) {
928 // TODO: once VT is available on platform replace the '1' with the current
929 // user configuration of VT.
930 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
931 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
932 }
Etan Cohencfc784d2014-08-07 18:40:31 -0700933 }
934
935 if (turnOn) {
936 turnOnIms();
Junda Liue7663c02015-06-23 11:16:26 -0700937 } else if (getBooleanCarrierConfig(mContext,
938 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800939 && (!isWfcEnabledByPlatform(mContext)
940 || !isWfcEnabledByUser(mContext))) {
Etan Cohencfc784d2014-08-07 18:40:31 -0700941 log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms");
942 turnOffIms();
943 }
944 }
945
ram7da5a112014-07-16 20:59:27 +0530946 /**
947 * Used for turning off IMS completely in order to make the device CSFB'ed.
948 * Once turned off, all calls will be over CS.
949 */
Etan Cohen82f78122014-12-15 10:10:14 -0800950 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -0700951 checkAndThrowExceptionIfServiceUnavailable();
952
ram7da5a112014-07-16 20:59:27 +0530953 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700954 mImsService.turnOffIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +0530955 } catch (RemoteException e) {
956 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
957 }
958 }
959
960 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700961 * Death recipient class for monitoring IMS service.
962 */
963 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
964 @Override
965 public void binderDied() {
966 mImsService = null;
967 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500968 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700969 mEcbm = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700970
971 if (mContext != null) {
Etan Cohend7727462014-07-12 14:54:10 -0700972 Intent intent = new Intent(ACTION_IMS_SERVICE_DOWN);
Etan Cohenabbd7882014-09-26 22:35:35 -0700973 intent.putExtra(EXTRA_PHONE_ID, mPhoneId);
Etan Cohend7727462014-07-12 14:54:10 -0700974 mContext.sendBroadcast(new Intent(intent));
Wink Savilleef36ef62014-06-11 08:39:38 -0700975 }
976 }
977 }
978
979 /**
980 * Adapter class for {@link IImsRegistrationListener}.
981 */
982 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
983 private int mServiceClass;
984 private ImsConnectionStateListener mListener;
985
986 public ImsRegistrationListenerProxy(int serviceClass,
987 ImsConnectionStateListener listener) {
988 mServiceClass = serviceClass;
989 mListener = listener;
990 }
991
992 public boolean isSameProxy(int serviceClass) {
993 return (mServiceClass == serviceClass);
994 }
995
996 @Override
997 public void registrationConnected() {
998 if (DBG) {
999 log("registrationConnected ::");
1000 }
1001
1002 if (mListener != null) {
1003 mListener.onImsConnected();
1004 }
1005 }
1006
1007 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08001008 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07001009 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08001010 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07001011 }
1012
1013 if (mListener != null) {
Rekha Kumar14631742015-02-04 10:47:00 -08001014 mListener.onImsProgressing();
1015 }
1016 }
1017
1018 @Override
1019 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
1020 if (DBG) {
1021 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
1022 }
1023
1024 if (mListener != null) {
1025 mListener.onImsDisconnected(imsReasonInfo);
Wink Savilleef36ef62014-06-11 08:39:38 -07001026 }
1027 }
1028
1029 @Override
1030 public void registrationResumed() {
1031 if (DBG) {
1032 log("registrationResumed ::");
1033 }
1034
1035 if (mListener != null) {
1036 mListener.onImsResumed();
1037 }
1038 }
1039
1040 @Override
1041 public void registrationSuspended() {
1042 if (DBG) {
1043 log("registrationSuspended ::");
1044 }
1045
1046 if (mListener != null) {
1047 mListener.onImsSuspended();
1048 }
1049 }
1050
1051 @Override
1052 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
1053 log("registrationServiceCapabilityChanged :: serviceClass=" +
1054 serviceClass + ", event=" + event);
1055
1056 if (mListener != null) {
1057 mListener.onImsConnected();
1058 }
1059 }
ram7da5a112014-07-16 20:59:27 +05301060
1061 @Override
1062 public void registrationFeatureCapabilityChanged(int serviceClass,
1063 int[] enabledFeatures, int[] disabledFeatures) {
1064 log("registrationFeatureCapabilityChanged :: serviceClass=" +
1065 serviceClass);
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05001066 if (mListener != null) {
1067 mListener.onFeatureCapabilityChanged(serviceClass,
1068 enabledFeatures, disabledFeatures);
1069 }
ram7da5a112014-07-16 20:59:27 +05301070 }
1071
Wink Savilleef36ef62014-06-11 08:39:38 -07001072 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001073 /**
1074 * Gets the ECBM interface to request ECBM exit.
1075 *
1076 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1077 * @return the ECBM interface instance
1078 * @throws ImsException if getting the ECBM interface results in an error
1079 */
1080 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
1081 if (mEcbm == null) {
1082 checkAndThrowExceptionIfServiceUnavailable();
1083
1084 try {
1085 IImsEcbm iEcbm = mImsService.getEcbmInterface(serviceId);
1086
1087 if (iEcbm == null) {
1088 throw new ImsException("getEcbmInterface()",
1089 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
1090 }
1091 mEcbm = new ImsEcbm(iEcbm);
1092 } catch (RemoteException e) {
1093 throw new ImsException("getEcbmInterface()", e,
1094 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1095 }
1096 }
1097 return mEcbm;
1098 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001099}