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