blob: 47d1405a23c00e187af4423a59e764a704d9ee69 [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;
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;
Wink Savilleef36ef62014-06-11 08:39:38 -070039import com.android.ims.internal.IImsRegistrationListener;
40import com.android.ims.internal.IImsService;
41import com.android.ims.internal.IImsUt;
42import com.android.ims.internal.ImsCallSession;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050043import com.android.ims.internal.IImsConfig;
44
Etan Cohend7727462014-07-12 14:54:10 -070045import java.util.HashMap;
46
Wink Savilleef36ef62014-06-11 08:39:38 -070047/**
48 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
49 * the operator's IMS network. This class is the starting point for any IMS actions.
50 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
51 * <p>The APIs in this class allows you to:</p>
52 *
53 * @hide
54 */
55public class ImsManager {
Etan Cohen19604c02014-08-11 14:32:57 -070056
Etan Cohenaf55a402014-09-04 22:34:41 -070057 /*
58 * Debug flag to override configuration flag
59 */
Etan Cohenb651fa52014-10-22 10:51:29 -070060 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr";
61 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenea2b5832014-10-23 18:50:35 -070062 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr";
63 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohena00c9192014-12-23 15:02:29 -080064 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr";
65 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0;
Etan Cohenaf55a402014-09-04 22:34:41 -070066
Wink Savilleef36ef62014-06-11 08:39:38 -070067 /**
68 * For accessing the IMS related service.
69 * Internal use only.
70 * @hide
71 */
Etan Cohend7727462014-07-12 14:54:10 -070072 private static final String IMS_SERVICE = "ims";
Wink Savilleef36ef62014-06-11 08:39:38 -070073
74 /**
75 * The result code to be sent back with the incoming call {@link PendingIntent}.
76 * @see #open(PendingIntent, ImsConnectionStateListener)
77 */
78 public static final int INCOMING_CALL_RESULT_CODE = 101;
79
80 /**
81 * Key to retrieve the call ID from an incoming call intent.
82 * @see #open(PendingIntent, ImsConnectionStateListener)
83 */
84 public static final String EXTRA_CALL_ID = "android:imsCallID";
85
86 /**
87 * Action to broadcast when ImsService is up.
88 * Internal use only.
89 * @hide
90 */
91 public static final String ACTION_IMS_SERVICE_UP =
92 "com.android.ims.IMS_SERVICE_UP";
93
94 /**
95 * Action to broadcast when ImsService is down.
96 * Internal use only.
97 * @hide
98 */
99 public static final String ACTION_IMS_SERVICE_DOWN =
100 "com.android.ims.IMS_SERVICE_DOWN";
101
102 /**
Pavel Zhamaitsiak0c2f15c2015-03-12 15:37:54 -0700103 * Action to broadcast when ImsService registration fails.
104 * Internal use only.
105 * @hide
106 */
107 public static final String ACTION_IMS_REGISTRATION_ERROR =
108 "com.android.ims.REGISTRATION_ERROR";
109
110 /**
Etan Cohend7727462014-07-12 14:54:10 -0700111 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
Etan Cohenabbd7882014-09-26 22:35:35 -0700112 * A long value; the phone ID corresponding to the IMS service coming up or down.
Etan Cohend7727462014-07-12 14:54:10 -0700113 * Internal use only.
114 * @hide
115 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700116 public static final String EXTRA_PHONE_ID = "android:phone_id";
Etan Cohend7727462014-07-12 14:54:10 -0700117
118 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700119 * Action for the incoming call intent for the Phone app.
120 * Internal use only.
121 * @hide
122 */
123 public static final String ACTION_IMS_INCOMING_CALL =
124 "com.android.ims.IMS_INCOMING_CALL";
125
126 /**
127 * Part of the ACTION_IMS_INCOMING_CALL intents.
128 * An integer value; service identifier obtained from {@link ImsManager#open}.
129 * Internal use only.
130 * @hide
131 */
132 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
133
134 /**
135 * Part of the ACTION_IMS_INCOMING_CALL intents.
136 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
137 * The value "true" indicates that the incoming call is for USSD.
138 * Internal use only.
139 * @hide
140 */
141 public static final String EXTRA_USSD = "android:ussd";
142
Wink Savilleef36ef62014-06-11 08:39:38 -0700143 private static final String TAG = "ImsManager";
144 private static final boolean DBG = true;
145
Wink Saville1e5a38a2014-10-23 10:24:46 -0700146 private static HashMap<Integer, ImsManager> sImsManagerInstances =
147 new HashMap<Integer, ImsManager>();
Etan Cohend7727462014-07-12 14:54:10 -0700148
Wink Savilleef36ef62014-06-11 08:39:38 -0700149 private Context mContext;
Etan Cohenabbd7882014-09-26 22:35:35 -0700150 private int mPhoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700151 private IImsService mImsService = null;
152 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
153 // Ut interface for the supplementary service configuration
154 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500155 // Interface to get/set ims config items
156 private ImsConfig mConfig = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700157
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700158 // ECBM interface
159 private ImsEcbm mEcbm = null;
160
Wink Savilleef36ef62014-06-11 08:39:38 -0700161 /**
162 * Gets a manager instance.
163 *
164 * @param context application context for creating the manager object
Etan Cohenabbd7882014-09-26 22:35:35 -0700165 * @param phoneId the phone ID for the IMS Service
166 * @return the manager instance corresponding to the phoneId
Wink Savilleef36ef62014-06-11 08:39:38 -0700167 */
Etan Cohenabbd7882014-09-26 22:35:35 -0700168 public static ImsManager getInstance(Context context, int phoneId) {
Etan Cohend7727462014-07-12 14:54:10 -0700169 synchronized (sImsManagerInstances) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700170 if (sImsManagerInstances.containsKey(phoneId))
171 return sImsManagerInstances.get(phoneId);
Wink Savilleef36ef62014-06-11 08:39:38 -0700172
Etan Cohenabbd7882014-09-26 22:35:35 -0700173 ImsManager mgr = new ImsManager(context, phoneId);
174 sImsManagerInstances.put(phoneId, mgr);
Etan Cohend7727462014-07-12 14:54:10 -0700175
176 return mgr;
177 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700178 }
179
Etan Cohen45b5f312014-08-19 15:55:08 -0700180 /**
181 * Returns the user configuration of Enhanced 4G LTE Mode setting
182 */
183 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) {
Libin.Tang@motorola.com8a6bf4b2014-10-10 15:02:41 -0500184 int enabled = android.provider.Settings.Global.getInt(
185 context.getContentResolver(),
Etan Cohenb651fa52014-10-22 10:51:29 -0700186 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
Etan Cohena00c9192014-12-23 15:02:29 -0800187 return (enabled == 1) ? true : false;
Etan Cohen45b5f312014-08-19 15:55:08 -0700188 }
189
190 /**
Etan Cohen82f78122014-12-15 10:10:14 -0800191 * Change persistent Enhanced 4G LTE Mode setting
192 */
193 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
194 int value = enabled ? 1 : 0;
195 android.provider.Settings.Global.putInt(
196 context.getContentResolver(),
197 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
198
199 if (isNonTtyOrTtyOnVolteEnabled(context)) {
200 ImsManager imsManager = ImsManager.getInstance(context,
201 SubscriptionManager.getDefaultVoicePhoneId());
202 if (imsManager != null) {
203 try {
204 imsManager.setAdvanced4GMode(enabled);
205 } catch (ImsException ie) {
206 // do nothing
207 }
208 }
209 }
210 }
211
212 /**
213 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is
214 * supported.
215 */
216 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) {
Junda Liue7663c02015-06-23 11:16:26 -0700217 if (getBooleanCarrierConfig(context,
218 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800219 return true;
220 }
221
222 return Settings.Secure.getInt(context.getContentResolver(),
223 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF)
224 == TelecomManager.TTY_MODE_OFF;
225 }
226
227 /**
Etan Cohenea2b5832014-10-23 18:50:35 -0700228 * Returns a platform configuration for VoLTE which may override the user setting.
Etan Cohen45b5f312014-08-19 15:55:08 -0700229 */
Etan Cohenea2b5832014-10-23 18:50:35 -0700230 public static boolean isVolteEnabledByPlatform(Context context) {
Etan Cohenb651fa52014-10-22 10:51:29 -0700231 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
232 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
Etan Cohenaf55a402014-09-04 22:34:41 -0700233 return true;
234 }
235
Etan Cohenb5388a32014-11-26 11:57:47 -0800236 return context.getResources().getBoolean(
Junda Liue7663c02015-06-23 11:16:26 -0700237 com.android.internal.R.bool.config_device_volte_available)
238 && getBooleanCarrierConfig(context,
Junda Liu7e16d5d2015-07-22 12:23:46 -0700239 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL);
Etan Cohenb5388a32014-11-26 11:57:47 -0800240 }
241
242 /*
243 * Indicates whether VoLTE is provisioned on device
244 */
245 public static boolean isVolteProvisionedOnDevice(Context context) {
246 boolean isProvisioned = true;
Junda Liue7663c02015-06-23 11:16:26 -0700247 if (getBooleanCarrierConfig(context,
248 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {
Etan Cohenb5388a32014-11-26 11:57:47 -0800249 isProvisioned = false; // disable on any error
250 ImsManager mgr = ImsManager.getInstance(context,
Jonathan Basserid7133652015-04-07 19:54:24 -0700251 SubscriptionManager.getDefaultVoicePhoneId());
Etan Cohenb5388a32014-11-26 11:57:47 -0800252 if (mgr != null) {
253 try {
254 ImsConfig config = mgr.getConfigInterface();
255 if (config != null) {
256 isProvisioned = config.getVolteProvisioned();
257 }
258 } catch (ImsException ie) {
259 // do nothing
260 }
261 }
262 }
263
264 return isProvisioned;
Etan Cohenb651fa52014-10-22 10:51:29 -0700265 }
266
Etan Cohenea2b5832014-10-23 18:50:35 -0700267 /**
268 * Returns a platform configuration for VT which may override the user setting.
269 *
270 * Note: VT presumes that VoLTE is enabled (these are configuration settings
271 * which must be done correctly).
272 */
Etan Cohenb651fa52014-10-22 10:51:29 -0700273 public static boolean isVtEnabledByPlatform(Context context) {
Etan Cohenea2b5832014-10-23 18:50:35 -0700274 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
275 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
276 return true;
277 }
278
Etan Cohenb651fa52014-10-22 10:51:29 -0700279 return
280 context.getResources().getBoolean(
281 com.android.internal.R.bool.config_device_vt_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700282 getBooleanCarrierConfig(context,
283 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL);
Etan Cohen45b5f312014-08-19 15:55:08 -0700284 }
285
Etan Cohena00c9192014-12-23 15:02:29 -0800286 /**
287 * Returns the user configuration of WFC setting
288 */
289 public static boolean isWfcEnabledByUser(Context context) {
290 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
291 android.provider.Settings.Global.WFC_IMS_ENABLED,
Pavel Zhamaitsiakeb13a592015-04-27 09:44:33 -0700292 ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800293 return (enabled == 1) ? true : false;
294 }
295
296 /**
297 * Change persistent WFC enabled setting
298 */
299 public static void setWfcSetting(Context context, boolean enabled) {
300 int value = enabled ? 1 : 0;
301 android.provider.Settings.Global.putInt(context.getContentResolver(),
302 android.provider.Settings.Global.WFC_IMS_ENABLED, value);
303
304 ImsManager imsManager = ImsManager.getInstance(context,
305 SubscriptionManager.getDefaultVoicePhoneId());
306 if (imsManager != null) {
307 try {
308 ImsConfig config = imsManager.getConfigInterface();
Etan Cohena00c9192014-12-23 15:02:29 -0800309 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI,
Nathan Harold3a99f782015-07-24 15:02:34 -0700310 TelephonyManager.NETWORK_TYPE_IWLAN,
Etan Cohena00c9192014-12-23 15:02:29 -0800311 enabled ? ImsConfig.FeatureValueConstants.ON
312 : ImsConfig.FeatureValueConstants.OFF, null);
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800313
314 if (enabled) {
315 imsManager.turnOnIms();
Junda Liue7663c02015-06-23 11:16:26 -0700316 } else if (getBooleanCarrierConfig(context,
317 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800318 && (!isVolteEnabledByPlatform(context)
319 || !isEnhanced4gLteModeSettingEnabledByUser(context))) {
320 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms");
321 imsManager.turnOffIms();
322 }
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700323
324 // Force IMS to register over LTE when turning off WFC
325 setWfcModeInternal(context, enabled
326 ? getWfcMode(context)
327 : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED);
Etan Cohena00c9192014-12-23 15:02:29 -0800328 } catch (ImsException e) {
Pavel Zhamaitsiak183af602015-02-24 10:20:27 -0800329 loge("setWfcSetting(): " + e);
Etan Cohena00c9192014-12-23 15:02:29 -0800330 }
331 }
332 }
333
334 /**
335 * Returns the user configuration of WFC modem setting
336 */
337 public static int getWfcMode(Context context) {
338 int setting = android.provider.Settings.Global.getInt(context.getContentResolver(),
339 android.provider.Settings.Global.WFC_IMS_MODE,
340 ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED);
341 if (DBG) log("getWfcMode - setting=" + setting);
342 return setting;
343 }
344
345 /**
346 * Returns the user configuration of WFC modem setting
347 */
348 public static void setWfcMode(Context context, int wfcMode) {
349 if (DBG) log("setWfcMode - setting=" + wfcMode);
350 android.provider.Settings.Global.putInt(context.getContentResolver(),
351 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode);
352
Pavel Zhamaitsiak9e6eca22015-03-16 15:30:53 -0700353 setWfcModeInternal(context, wfcMode);
354 }
355
356 private static void setWfcModeInternal(Context context, int wfcMode) {
Etan Cohena00c9192014-12-23 15:02:29 -0800357 final ImsManager imsManager = ImsManager.getInstance(context,
358 SubscriptionManager.getDefaultVoicePhoneId());
359 if (imsManager != null) {
360 final int value = wfcMode;
361 QueuedWork.singleThreadExecutor().submit(new Runnable() {
362 public void run() {
363 try {
364 imsManager.getConfigInterface().setProvisionedValue(
365 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE,
366 value);
367 } catch (ImsException e) {
368 // do nothing
369 }
370 }
371 });
372 }
373 }
374
375 /**
376 * Returns the user configuration of WFC roaming setting
377 */
378 public static boolean isWfcRoamingEnabledByUser(Context context) {
379 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
380 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED,
Pavel Zhamaitsiak28c84002015-03-10 16:42:01 -0700381 ImsConfig.FeatureValueConstants.OFF);
Etan Cohena00c9192014-12-23 15:02:29 -0800382 return (enabled == 1) ? true : false;
383 }
384
385 /**
386 * Change persistent WFC roaming enabled setting
387 */
388 public static void setWfcRoamingSetting(Context context, boolean enabled) {
389 final int value = enabled
390 ? ImsConfig.FeatureValueConstants.ON
391 : ImsConfig.FeatureValueConstants.OFF;
392 android.provider.Settings.Global.putInt(context.getContentResolver(),
393 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, value);
394
395 final ImsManager imsManager = ImsManager.getInstance(context,
396 SubscriptionManager.getDefaultVoicePhoneId());
397 if (imsManager != null) {
398 QueuedWork.singleThreadExecutor().submit(new Runnable() {
399 public void run() {
400 try {
401 imsManager.getConfigInterface().setProvisionedValue(
402 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING,
403 value);
404 } catch (ImsException e) {
405 // do nothing
406 }
407 }
408 });
409 }
410 }
411
412 /**
413 * Returns a platform configuration for WFC which may override the user
414 * setting. Note: WFC presumes that VoLTE is enabled (these are
415 * configuration settings which must be done correctly).
416 */
417 public static boolean isWfcEnabledByPlatform(Context context) {
418 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
419 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
420 return true;
421 }
422
423 return
424 context.getResources().getBoolean(
425 com.android.internal.R.bool.config_device_wfc_ims_available) &&
Junda Liue7663c02015-06-23 11:16:26 -0700426 getBooleanCarrierConfig(context,
427 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL);
Etan Cohena00c9192014-12-23 15:02:29 -0800428 }
429
Etan Cohenabbd7882014-09-26 22:35:35 -0700430 private ImsManager(Context context, int phoneId) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700431 mContext = context;
Etan Cohenabbd7882014-09-26 22:35:35 -0700432 mPhoneId = phoneId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700433 createImsService(true);
434 }
435
Etan Cohenf4311122015-02-26 17:47:13 -0800436 /*
437 * Returns a flag indicating whether the IMS service is available.
438 */
439 public boolean isServiceAvailable() {
440 if (mImsService != null) {
441 return true;
442 }
443
444 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
445 if (binder != null) {
446 return true;
447 }
448
449 return false;
450 }
451
Wink Savilleef36ef62014-06-11 08:39:38 -0700452 /**
453 * Opens the IMS service for making calls and/or receiving generic IMS calls.
454 * The caller may make subsquent calls through {@link #makeCall}.
455 * The IMS service will register the device to the operator's network with the credentials
456 * (from ISIM) periodically in order to receive calls from the operator's network.
457 * When the IMS service receives a new call, it will send out an intent with
458 * the provided action string.
459 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
460 *
461 * @param serviceClass a service class specified in {@link ImsServiceClass}
462 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
463 * @param incomingCallPendingIntent When an incoming call is received,
464 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
465 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
466 * as the result code and the intent to fill in the call ID; It cannot be null
467 * @param listener To listen to IMS registration events; It cannot be null
468 * @return identifier (greater than 0) for the specified service
469 * @throws NullPointerException if {@code incomingCallPendingIntent}
470 * or {@code listener} is null
471 * @throws ImsException if calling the IMS service results in an error
472 * @see #getCallId
473 * @see #getServiceId
474 */
475 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
476 ImsConnectionStateListener listener) throws ImsException {
477 checkAndThrowExceptionIfServiceUnavailable();
478
479 if (incomingCallPendingIntent == null) {
480 throw new NullPointerException("incomingCallPendingIntent can't be null");
481 }
482
483 if (listener == null) {
484 throw new NullPointerException("listener can't be null");
485 }
486
487 int result = 0;
488
489 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700490 result = mImsService.open(mPhoneId, serviceClass, incomingCallPendingIntent,
Wink Savilleef36ef62014-06-11 08:39:38 -0700491 createRegistrationListenerProxy(serviceClass, listener));
492 } catch (RemoteException e) {
493 throw new ImsException("open()", e,
494 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
495 }
496
497 if (result <= 0) {
498 // If the return value is a minus value,
499 // it means that an error occurred in the service.
500 // So, it needs to convert to the reason code specified in ImsReasonInfo.
501 throw new ImsException("open()", (result * (-1)));
502 }
503
504 return result;
505 }
506
507 /**
508 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
509 * All the resources that were allocated to the service are also released.
510 *
511 * @param serviceId a service id to be closed which is obtained from {@link ImsManager#open}
512 * @throws ImsException if calling the IMS service results in an error
513 */
514 public void close(int serviceId) throws ImsException {
515 checkAndThrowExceptionIfServiceUnavailable();
516
517 try {
518 mImsService.close(serviceId);
519 } catch (RemoteException e) {
520 throw new ImsException("close()", e,
521 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
522 } finally {
523 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500524 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700525 mEcbm = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700526 }
527 }
528
529 /**
530 * Gets the configuration interface to provision / withdraw the supplementary service settings.
531 *
532 * @param serviceId a service id which is obtained from {@link ImsManager#open}
533 * @return the Ut interface instance
534 * @throws ImsException if getting the Ut interface results in an error
535 */
536 public ImsUtInterface getSupplementaryServiceConfiguration(int serviceId)
537 throws ImsException {
538 // FIXME: manage the multiple Ut interfaces based on the service id
539 if (mUt == null) {
540 checkAndThrowExceptionIfServiceUnavailable();
541
542 try {
543 IImsUt iUt = mImsService.getUtInterface(serviceId);
544
545 if (iUt == null) {
546 throw new ImsException("getSupplementaryServiceConfiguration()",
547 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
548 }
549
550 mUt = new ImsUt(iUt);
551 } catch (RemoteException e) {
552 throw new ImsException("getSupplementaryServiceConfiguration()", e,
553 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
554 }
555 }
556
557 return mUt;
558 }
559
560 /**
561 * Checks if the IMS service has successfully registered to the IMS network
562 * with the specified service & call type.
563 *
564 * @param serviceId a service id which is obtained from {@link ImsManager#open}
565 * @param serviceType a service type that is specified in {@link ImsCallProfile}
566 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
567 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
568 * @param callType a call type that is specified in {@link ImsCallProfile}
569 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
570 * {@link ImsCallProfile#CALL_TYPE_VOICE}
571 * {@link ImsCallProfile#CALL_TYPE_VT}
572 * {@link ImsCallProfile#CALL_TYPE_VS}
573 * @return true if the specified service id is connected to the IMS network;
574 * false otherwise
575 * @throws ImsException if calling the IMS service results in an error
576 */
577 public boolean isConnected(int serviceId, int serviceType, int callType)
578 throws ImsException {
579 checkAndThrowExceptionIfServiceUnavailable();
580
581 try {
582 return mImsService.isConnected(serviceId, serviceType, callType);
583 } catch (RemoteException e) {
584 throw new ImsException("isServiceConnected()", e,
585 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
586 }
587 }
588
589 /**
590 * Checks if the specified IMS service is opend.
591 *
592 * @param serviceId a service id which is obtained from {@link ImsManager#open}
593 * @return true if the specified service id is opened; false otherwise
594 * @throws ImsException if calling the IMS service results in an error
595 */
596 public boolean isOpened(int serviceId) throws ImsException {
597 checkAndThrowExceptionIfServiceUnavailable();
598
599 try {
600 return mImsService.isOpened(serviceId);
601 } catch (RemoteException e) {
602 throw new ImsException("isOpened()", e,
603 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
604 }
605 }
606
607 /**
608 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
609 *
610 * @param serviceId a service id which is obtained from {@link ImsManager#open}
611 * @param serviceType a service type that is specified in {@link ImsCallProfile}
612 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
613 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
614 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
615 * @param callType a call type that is specified in {@link ImsCallProfile}
616 * {@link ImsCallProfile#CALL_TYPE_VOICE}
617 * {@link ImsCallProfile#CALL_TYPE_VT}
618 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
619 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
620 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
621 * {@link ImsCallProfile#CALL_TYPE_VS}
622 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
623 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
624 * @return a {@link ImsCallProfile} object
625 * @throws ImsException if calling the IMS service results in an error
626 */
627 public ImsCallProfile createCallProfile(int serviceId,
628 int serviceType, int callType) throws ImsException {
629 checkAndThrowExceptionIfServiceUnavailable();
630
631 try {
632 return mImsService.createCallProfile(serviceId, serviceType, callType);
633 } catch (RemoteException e) {
634 throw new ImsException("createCallProfile()", e,
635 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
636 }
637 }
638
639 /**
640 * Creates a {@link ImsCall} to make a call.
641 *
642 * @param serviceId a service id which is obtained from {@link ImsManager#open}
643 * @param profile a call profile to make the call
644 * (it contains service type, call type, media information, etc.)
645 * @param participants participants to invite the conference call
646 * @param listener listen to the call events from {@link ImsCall}
647 * @return a {@link ImsCall} object
648 * @throws ImsException if calling the IMS service results in an error
649 */
650 public ImsCall makeCall(int serviceId, ImsCallProfile profile, String[] callees,
651 ImsCall.Listener listener) throws ImsException {
652 if (DBG) {
653 log("makeCall :: serviceId=" + serviceId
654 + ", profile=" + profile + ", callees=" + callees);
655 }
656
657 checkAndThrowExceptionIfServiceUnavailable();
658
659 ImsCall call = new ImsCall(mContext, profile);
660
661 call.setListener(listener);
662 ImsCallSession session = createCallSession(serviceId, profile);
663
664 if ((callees != null) && (callees.length == 1)) {
665 call.start(session, callees[0]);
666 } else {
667 call.start(session, callees);
668 }
669
670 return call;
671 }
672
673 /**
674 * Creates a {@link ImsCall} to take an incoming call.
675 *
676 * @param serviceId a service id which is obtained from {@link ImsManager#open}
677 * @param incomingCallIntent the incoming call broadcast intent
678 * @param listener to listen to the call events from {@link ImsCall}
679 * @return a {@link ImsCall} object
680 * @throws ImsException if calling the IMS service results in an error
681 */
682 public ImsCall takeCall(int serviceId, Intent incomingCallIntent,
683 ImsCall.Listener listener) throws ImsException {
684 if (DBG) {
685 log("takeCall :: serviceId=" + serviceId
686 + ", incomingCall=" + incomingCallIntent);
687 }
688
689 checkAndThrowExceptionIfServiceUnavailable();
690
691 if (incomingCallIntent == null) {
692 throw new ImsException("Can't retrieve session with null intent",
693 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
694 }
695
696 int incomingServiceId = getServiceId(incomingCallIntent);
697
698 if (serviceId != incomingServiceId) {
699 throw new ImsException("Service id is mismatched in the incoming call intent",
700 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
701 }
702
703 String callId = getCallId(incomingCallIntent);
704
705 if (callId == null) {
706 throw new ImsException("Call ID missing in the incoming call intent",
707 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
708 }
709
710 try {
711 IImsCallSession session = mImsService.getPendingCallSession(serviceId, callId);
712
713 if (session == null) {
714 throw new ImsException("No pending session for the call",
715 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
716 }
717
718 ImsCall call = new ImsCall(mContext, session.getCallProfile());
719
720 call.attachSession(new ImsCallSession(session));
721 call.setListener(listener);
722
723 return call;
724 } catch (Throwable t) {
725 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
726 }
727 }
728
729 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500730 * Gets the config interface to get/set service/capability parameters.
731 *
732 * @return the ImsConfig instance.
733 * @throws ImsException if getting the setting interface results in an error.
734 */
735 public ImsConfig getConfigInterface() throws ImsException {
736
737 if (mConfig == null) {
738 checkAndThrowExceptionIfServiceUnavailable();
739
740 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700741 IImsConfig config = mImsService.getConfigInterface(mPhoneId);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500742 if (config == null) {
743 throw new ImsException("getConfigInterface()",
744 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
745 }
Libin.Tang@motorola.com54953c72014-08-07 15:02:08 -0500746 mConfig = new ImsConfig(config, mContext);
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500747 } catch (RemoteException e) {
748 throw new ImsException("getConfigInterface()", e,
749 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
750 }
751 }
752 if (DBG) log("getConfigInterface(), mConfig= " + mConfig);
753 return mConfig;
754 }
755
Etan Cohen82f78122014-12-15 10:10:14 -0800756 public void setUiTTYMode(Context context, int serviceId, int uiTtyMode, Message onComplete)
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530757 throws ImsException {
758
Etan Cohen82f78122014-12-15 10:10:14 -0800759 checkAndThrowExceptionIfServiceUnavailable();
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530760
Etan Cohen82f78122014-12-15 10:10:14 -0800761 try {
762 mImsService.setUiTTYMode(serviceId, uiTtyMode, onComplete);
763 } catch (RemoteException e) {
764 throw new ImsException("setTTYMode()", e,
765 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
766 }
767
Junda Liue7663c02015-06-23 11:16:26 -0700768 if (!getBooleanCarrierConfig(context,
769 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) {
Etan Cohen82f78122014-12-15 10:10:14 -0800770 setAdvanced4GMode((uiTtyMode == TelecomManager.TTY_MODE_OFF) &&
771 isEnhanced4gLteModeSettingEnabledByUser(context));
772 }
Shriram Ganeshc403b7b2014-08-14 14:18:57 +0530773 }
774
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500775 /**
Junda Liue7663c02015-06-23 11:16:26 -0700776 * Get the boolean config from carrier config manager.
777 *
778 * @param context the context to get carrier service
779 * @param key config key defined in CarrierConfigManager
780 * @return boolean value of corresponding key.
781 */
782 private static boolean getBooleanCarrierConfig(Context context, String key) {
783 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
784 Context.CARRIER_CONFIG_SERVICE);
Jonathan Basseri2acea6f2015-07-01 15:00:38 -0700785 PersistableBundle b = null;
Junda Liue7663c02015-06-23 11:16:26 -0700786 if (configManager != null) {
Jonathan Basseri2acea6f2015-07-01 15:00:38 -0700787 b = configManager.getConfig();
788 }
789 if (b != null) {
790 return b.getBoolean(key);
Junda Liue7663c02015-06-23 11:16:26 -0700791 } else {
792 // Return static default defined in CarrierConfigManager.
793 return CarrierConfigManager.getDefaultConfig().getBoolean(key);
794 }
795 }
796
797 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700798 * Gets the call ID from the specified incoming call broadcast intent.
799 *
800 * @param incomingCallIntent the incoming call broadcast intent
801 * @return the call ID or null if the intent does not contain it
802 */
803 private static String getCallId(Intent incomingCallIntent) {
804 if (incomingCallIntent == null) {
805 return null;
806 }
807
808 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
809 }
810
811 /**
812 * Gets the service type from the specified incoming call broadcast intent.
813 *
814 * @param incomingCallIntent the incoming call broadcast intent
815 * @return the service identifier or -1 if the intent does not contain it
816 */
817 private static int getServiceId(Intent incomingCallIntent) {
818 if (incomingCallIntent == null) {
819 return (-1);
820 }
821
822 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
823 }
824
825 /**
826 * Binds the IMS service only if the service is not created.
827 */
828 private void checkAndThrowExceptionIfServiceUnavailable()
829 throws ImsException {
830 if (mImsService == null) {
831 createImsService(true);
832
833 if (mImsService == null) {
834 throw new ImsException("Service is unavailable",
835 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
836 }
837 }
838 }
839
Etan Cohenabbd7882014-09-26 22:35:35 -0700840 private static String getImsServiceName(int phoneId) {
841 // TODO: MSIM implementation needs to decide on service name as a function of phoneId
Etan Cohend7727462014-07-12 14:54:10 -0700842 return IMS_SERVICE;
843 }
844
Wink Savilleef36ef62014-06-11 08:39:38 -0700845 /**
846 * Binds the IMS service to make/receive the call.
847 */
848 private void createImsService(boolean checkService) {
849 if (checkService) {
Etan Cohenabbd7882014-09-26 22:35:35 -0700850 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -0700851
852 if (binder == null) {
853 return;
854 }
855 }
856
Etan Cohenabbd7882014-09-26 22:35:35 -0700857 IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId));
Wink Savilleef36ef62014-06-11 08:39:38 -0700858
859 if (b != null) {
860 try {
861 b.linkToDeath(mDeathRecipient, 0);
862 } catch (RemoteException e) {
863 }
864 }
865
866 mImsService = IImsService.Stub.asInterface(b);
867 }
868
869 /**
870 * Creates a {@link ImsCallSession} with the specified call profile.
871 * Use other methods, if applicable, instead of interacting with
872 * {@link ImsCallSession} directly.
873 *
874 * @param serviceId a service id which is obtained from {@link ImsManager#open}
875 * @param profile a call profile to make the call
876 */
877 private ImsCallSession createCallSession(int serviceId,
878 ImsCallProfile profile) throws ImsException {
879 try {
880 return new ImsCallSession(mImsService.createCallSession(serviceId, profile, null));
881 } catch (RemoteException e) {
882 return null;
883 }
884 }
885
886 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass,
887 ImsConnectionStateListener listener) {
888 ImsRegistrationListenerProxy proxy =
889 new ImsRegistrationListenerProxy(serviceClass, listener);
890 return proxy;
891 }
892
Etan Cohena00c9192014-12-23 15:02:29 -0800893 private static void log(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700894 Rlog.d(TAG, s);
895 }
896
Etan Cohena00c9192014-12-23 15:02:29 -0800897 private static void loge(String s) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700898 Rlog.e(TAG, s);
899 }
900
Etan Cohena00c9192014-12-23 15:02:29 -0800901 private static void loge(String s, Throwable t) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700902 Rlog.e(TAG, s, t);
903 }
904
905 /**
ram7da5a112014-07-16 20:59:27 +0530906 * Used for turning on IMS.if its off already
907 */
Etan Cohen82f78122014-12-15 10:10:14 -0800908 private void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -0700909 checkAndThrowExceptionIfServiceUnavailable();
910
ram7da5a112014-07-16 20:59:27 +0530911 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700912 mImsService.turnOnIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +0530913 } catch (RemoteException e) {
914 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
915 }
916 }
917
Omkar Kolangade75f3ca32014-10-24 11:10:52 -0700918 private boolean isImsTurnOffAllowed() {
919 return getBooleanCarrierConfig(mContext,
920 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)
921 && (!isWfcEnabledByPlatform(mContext)
922 || !isWfcEnabledByUser(mContext));
923 }
924
Etan Cohen82f78122014-12-15 10:10:14 -0800925 private void setAdvanced4GMode(boolean turnOn) throws ImsException {
Etan Cohencfc784d2014-08-07 18:40:31 -0700926 checkAndThrowExceptionIfServiceUnavailable();
927
Omkar Kolangade75f3ca32014-10-24 11:10:52 -0700928 try {
929 ImsConfig config = getConfigInterface();
930 if (config != null && (turnOn || !isImsTurnOffAllowed())) {
931 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
Etan Cohenb651fa52014-10-22 10:51:29 -0700932 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
Omkar Kolangade75f3ca32014-10-24 11:10:52 -0700933 if (isVtEnabledByPlatform(mContext)) {
934 // TODO: once VT is available on platform:
935 // - replace the '1' with the current user configuration of VT.
936 // - separate exception checks for setFeatureValue() failures for VoLTE and VT.
937 // I.e. if VoLTE fails still try to configure VT.
938 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
939 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
940 }
Etan Cohenb651fa52014-10-22 10:51:29 -0700941 }
Omkar Kolangade75f3ca32014-10-24 11:10:52 -0700942 } catch (ImsException e) {
943 log("setAdvanced4GMode() : " + e);
Etan Cohencfc784d2014-08-07 18:40:31 -0700944 }
Etan Cohencfc784d2014-08-07 18:40:31 -0700945 if (turnOn) {
946 turnOnIms();
Omkar Kolangade75f3ca32014-10-24 11:10:52 -0700947 } else if (isImsTurnOffAllowed()) {
Etan Cohencfc784d2014-08-07 18:40:31 -0700948 log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms");
949 turnOffIms();
950 }
951 }
952
ram7da5a112014-07-16 20:59:27 +0530953 /**
954 * Used for turning off IMS completely in order to make the device CSFB'ed.
955 * Once turned off, all calls will be over CS.
956 */
Etan Cohen82f78122014-12-15 10:10:14 -0800957 private void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -0700958 checkAndThrowExceptionIfServiceUnavailable();
959
ram7da5a112014-07-16 20:59:27 +0530960 try {
Etan Cohenabbd7882014-09-26 22:35:35 -0700961 mImsService.turnOffIms(mPhoneId);
ram7da5a112014-07-16 20:59:27 +0530962 } catch (RemoteException e) {
963 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
964 }
965 }
966
967 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700968 * Death recipient class for monitoring IMS service.
969 */
970 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
971 @Override
972 public void binderDied() {
973 mImsService = null;
974 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500975 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700976 mEcbm = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700977
978 if (mContext != null) {
Etan Cohend7727462014-07-12 14:54:10 -0700979 Intent intent = new Intent(ACTION_IMS_SERVICE_DOWN);
Etan Cohenabbd7882014-09-26 22:35:35 -0700980 intent.putExtra(EXTRA_PHONE_ID, mPhoneId);
Etan Cohend7727462014-07-12 14:54:10 -0700981 mContext.sendBroadcast(new Intent(intent));
Wink Savilleef36ef62014-06-11 08:39:38 -0700982 }
983 }
984 }
985
986 /**
987 * Adapter class for {@link IImsRegistrationListener}.
988 */
989 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
990 private int mServiceClass;
991 private ImsConnectionStateListener mListener;
992
993 public ImsRegistrationListenerProxy(int serviceClass,
994 ImsConnectionStateListener listener) {
995 mServiceClass = serviceClass;
996 mListener = listener;
997 }
998
999 public boolean isSameProxy(int serviceClass) {
1000 return (mServiceClass == serviceClass);
1001 }
1002
1003 @Override
1004 public void registrationConnected() {
1005 if (DBG) {
1006 log("registrationConnected ::");
1007 }
1008
1009 if (mListener != null) {
1010 mListener.onImsConnected();
1011 }
1012 }
1013
1014 @Override
Rekha Kumar14631742015-02-04 10:47:00 -08001015 public void registrationProgressing() {
Wink Savilleef36ef62014-06-11 08:39:38 -07001016 if (DBG) {
Rekha Kumar14631742015-02-04 10:47:00 -08001017 log("registrationProgressing ::");
Wink Savilleef36ef62014-06-11 08:39:38 -07001018 }
1019
1020 if (mListener != null) {
Rekha Kumar14631742015-02-04 10:47:00 -08001021 mListener.onImsProgressing();
1022 }
1023 }
1024
1025 @Override
1026 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
1027 if (DBG) {
1028 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo);
1029 }
1030
1031 if (mListener != null) {
1032 mListener.onImsDisconnected(imsReasonInfo);
Wink Savilleef36ef62014-06-11 08:39:38 -07001033 }
1034 }
1035
1036 @Override
1037 public void registrationResumed() {
1038 if (DBG) {
1039 log("registrationResumed ::");
1040 }
1041
1042 if (mListener != null) {
1043 mListener.onImsResumed();
1044 }
1045 }
1046
1047 @Override
1048 public void registrationSuspended() {
1049 if (DBG) {
1050 log("registrationSuspended ::");
1051 }
1052
1053 if (mListener != null) {
1054 mListener.onImsSuspended();
1055 }
1056 }
1057
1058 @Override
1059 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
1060 log("registrationServiceCapabilityChanged :: serviceClass=" +
1061 serviceClass + ", event=" + event);
1062
1063 if (mListener != null) {
1064 mListener.onImsConnected();
1065 }
1066 }
ram7da5a112014-07-16 20:59:27 +05301067
1068 @Override
1069 public void registrationFeatureCapabilityChanged(int serviceClass,
1070 int[] enabledFeatures, int[] disabledFeatures) {
1071 log("registrationFeatureCapabilityChanged :: serviceClass=" +
1072 serviceClass);
Libin.Tang@motorola.come2296782014-08-19 14:20:01 -05001073 if (mListener != null) {
1074 mListener.onFeatureCapabilityChanged(serviceClass,
1075 enabledFeatures, disabledFeatures);
1076 }
ram7da5a112014-07-16 20:59:27 +05301077 }
1078
Wink Savilleef36ef62014-06-11 08:39:38 -07001079 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -07001080 /**
1081 * Gets the ECBM interface to request ECBM exit.
1082 *
1083 * @param serviceId a service id which is obtained from {@link ImsManager#open}
1084 * @return the ECBM interface instance
1085 * @throws ImsException if getting the ECBM interface results in an error
1086 */
1087 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
1088 if (mEcbm == null) {
1089 checkAndThrowExceptionIfServiceUnavailable();
1090
1091 try {
1092 IImsEcbm iEcbm = mImsService.getEcbmInterface(serviceId);
1093
1094 if (iEcbm == null) {
1095 throw new ImsException("getEcbmInterface()",
1096 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
1097 }
1098 mEcbm = new ImsEcbm(iEcbm);
1099 } catch (RemoteException e) {
1100 throw new ImsException("getEcbmInterface()", e,
1101 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
1102 }
1103 }
1104 return mEcbm;
1105 }
Wink Savilleef36ef62014-06-11 08:39:38 -07001106}