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