blob: b33517f5fe756ac2caafd6c61656a4d9942c55e8 [file] [log] [blame]
Wink Savilleef36ef62014-06-11 08:39:38 -07001/*
2 * Copyright (c) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.ims;
18
19import android.app.PendingIntent;
20import android.content.Context;
21import android.content.Intent;
Wink Savilleef36ef62014-06-11 08:39:38 -070022import android.os.IBinder;
23import android.os.IBinder.DeathRecipient;
24import android.os.Message;
25import android.os.Process;
26import android.os.RemoteException;
27import android.os.ServiceManager;
28import android.telephony.Rlog;
Etan Cohencfc784d2014-08-07 18:40:31 -070029import android.telephony.TelephonyManager;
Wink Savilleef36ef62014-06-11 08:39:38 -070030
31import com.android.ims.internal.IImsCallSession;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -070032import com.android.ims.internal.IImsEcbm;
33import com.android.ims.internal.IImsEcbmListener;
Wink Savilleef36ef62014-06-11 08:39:38 -070034import com.android.ims.internal.IImsRegistrationListener;
35import com.android.ims.internal.IImsService;
36import com.android.ims.internal.IImsUt;
37import com.android.ims.internal.ImsCallSession;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -050038import com.android.ims.internal.IImsConfig;
39
Etan Cohend7727462014-07-12 14:54:10 -070040import java.util.HashMap;
41
Wink Savilleef36ef62014-06-11 08:39:38 -070042/**
43 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to
44 * the operator's IMS network. This class is the starting point for any IMS actions.
45 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p>
46 * <p>The APIs in this class allows you to:</p>
47 *
48 * @hide
49 */
50public class ImsManager {
51 /**
52 * For accessing the IMS related service.
53 * Internal use only.
54 * @hide
55 */
Etan Cohend7727462014-07-12 14:54:10 -070056 private static final String IMS_SERVICE = "ims";
Wink Savilleef36ef62014-06-11 08:39:38 -070057
58 /**
59 * The result code to be sent back with the incoming call {@link PendingIntent}.
60 * @see #open(PendingIntent, ImsConnectionStateListener)
61 */
62 public static final int INCOMING_CALL_RESULT_CODE = 101;
63
64 /**
65 * Key to retrieve the call ID from an incoming call intent.
66 * @see #open(PendingIntent, ImsConnectionStateListener)
67 */
68 public static final String EXTRA_CALL_ID = "android:imsCallID";
69
70 /**
71 * Action to broadcast when ImsService is up.
72 * Internal use only.
73 * @hide
74 */
75 public static final String ACTION_IMS_SERVICE_UP =
76 "com.android.ims.IMS_SERVICE_UP";
77
78 /**
79 * Action to broadcast when ImsService is down.
80 * Internal use only.
81 * @hide
82 */
83 public static final String ACTION_IMS_SERVICE_DOWN =
84 "com.android.ims.IMS_SERVICE_DOWN";
85
86 /**
Etan Cohend7727462014-07-12 14:54:10 -070087 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
88 * A long value; the subId corresponding to the IMS service coming up or down.
89 * Internal use only.
90 * @hide
91 */
92 public static final String EXTRA_SUBID = "android:subid";
93
94 /**
Wink Savilleef36ef62014-06-11 08:39:38 -070095 * Action for the incoming call intent for the Phone app.
96 * Internal use only.
97 * @hide
98 */
99 public static final String ACTION_IMS_INCOMING_CALL =
100 "com.android.ims.IMS_INCOMING_CALL";
101
102 /**
103 * Part of the ACTION_IMS_INCOMING_CALL intents.
104 * An integer value; service identifier obtained from {@link ImsManager#open}.
105 * Internal use only.
106 * @hide
107 */
108 public static final String EXTRA_SERVICE_ID = "android:imsServiceId";
109
110 /**
111 * Part of the ACTION_IMS_INCOMING_CALL intents.
112 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD.
113 * The value "true" indicates that the incoming call is for USSD.
114 * Internal use only.
115 * @hide
116 */
117 public static final String EXTRA_USSD = "android:ussd";
118
119
120
121 private static final String TAG = "ImsManager";
122 private static final boolean DBG = true;
123
Etan Cohend7727462014-07-12 14:54:10 -0700124 private static HashMap<Long, ImsManager> sImsManagerInstances =
125 new HashMap<Long, ImsManager>();
126
Wink Savilleef36ef62014-06-11 08:39:38 -0700127 private Context mContext;
Etan Cohend7727462014-07-12 14:54:10 -0700128 private long mSubId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700129 private IImsService mImsService = null;
130 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient();
131 // Ut interface for the supplementary service configuration
132 private ImsUt mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500133 // Interface to get/set ims config items
134 private ImsConfig mConfig = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700135
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700136 // ECBM interface
137 private ImsEcbm mEcbm = null;
138
Wink Savilleef36ef62014-06-11 08:39:38 -0700139 /**
140 * Gets a manager instance.
141 *
142 * @param context application context for creating the manager object
Etan Cohend7727462014-07-12 14:54:10 -0700143 * @param subId the subscription ID for the IMS Service
144 * @return the manager instance corresponding to the subId
Wink Savilleef36ef62014-06-11 08:39:38 -0700145 */
Etan Cohend7727462014-07-12 14:54:10 -0700146 public static ImsManager getInstance(Context context, long subId) {
147 synchronized (sImsManagerInstances) {
148 if (sImsManagerInstances.containsKey(subId))
149 return sImsManagerInstances.get(subId);
Wink Savilleef36ef62014-06-11 08:39:38 -0700150
Etan Cohend7727462014-07-12 14:54:10 -0700151 ImsManager mgr = new ImsManager(context, subId);
152 sImsManagerInstances.put(subId, mgr);
153
154 return mgr;
155 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700156 }
157
Etan Cohend7727462014-07-12 14:54:10 -0700158 private ImsManager(Context context, long subId) {
Wink Savilleef36ef62014-06-11 08:39:38 -0700159 mContext = context;
Etan Cohend7727462014-07-12 14:54:10 -0700160 mSubId = subId;
Wink Savilleef36ef62014-06-11 08:39:38 -0700161 createImsService(true);
162 }
163
164 /**
165 * Opens the IMS service for making calls and/or receiving generic IMS calls.
166 * The caller may make subsquent calls through {@link #makeCall}.
167 * The IMS service will register the device to the operator's network with the credentials
168 * (from ISIM) periodically in order to receive calls from the operator's network.
169 * When the IMS service receives a new call, it will send out an intent with
170 * the provided action string.
171 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call.
172 *
173 * @param serviceClass a service class specified in {@link ImsServiceClass}
174 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}.
175 * @param incomingCallPendingIntent When an incoming call is received,
176 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to
177 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE}
178 * as the result code and the intent to fill in the call ID; It cannot be null
179 * @param listener To listen to IMS registration events; It cannot be null
180 * @return identifier (greater than 0) for the specified service
181 * @throws NullPointerException if {@code incomingCallPendingIntent}
182 * or {@code listener} is null
183 * @throws ImsException if calling the IMS service results in an error
184 * @see #getCallId
185 * @see #getServiceId
186 */
187 public int open(int serviceClass, PendingIntent incomingCallPendingIntent,
188 ImsConnectionStateListener listener) throws ImsException {
189 checkAndThrowExceptionIfServiceUnavailable();
190
191 if (incomingCallPendingIntent == null) {
192 throw new NullPointerException("incomingCallPendingIntent can't be null");
193 }
194
195 if (listener == null) {
196 throw new NullPointerException("listener can't be null");
197 }
198
199 int result = 0;
200
201 try {
202 result = mImsService.open(serviceClass, incomingCallPendingIntent,
203 createRegistrationListenerProxy(serviceClass, listener));
204 } catch (RemoteException e) {
205 throw new ImsException("open()", e,
206 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
207 }
208
209 if (result <= 0) {
210 // If the return value is a minus value,
211 // it means that an error occurred in the service.
212 // So, it needs to convert to the reason code specified in ImsReasonInfo.
213 throw new ImsException("open()", (result * (-1)));
214 }
215
216 return result;
217 }
218
219 /**
220 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls.
221 * All the resources that were allocated to the service are also released.
222 *
223 * @param serviceId a service id to be closed which is obtained from {@link ImsManager#open}
224 * @throws ImsException if calling the IMS service results in an error
225 */
226 public void close(int serviceId) throws ImsException {
227 checkAndThrowExceptionIfServiceUnavailable();
228
229 try {
230 mImsService.close(serviceId);
231 } catch (RemoteException e) {
232 throw new ImsException("close()", e,
233 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
234 } finally {
235 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500236 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700237 mEcbm = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700238 }
239 }
240
241 /**
242 * Gets the configuration interface to provision / withdraw the supplementary service settings.
243 *
244 * @param serviceId a service id which is obtained from {@link ImsManager#open}
245 * @return the Ut interface instance
246 * @throws ImsException if getting the Ut interface results in an error
247 */
248 public ImsUtInterface getSupplementaryServiceConfiguration(int serviceId)
249 throws ImsException {
250 // FIXME: manage the multiple Ut interfaces based on the service id
251 if (mUt == null) {
252 checkAndThrowExceptionIfServiceUnavailable();
253
254 try {
255 IImsUt iUt = mImsService.getUtInterface(serviceId);
256
257 if (iUt == null) {
258 throw new ImsException("getSupplementaryServiceConfiguration()",
259 ImsReasonInfo.CODE_UT_NOT_SUPPORTED);
260 }
261
262 mUt = new ImsUt(iUt);
263 } catch (RemoteException e) {
264 throw new ImsException("getSupplementaryServiceConfiguration()", e,
265 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
266 }
267 }
268
269 return mUt;
270 }
271
272 /**
273 * Checks if the IMS service has successfully registered to the IMS network
274 * with the specified service & call type.
275 *
276 * @param serviceId a service id which is obtained from {@link ImsManager#open}
277 * @param serviceType a service type that is specified in {@link ImsCallProfile}
278 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
279 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
280 * @param callType a call type that is specified in {@link ImsCallProfile}
281 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO}
282 * {@link ImsCallProfile#CALL_TYPE_VOICE}
283 * {@link ImsCallProfile#CALL_TYPE_VT}
284 * {@link ImsCallProfile#CALL_TYPE_VS}
285 * @return true if the specified service id is connected to the IMS network;
286 * false otherwise
287 * @throws ImsException if calling the IMS service results in an error
288 */
289 public boolean isConnected(int serviceId, int serviceType, int callType)
290 throws ImsException {
291 checkAndThrowExceptionIfServiceUnavailable();
292
293 try {
294 return mImsService.isConnected(serviceId, serviceType, callType);
295 } catch (RemoteException e) {
296 throw new ImsException("isServiceConnected()", e,
297 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
298 }
299 }
300
301 /**
302 * Checks if the specified IMS service is opend.
303 *
304 * @param serviceId a service id which is obtained from {@link ImsManager#open}
305 * @return true if the specified service id is opened; false otherwise
306 * @throws ImsException if calling the IMS service results in an error
307 */
308 public boolean isOpened(int serviceId) throws ImsException {
309 checkAndThrowExceptionIfServiceUnavailable();
310
311 try {
312 return mImsService.isOpened(serviceId);
313 } catch (RemoteException e) {
314 throw new ImsException("isOpened()", e,
315 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
316 }
317 }
318
319 /**
320 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
321 *
322 * @param serviceId a service id which is obtained from {@link ImsManager#open}
323 * @param serviceType a service type that is specified in {@link ImsCallProfile}
324 * {@link ImsCallProfile#SERVICE_TYPE_NONE}
325 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
326 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
327 * @param callType a call type that is specified in {@link ImsCallProfile}
328 * {@link ImsCallProfile#CALL_TYPE_VOICE}
329 * {@link ImsCallProfile#CALL_TYPE_VT}
330 * {@link ImsCallProfile#CALL_TYPE_VT_TX}
331 * {@link ImsCallProfile#CALL_TYPE_VT_RX}
332 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
333 * {@link ImsCallProfile#CALL_TYPE_VS}
334 * {@link ImsCallProfile#CALL_TYPE_VS_TX}
335 * {@link ImsCallProfile#CALL_TYPE_VS_RX}
336 * @return a {@link ImsCallProfile} object
337 * @throws ImsException if calling the IMS service results in an error
338 */
339 public ImsCallProfile createCallProfile(int serviceId,
340 int serviceType, int callType) throws ImsException {
341 checkAndThrowExceptionIfServiceUnavailable();
342
343 try {
344 return mImsService.createCallProfile(serviceId, serviceType, callType);
345 } catch (RemoteException e) {
346 throw new ImsException("createCallProfile()", e,
347 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
348 }
349 }
350
351 /**
352 * Creates a {@link ImsCall} to make a call.
353 *
354 * @param serviceId a service id which is obtained from {@link ImsManager#open}
355 * @param profile a call profile to make the call
356 * (it contains service type, call type, media information, etc.)
357 * @param participants participants to invite the conference call
358 * @param listener listen to the call events from {@link ImsCall}
359 * @return a {@link ImsCall} object
360 * @throws ImsException if calling the IMS service results in an error
361 */
362 public ImsCall makeCall(int serviceId, ImsCallProfile profile, String[] callees,
363 ImsCall.Listener listener) throws ImsException {
364 if (DBG) {
365 log("makeCall :: serviceId=" + serviceId
366 + ", profile=" + profile + ", callees=" + callees);
367 }
368
369 checkAndThrowExceptionIfServiceUnavailable();
370
371 ImsCall call = new ImsCall(mContext, profile);
372
373 call.setListener(listener);
374 ImsCallSession session = createCallSession(serviceId, profile);
375
376 if ((callees != null) && (callees.length == 1)) {
377 call.start(session, callees[0]);
378 } else {
379 call.start(session, callees);
380 }
381
382 return call;
383 }
384
385 /**
386 * Creates a {@link ImsCall} to take an incoming call.
387 *
388 * @param serviceId a service id which is obtained from {@link ImsManager#open}
389 * @param incomingCallIntent the incoming call broadcast intent
390 * @param listener to listen to the call events from {@link ImsCall}
391 * @return a {@link ImsCall} object
392 * @throws ImsException if calling the IMS service results in an error
393 */
394 public ImsCall takeCall(int serviceId, Intent incomingCallIntent,
395 ImsCall.Listener listener) throws ImsException {
396 if (DBG) {
397 log("takeCall :: serviceId=" + serviceId
398 + ", incomingCall=" + incomingCallIntent);
399 }
400
401 checkAndThrowExceptionIfServiceUnavailable();
402
403 if (incomingCallIntent == null) {
404 throw new ImsException("Can't retrieve session with null intent",
405 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
406 }
407
408 int incomingServiceId = getServiceId(incomingCallIntent);
409
410 if (serviceId != incomingServiceId) {
411 throw new ImsException("Service id is mismatched in the incoming call intent",
412 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
413 }
414
415 String callId = getCallId(incomingCallIntent);
416
417 if (callId == null) {
418 throw new ImsException("Call ID missing in the incoming call intent",
419 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
420 }
421
422 try {
423 IImsCallSession session = mImsService.getPendingCallSession(serviceId, callId);
424
425 if (session == null) {
426 throw new ImsException("No pending session for the call",
427 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL);
428 }
429
430 ImsCall call = new ImsCall(mContext, session.getCallProfile());
431
432 call.attachSession(new ImsCallSession(session));
433 call.setListener(listener);
434
435 return call;
436 } catch (Throwable t) {
437 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED);
438 }
439 }
440
441 /**
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500442 * Gets the config interface to get/set service/capability parameters.
443 *
444 * @return the ImsConfig instance.
445 * @throws ImsException if getting the setting interface results in an error.
446 */
447 public ImsConfig getConfigInterface() throws ImsException {
448
449 if (mConfig == null) {
450 checkAndThrowExceptionIfServiceUnavailable();
451
452 try {
453 IImsConfig config = mImsService.getConfigInterface();
454 if (config == null) {
455 throw new ImsException("getConfigInterface()",
456 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
457 }
458 mConfig = new ImsConfig(config);
459 } catch (RemoteException e) {
460 throw new ImsException("getConfigInterface()", e,
461 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
462 }
463 }
464 if (DBG) log("getConfigInterface(), mConfig= " + mConfig);
465 return mConfig;
466 }
467
468 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700469 * Gets the call ID from the specified incoming call broadcast intent.
470 *
471 * @param incomingCallIntent the incoming call broadcast intent
472 * @return the call ID or null if the intent does not contain it
473 */
474 private static String getCallId(Intent incomingCallIntent) {
475 if (incomingCallIntent == null) {
476 return null;
477 }
478
479 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
480 }
481
482 /**
483 * Gets the service type from the specified incoming call broadcast intent.
484 *
485 * @param incomingCallIntent the incoming call broadcast intent
486 * @return the service identifier or -1 if the intent does not contain it
487 */
488 private static int getServiceId(Intent incomingCallIntent) {
489 if (incomingCallIntent == null) {
490 return (-1);
491 }
492
493 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1);
494 }
495
496 /**
497 * Binds the IMS service only if the service is not created.
498 */
499 private void checkAndThrowExceptionIfServiceUnavailable()
500 throws ImsException {
501 if (mImsService == null) {
502 createImsService(true);
503
504 if (mImsService == null) {
505 throw new ImsException("Service is unavailable",
506 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
507 }
508 }
509 }
510
Etan Cohend7727462014-07-12 14:54:10 -0700511 private static String getImsServiceName(long subId) {
512 // TODO: MSIM implementation needs to decide on service name as a function of subId
513 // or value derived from subId (slot ID?)
514 return IMS_SERVICE;
515 }
516
Wink Savilleef36ef62014-06-11 08:39:38 -0700517 /**
518 * Binds the IMS service to make/receive the call.
519 */
520 private void createImsService(boolean checkService) {
521 if (checkService) {
Etan Cohend7727462014-07-12 14:54:10 -0700522 IBinder binder = ServiceManager.checkService(getImsServiceName(mSubId));
Wink Savilleef36ef62014-06-11 08:39:38 -0700523
524 if (binder == null) {
525 return;
526 }
527 }
528
Etan Cohend7727462014-07-12 14:54:10 -0700529 IBinder b = ServiceManager.getService(getImsServiceName(mSubId));
Wink Savilleef36ef62014-06-11 08:39:38 -0700530
531 if (b != null) {
532 try {
533 b.linkToDeath(mDeathRecipient, 0);
534 } catch (RemoteException e) {
535 }
536 }
537
538 mImsService = IImsService.Stub.asInterface(b);
539 }
540
541 /**
542 * Creates a {@link ImsCallSession} with the specified call profile.
543 * Use other methods, if applicable, instead of interacting with
544 * {@link ImsCallSession} directly.
545 *
546 * @param serviceId a service id which is obtained from {@link ImsManager#open}
547 * @param profile a call profile to make the call
548 */
549 private ImsCallSession createCallSession(int serviceId,
550 ImsCallProfile profile) throws ImsException {
551 try {
552 return new ImsCallSession(mImsService.createCallSession(serviceId, profile, null));
553 } catch (RemoteException e) {
554 return null;
555 }
556 }
557
558 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass,
559 ImsConnectionStateListener listener) {
560 ImsRegistrationListenerProxy proxy =
561 new ImsRegistrationListenerProxy(serviceClass, listener);
562 return proxy;
563 }
564
565 private void log(String s) {
566 Rlog.d(TAG, s);
567 }
568
569 private void loge(String s) {
570 Rlog.e(TAG, s);
571 }
572
573 private void loge(String s, Throwable t) {
574 Rlog.e(TAG, s, t);
575 }
576
577 /**
ram7da5a112014-07-16 20:59:27 +0530578 * Used for turning on IMS.if its off already
579 */
580 public void turnOnIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -0700581 checkAndThrowExceptionIfServiceUnavailable();
582
ram7da5a112014-07-16 20:59:27 +0530583 try {
584 mImsService.turnOnIms();
585 } catch (RemoteException e) {
586 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
587 }
588 }
589
Etan Cohencfc784d2014-08-07 18:40:31 -0700590 public void setAdvanced4GMode(boolean turnOn) throws ImsException {
591 checkAndThrowExceptionIfServiceUnavailable();
592
593 ImsConfig config = getConfigInterface();
594 if (config != null) {
595 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
596 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
597 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
598 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
599 }
600
601 if (turnOn) {
602 turnOnIms();
603 } else if (mContext.getResources().getBoolean(
604 com.android.internal.R.bool.imsServiceAllowTurnOff)) {
605 log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms");
606 turnOffIms();
607 }
608 }
609
ram7da5a112014-07-16 20:59:27 +0530610 /**
611 * Used for turning off IMS completely in order to make the device CSFB'ed.
612 * Once turned off, all calls will be over CS.
613 */
614 public void turnOffIms() throws ImsException {
Etan Cohen0c9c09e2014-07-25 11:09:12 -0700615 checkAndThrowExceptionIfServiceUnavailable();
616
ram7da5a112014-07-16 20:59:27 +0530617 try {
618 mImsService.turnOffIms();
619 } catch (RemoteException e) {
620 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
621 }
622 }
623
624 /**
Wink Savilleef36ef62014-06-11 08:39:38 -0700625 * Death recipient class for monitoring IMS service.
626 */
627 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient {
628 @Override
629 public void binderDied() {
630 mImsService = null;
631 mUt = null;
Libin.Tang@motorola.com076c55d2014-06-23 19:46:36 -0500632 mConfig = null;
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700633 mEcbm = null;
Wink Savilleef36ef62014-06-11 08:39:38 -0700634
635 if (mContext != null) {
Etan Cohend7727462014-07-12 14:54:10 -0700636 Intent intent = new Intent(ACTION_IMS_SERVICE_DOWN);
637 intent.putExtra(EXTRA_SUBID, mSubId);
638 mContext.sendBroadcast(new Intent(intent));
Wink Savilleef36ef62014-06-11 08:39:38 -0700639 }
640 }
641 }
642
643 /**
644 * Adapter class for {@link IImsRegistrationListener}.
645 */
646 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
647 private int mServiceClass;
648 private ImsConnectionStateListener mListener;
649
650 public ImsRegistrationListenerProxy(int serviceClass,
651 ImsConnectionStateListener listener) {
652 mServiceClass = serviceClass;
653 mListener = listener;
654 }
655
656 public boolean isSameProxy(int serviceClass) {
657 return (mServiceClass == serviceClass);
658 }
659
660 @Override
661 public void registrationConnected() {
662 if (DBG) {
663 log("registrationConnected ::");
664 }
665
666 if (mListener != null) {
667 mListener.onImsConnected();
668 }
669 }
670
671 @Override
672 public void registrationDisconnected() {
673 if (DBG) {
674 log("registrationDisconnected ::");
675 }
676
677 if (mListener != null) {
678 mListener.onImsDisconnected();
679 }
680 }
681
682 @Override
683 public void registrationResumed() {
684 if (DBG) {
685 log("registrationResumed ::");
686 }
687
688 if (mListener != null) {
689 mListener.onImsResumed();
690 }
691 }
692
693 @Override
694 public void registrationSuspended() {
695 if (DBG) {
696 log("registrationSuspended ::");
697 }
698
699 if (mListener != null) {
700 mListener.onImsSuspended();
701 }
702 }
703
704 @Override
705 public void registrationServiceCapabilityChanged(int serviceClass, int event) {
706 log("registrationServiceCapabilityChanged :: serviceClass=" +
707 serviceClass + ", event=" + event);
708
709 if (mListener != null) {
710 mListener.onImsConnected();
711 }
712 }
ram7da5a112014-07-16 20:59:27 +0530713
714 @Override
715 public void registrationFeatureCapabilityChanged(int serviceClass,
716 int[] enabledFeatures, int[] disabledFeatures) {
717 log("registrationFeatureCapabilityChanged :: serviceClass=" +
718 serviceClass);
719 }
720
Wink Savilleef36ef62014-06-11 08:39:38 -0700721 }
Uma Maheswari Ramalingam4f2161d2014-07-31 16:01:47 -0700722 /**
723 * Gets the ECBM interface to request ECBM exit.
724 *
725 * @param serviceId a service id which is obtained from {@link ImsManager#open}
726 * @return the ECBM interface instance
727 * @throws ImsException if getting the ECBM interface results in an error
728 */
729 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException {
730 if (mEcbm == null) {
731 checkAndThrowExceptionIfServiceUnavailable();
732
733 try {
734 IImsEcbm iEcbm = mImsService.getEcbmInterface(serviceId);
735
736 if (iEcbm == null) {
737 throw new ImsException("getEcbmInterface()",
738 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED);
739 }
740 mEcbm = new ImsEcbm(iEcbm);
741 } catch (RemoteException e) {
742 throw new ImsException("getEcbmInterface()", e,
743 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
744 }
745 }
746 return mEcbm;
747 }
Wink Savilleef36ef62014-06-11 08:39:38 -0700748}