ImsManager.java revision 47aeacf0b9b7412b70e8cab8e81f358efd032f2a
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.app.QueuedWork; 21import android.content.Context; 22import android.content.Intent; 23import android.content.SharedPreferences; 24import android.net.Uri; 25import android.os.IBinder; 26import android.os.Message; 27import android.os.PersistableBundle; 28import android.os.RemoteException; 29import android.os.ServiceManager; 30import android.os.SystemProperties; 31import android.preference.PreferenceManager; 32import android.provider.Settings; 33import android.telecom.TelecomManager; 34import android.telephony.CarrierConfigManager; 35import android.telephony.Rlog; 36import android.telephony.SubscriptionManager; 37import android.telephony.TelephonyManager; 38 39import com.android.ims.internal.IImsCallSession; 40import com.android.ims.internal.IImsEcbm; 41import com.android.ims.internal.IImsEcbmListener; 42import com.android.ims.internal.IImsRegistrationListener; 43import com.android.ims.internal.IImsService; 44import com.android.ims.internal.IImsUt; 45import com.android.ims.internal.ImsCallSession; 46import com.android.ims.internal.IImsConfig; 47 48import java.io.FileDescriptor; 49import java.io.PrintWriter; 50import java.util.HashMap; 51 52/** 53 * Provides APIs for IMS services, such as initiating IMS calls, and provides access to 54 * the operator's IMS network. This class is the starting point for any IMS actions. 55 * You can acquire an instance of it with {@link #getInstance getInstance()}.</p> 56 * <p>The APIs in this class allows you to:</p> 57 * 58 * @hide 59 */ 60public class ImsManager { 61 62 /* 63 * Debug flag to override configuration flag 64 */ 65 public static final String PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE = "persist.dbg.volte_avail_ovr"; 66 public static final int PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT = 0; 67 public static final String PROPERTY_DBG_VT_AVAIL_OVERRIDE = "persist.dbg.vt_avail_ovr"; 68 public static final int PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT = 0; 69 public static final String PROPERTY_DBG_WFC_AVAIL_OVERRIDE = "persist.dbg.wfc_avail_ovr"; 70 public static final int PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT = 0; 71 72 /** 73 * For accessing the IMS related service. 74 * Internal use only. 75 * @hide 76 */ 77 private static final String IMS_SERVICE = "ims"; 78 79 /** 80 * The result code to be sent back with the incoming call {@link PendingIntent}. 81 * @see #open(PendingIntent, ImsConnectionStateListener) 82 */ 83 public static final int INCOMING_CALL_RESULT_CODE = 101; 84 85 /** 86 * Key to retrieve the call ID from an incoming call intent. 87 * @see #open(PendingIntent, ImsConnectionStateListener) 88 */ 89 public static final String EXTRA_CALL_ID = "android:imsCallID"; 90 91 /** 92 * Action to broadcast when ImsService is up. 93 * Internal use only. 94 * @hide 95 */ 96 public static final String ACTION_IMS_SERVICE_UP = 97 "com.android.ims.IMS_SERVICE_UP"; 98 99 /** 100 * Action to broadcast when ImsService is down. 101 * Internal use only. 102 * @hide 103 */ 104 public static final String ACTION_IMS_SERVICE_DOWN = 105 "com.android.ims.IMS_SERVICE_DOWN"; 106 107 /** 108 * Action to broadcast when ImsService registration fails. 109 * Internal use only. 110 * @hide 111 */ 112 public static final String ACTION_IMS_REGISTRATION_ERROR = 113 "com.android.ims.REGISTRATION_ERROR"; 114 115 /** 116 * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents. 117 * A long value; the phone ID corresponding to the IMS service coming up or down. 118 * Internal use only. 119 * @hide 120 */ 121 public static final String EXTRA_PHONE_ID = "android:phone_id"; 122 123 /** 124 * Action for the incoming call intent for the Phone app. 125 * Internal use only. 126 * @hide 127 */ 128 public static final String ACTION_IMS_INCOMING_CALL = 129 "com.android.ims.IMS_INCOMING_CALL"; 130 131 /** 132 * Part of the ACTION_IMS_INCOMING_CALL intents. 133 * An integer value; service identifier obtained from {@link ImsManager#open}. 134 * Internal use only. 135 * @hide 136 */ 137 public static final String EXTRA_SERVICE_ID = "android:imsServiceId"; 138 139 /** 140 * Part of the ACTION_IMS_INCOMING_CALL intents. 141 * An boolean value; Flag to indicate that the incoming call is a normal call or call for USSD. 142 * The value "true" indicates that the incoming call is for USSD. 143 * Internal use only. 144 * @hide 145 */ 146 public static final String EXTRA_USSD = "android:ussd"; 147 148 /** 149 * Part of the ACTION_IMS_INCOMING_CALL intents. 150 * A boolean value; Flag to indicate whether the call is an unknown 151 * dialing call. Such calls are originated by sending commands (like 152 * AT commands) directly to modem without Android involvement. 153 * Even though they are not incoming calls, they are propagated 154 * to Phone app using same ACTION_IMS_INCOMING_CALL intent. 155 * Internal use only. 156 * @hide 157 */ 158 public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown"; 159 160 private static final String TAG = "ImsManager"; 161 private static final boolean DBG = true; 162 163 private static HashMap<Integer, ImsManager> sImsManagerInstances = 164 new HashMap<Integer, ImsManager>(); 165 166 private Context mContext; 167 private int mPhoneId; 168 private IImsService mImsService = null; 169 private ImsServiceDeathRecipient mDeathRecipient = new ImsServiceDeathRecipient(); 170 // Ut interface for the supplementary service configuration 171 private ImsUt mUt = null; 172 // Interface to get/set ims config items 173 private ImsConfig mConfig = null; 174 private boolean mConfigUpdated = false; 175 private static final String PREF_ENABLE_VIDEO_CALLING_KEY = "enable_video_calling"; 176 177 private ImsConfigListener mImsConfigListener; 178 179 // ECBM interface 180 private ImsEcbm mEcbm = null; 181 182 /** 183 * Gets a manager instance. 184 * 185 * @param context application context for creating the manager object 186 * @param phoneId the phone ID for the IMS Service 187 * @return the manager instance corresponding to the phoneId 188 */ 189 public static ImsManager getInstance(Context context, int phoneId) { 190 synchronized (sImsManagerInstances) { 191 if (sImsManagerInstances.containsKey(phoneId)) 192 return sImsManagerInstances.get(phoneId); 193 194 ImsManager mgr = new ImsManager(context, phoneId); 195 sImsManagerInstances.put(phoneId, mgr); 196 197 return mgr; 198 } 199 } 200 201 /** 202 * Returns the user configuration of Enhanced 4G LTE Mode setting 203 */ 204 public static boolean isEnhanced4gLteModeSettingEnabledByUser(Context context) { 205 // If user can't edit Enhanced 4G LTE Mode, it assumes Enhanced 4G LTE Mode is always true. 206 // If user changes SIM from editable mode to uneditable mode, need to return true. 207 if (!getBooleanCarrierConfig(context, 208 CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)) { 209 return true; 210 } 211 int enabled = android.provider.Settings.Global.getInt( 212 context.getContentResolver(), 213 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON); 214 return (enabled == 1) ? true : false; 215 } 216 217 /** 218 * Change persistent Enhanced 4G LTE Mode setting 219 */ 220 public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) { 221 int value = enabled ? 1 : 0; 222 android.provider.Settings.Global.putInt( 223 context.getContentResolver(), 224 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value); 225 226 if (isNonTtyOrTtyOnVolteEnabled(context)) { 227 ImsManager imsManager = ImsManager.getInstance(context, 228 SubscriptionManager.getDefaultVoicePhoneId()); 229 if (imsManager != null) { 230 try { 231 imsManager.setAdvanced4GMode(enabled); 232 } catch (ImsException ie) { 233 // do nothing 234 } 235 } 236 } 237 } 238 239 /** 240 * Indicates whether the call is non-TTY or if TTY - whether TTY on VoLTE is 241 * supported. 242 */ 243 public static boolean isNonTtyOrTtyOnVolteEnabled(Context context) { 244 if (getBooleanCarrierConfig(context, 245 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) { 246 return true; 247 } 248 249 return Settings.Secure.getInt(context.getContentResolver(), 250 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF) 251 == TelecomManager.TTY_MODE_OFF; 252 } 253 254 /** 255 * Returns a platform configuration for VoLTE which may override the user setting. 256 */ 257 public static boolean isVolteEnabledByPlatform(Context context) { 258 if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE, 259 PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) { 260 return true; 261 } 262 263 return context.getResources().getBoolean( 264 com.android.internal.R.bool.config_device_volte_available) 265 && getBooleanCarrierConfig(context, 266 CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL) 267 && isGbaValid(context); 268 } 269 270 /* 271 * Indicates whether VoLTE is provisioned on device 272 */ 273 public static boolean isVolteProvisionedOnDevice(Context context) { 274 boolean isProvisioned = true; 275 if (getBooleanCarrierConfig(context, 276 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) { 277 isProvisioned = false; // disable on any error 278 ImsManager mgr = ImsManager.getInstance(context, 279 SubscriptionManager.getDefaultVoicePhoneId()); 280 if (mgr != null) { 281 try { 282 ImsConfig config = mgr.getConfigInterface(); 283 if (config != null) { 284 isProvisioned = config.getVolteProvisioned(); 285 } 286 } catch (ImsException ie) { 287 // do nothing 288 } 289 } 290 } 291 292 return isProvisioned; 293 } 294 295 /** 296 * Returns a platform configuration for VT which may override the user setting. 297 * 298 * Note: VT presumes that VoLTE is enabled (these are configuration settings 299 * which must be done correctly). 300 */ 301 public static boolean isVtEnabledByPlatform(Context context) { 302 if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE, 303 PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) { 304 return true; 305 } 306 307 return 308 context.getResources().getBoolean( 309 com.android.internal.R.bool.config_device_vt_available) && 310 getBooleanCarrierConfig(context, 311 CarrierConfigManager.KEY_CARRIER_VT_AVAILABLE_BOOL) && 312 isGbaValid(context); 313 } 314 315 /** 316 * Returns the user configuration of VT setting 317 */ 318 public static boolean isVtEnabledByUser(Context context) { 319 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(), 320 android.provider.Settings.Global.VT_IMS_ENABLED, 321 ImsConfig.FeatureValueConstants.ON); 322 return (enabled == 1) ? true : false; 323 } 324 325 /** 326 * Change persistent VT enabled setting 327 */ 328 public static void setVtSetting(Context context, boolean enabled) { 329 int value = enabled ? 1 : 0; 330 android.provider.Settings.Global.putInt(context.getContentResolver(), 331 android.provider.Settings.Global.VT_IMS_ENABLED, value); 332 333 ImsManager imsManager = ImsManager.getInstance(context, 334 SubscriptionManager.getDefaultVoicePhoneId()); 335 if (imsManager != null) { 336 try { 337 ImsConfig config = imsManager.getConfigInterface(); 338 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE, 339 TelephonyManager.NETWORK_TYPE_LTE, 340 enabled ? ImsConfig.FeatureValueConstants.ON 341 : ImsConfig.FeatureValueConstants.OFF, 342 imsManager.mImsConfigListener); 343 344 if (enabled) { 345 imsManager.turnOnIms(); 346 } else if (getBooleanCarrierConfig(context, 347 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL) 348 && (!isVolteEnabledByPlatform(context) 349 || !isEnhanced4gLteModeSettingEnabledByUser(context))) { 350 log("setVtSetting() : imsServiceAllowTurnOff -> turnOffIms"); 351 imsManager.turnOffIms(); 352 } 353 } catch (ImsException e) { 354 loge("setVtSetting(): " + e); 355 } 356 } 357 } 358 359 /** 360 * Returns the user configuration of WFC setting 361 */ 362 public static boolean isWfcEnabledByUser(Context context) { 363 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(), 364 android.provider.Settings.Global.WFC_IMS_ENABLED, 365 getBooleanCarrierConfig(context, 366 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ? 367 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); 368 return (enabled == 1) ? true : false; 369 } 370 371 /** 372 * Change persistent WFC enabled setting 373 */ 374 public static void setWfcSetting(Context context, boolean enabled) { 375 int value = enabled ? 1 : 0; 376 android.provider.Settings.Global.putInt(context.getContentResolver(), 377 android.provider.Settings.Global.WFC_IMS_ENABLED, value); 378 379 ImsManager imsManager = ImsManager.getInstance(context, 380 SubscriptionManager.getDefaultVoicePhoneId()); 381 if (imsManager != null) { 382 try { 383 ImsConfig config = imsManager.getConfigInterface(); 384 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI, 385 TelephonyManager.NETWORK_TYPE_IWLAN, 386 enabled ? ImsConfig.FeatureValueConstants.ON 387 : ImsConfig.FeatureValueConstants.OFF, 388 imsManager.mImsConfigListener); 389 390 if (enabled) { 391 imsManager.turnOnIms(); 392 } else if (getBooleanCarrierConfig(context, 393 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL) 394 && (!isVolteEnabledByPlatform(context) 395 || !isEnhanced4gLteModeSettingEnabledByUser(context))) { 396 log("setWfcSetting() : imsServiceAllowTurnOff -> turnOffIms"); 397 imsManager.turnOffIms(); 398 } 399 400 // Force IMS to register over LTE when turning off WFC 401 setWfcModeInternal(context, enabled 402 ? getWfcMode(context) 403 : ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED); 404 } catch (ImsException e) { 405 loge("setWfcSetting(): " + e); 406 } 407 } 408 } 409 410 /** 411 * Returns the user configuration of WFC modem setting 412 */ 413 public static int getWfcMode(Context context) { 414 int setting = android.provider.Settings.Global.getInt(context.getContentResolver(), 415 android.provider.Settings.Global.WFC_IMS_MODE, getIntCarrierConfig(context, 416 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); 417 if (DBG) log("getWfcMode - setting=" + setting); 418 return setting; 419 } 420 421 /** 422 * Returns the user configuration of WFC modem setting 423 */ 424 public static void setWfcMode(Context context, int wfcMode) { 425 if (DBG) log("setWfcMode - setting=" + wfcMode); 426 android.provider.Settings.Global.putInt(context.getContentResolver(), 427 android.provider.Settings.Global.WFC_IMS_MODE, wfcMode); 428 429 setWfcModeInternal(context, wfcMode); 430 } 431 432 private static void setWfcModeInternal(Context context, int wfcMode) { 433 final ImsManager imsManager = ImsManager.getInstance(context, 434 SubscriptionManager.getDefaultVoicePhoneId()); 435 if (imsManager != null) { 436 final int value = wfcMode; 437 Thread thread = new Thread(new Runnable() { 438 public void run() { 439 try { 440 imsManager.getConfigInterface().setProvisionedValue( 441 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_MODE, 442 value); 443 } catch (ImsException e) { 444 // do nothing 445 } 446 } 447 }); 448 thread.start(); 449 } 450 } 451 452 /** 453 * Returns the user configuration of WFC roaming setting 454 */ 455 public static boolean isWfcRoamingEnabledByUser(Context context) { 456 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(), 457 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, 458 getBooleanCarrierConfig(context, 459 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ? 460 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); 461 return (enabled == 1) ? true : false; 462 } 463 464 /** 465 * Change persistent WFC roaming enabled setting 466 */ 467 public static void setWfcRoamingSetting(Context context, boolean enabled) { 468 android.provider.Settings.Global.putInt(context.getContentResolver(), 469 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, 470 enabled ? ImsConfig.FeatureValueConstants.ON 471 : ImsConfig.FeatureValueConstants.OFF); 472 473 setWfcRoamingSettingInternal(context, enabled); 474 } 475 476 private static void setWfcRoamingSettingInternal(Context context, boolean enabled) { 477 final ImsManager imsManager = ImsManager.getInstance(context, 478 SubscriptionManager.getDefaultVoicePhoneId()); 479 if (imsManager != null) { 480 final int value = enabled 481 ? ImsConfig.FeatureValueConstants.ON 482 : ImsConfig.FeatureValueConstants.OFF; 483 Thread thread = new Thread(new Runnable() { 484 public void run() { 485 try { 486 imsManager.getConfigInterface().setProvisionedValue( 487 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_ROAMING, 488 value); 489 } catch (ImsException e) { 490 // do nothing 491 } 492 } 493 }); 494 thread.start(); 495 } 496 } 497 498 /** 499 * Returns a platform configuration for WFC which may override the user 500 * setting. Note: WFC presumes that VoLTE is enabled (these are 501 * configuration settings which must be done correctly). 502 */ 503 public static boolean isWfcEnabledByPlatform(Context context) { 504 if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE, 505 PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) { 506 return true; 507 } 508 509 return 510 context.getResources().getBoolean( 511 com.android.internal.R.bool.config_device_wfc_ims_available) && 512 getBooleanCarrierConfig(context, 513 CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL) && 514 isGbaValid(context); 515 } 516 517 /** 518 * If carrier requires that IMS is only available if GBA capable SIM is used, 519 * then this function checks GBA bit in EF IST. 520 * 521 * Format of EF IST is defined in 3GPP TS 31.103 (Section 4.2.7). 522 */ 523 private static boolean isGbaValid(Context context) { 524 if (getBooleanCarrierConfig(context, 525 CarrierConfigManager.KEY_CARRIER_IMS_GBA_REQUIRED_BOOL)) { 526 final TelephonyManager telephonyManager = TelephonyManager.getDefault(); 527 String efIst = telephonyManager.getIsimIst(); 528 if (efIst == null) { 529 loge("ISF is NULL"); 530 return true; 531 } 532 boolean result = efIst != null && efIst.length() > 1 && 533 (0x02 & (byte)efIst.charAt(1)) != 0; 534 if (DBG) log("GBA capable=" + result + ", ISF=" + efIst); 535 return result; 536 } 537 return true; 538 } 539 540 /** 541 * Sync carrier config and user settings with ImsConfig. 542 * 543 * @param context for the manager object 544 * @param phoneId phone id 545 * @param force update 546 */ 547 public static void updateImsServiceConfig(Context context, int phoneId, boolean force) { 548 if (!force) { 549 if (TelephonyManager.getDefault().getSimState() != TelephonyManager.SIM_STATE_READY) { 550 log("updateImsServiceConfig: SIM not ready"); 551 // Don't disable IMS if SIM is not ready 552 return; 553 } 554 } 555 556 final ImsManager imsManager = ImsManager.getInstance(context, phoneId); 557 if (imsManager != null && (!imsManager.mConfigUpdated || force)) { 558 try { 559 boolean isImsUsed = imsManager.updateVolteFeatureValue(); 560 isImsUsed |= imsManager.updateVideoCallFeatureValue(); 561 isImsUsed |= imsManager.updateWfcFeatureAndProvisionedValues(); 562 563 if (isImsUsed || !getBooleanCarrierConfig(context, 564 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)) { 565 // Turn on IMS if it is used. 566 // Also, if turning off is not allowed for current carrier, 567 // we need to turn IMS on because it might be turned off before 568 // phone switched to current carrier. 569 imsManager.turnOnIms(); 570 } else { 571 // Turn off IMS if it is not used AND turning off is allowed for carrier. 572 imsManager.turnOffIms(); 573 } 574 575 imsManager.mConfigUpdated = true; 576 } catch (ImsException e) { 577 loge("updateImsServiceConfig: " + e); 578 imsManager.mConfigUpdated = false; 579 } 580 } 581 } 582 583 /** 584 * Update VoLTE config 585 * @return whether feature is On 586 * @throws ImsException 587 */ 588 private boolean updateVolteFeatureValue() throws ImsException { 589 boolean available = isVolteEnabledByPlatform(mContext); 590 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(mContext); 591 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(mContext); 592 boolean isFeatureOn = available && enabled && isNonTty; 593 594 log("updateVolteFeatureValue: available = " + available 595 + ", enabled = " + enabled 596 + ", nonTTY = " + isNonTty); 597 598 getConfigInterface().setFeatureValue( 599 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE, 600 TelephonyManager.NETWORK_TYPE_LTE, 601 isFeatureOn ? 602 ImsConfig.FeatureValueConstants.ON : 603 ImsConfig.FeatureValueConstants.OFF, 604 mImsConfigListener); 605 606 return isFeatureOn; 607 } 608 609 /** 610 * Update VC config 611 * @return whether feature is On 612 * @throws ImsException 613 */ 614 private boolean updateVideoCallFeatureValue() throws ImsException { 615 boolean available = isVtEnabledByPlatform(mContext); 616 SharedPreferences sharedPrefs = 617 PreferenceManager.getDefaultSharedPreferences(mContext); 618 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(mContext) && 619 sharedPrefs.getBoolean(PREF_ENABLE_VIDEO_CALLING_KEY, true); 620 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(mContext); 621 boolean isFeatureOn = available && enabled && isNonTty; 622 623 log("updateVideoCallFeatureValue: available = " + available 624 + ", enabled = " + enabled 625 + ", nonTTY = " + isNonTty); 626 627 getConfigInterface().setFeatureValue( 628 ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE, 629 TelephonyManager.NETWORK_TYPE_LTE, 630 isFeatureOn ? 631 ImsConfig.FeatureValueConstants.ON : 632 ImsConfig.FeatureValueConstants.OFF, 633 mImsConfigListener); 634 635 return isFeatureOn; 636 } 637 638 /** 639 * Update WFC config 640 * @return whether feature is On 641 * @throws ImsException 642 */ 643 private boolean updateWfcFeatureAndProvisionedValues() throws ImsException { 644 boolean available = isWfcEnabledByPlatform(mContext); 645 boolean enabled = isWfcEnabledByUser(mContext); 646 int mode = getWfcMode(mContext); 647 boolean roaming = isWfcRoamingEnabledByUser(mContext); 648 boolean isFeatureOn = available && enabled; 649 650 log("updateWfcFeatureAndProvisionedValues: available = " + available 651 + ", enabled = " + enabled 652 + ", mode = " + mode 653 + ", roaming = " + roaming); 654 655 getConfigInterface().setFeatureValue( 656 ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI, 657 TelephonyManager.NETWORK_TYPE_IWLAN, 658 isFeatureOn ? 659 ImsConfig.FeatureValueConstants.ON : 660 ImsConfig.FeatureValueConstants.OFF, 661 mImsConfigListener); 662 663 if (!isFeatureOn) { 664 mode = ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED; 665 roaming = false; 666 } 667 setWfcModeInternal(mContext, mode); 668 setWfcRoamingSettingInternal(mContext, roaming); 669 670 return isFeatureOn; 671 } 672 673 private ImsManager(Context context, int phoneId) { 674 mContext = context; 675 mPhoneId = phoneId; 676 createImsService(true); 677 } 678 679 /* 680 * Returns a flag indicating whether the IMS service is available. 681 */ 682 public boolean isServiceAvailable() { 683 if (mImsService != null) { 684 return true; 685 } 686 687 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId)); 688 if (binder != null) { 689 return true; 690 } 691 692 return false; 693 } 694 695 public void setImsConfigListener(ImsConfigListener listener) { 696 mImsConfigListener = listener; 697 } 698 699 /** 700 * Opens the IMS service for making calls and/or receiving generic IMS calls. 701 * The caller may make subsquent calls through {@link #makeCall}. 702 * The IMS service will register the device to the operator's network with the credentials 703 * (from ISIM) periodically in order to receive calls from the operator's network. 704 * When the IMS service receives a new call, it will send out an intent with 705 * the provided action string. 706 * The intent contains a call ID extra {@link getCallId} and it can be used to take a call. 707 * 708 * @param serviceClass a service class specified in {@link ImsServiceClass} 709 * For VoLTE service, it MUST be a {@link ImsServiceClass#MMTEL}. 710 * @param incomingCallPendingIntent When an incoming call is received, 711 * the IMS service will call {@link PendingIntent#send(Context, int, Intent)} to 712 * send back the intent to the caller with {@link #INCOMING_CALL_RESULT_CODE} 713 * as the result code and the intent to fill in the call ID; It cannot be null 714 * @param listener To listen to IMS registration events; It cannot be null 715 * @return identifier (greater than 0) for the specified service 716 * @throws NullPointerException if {@code incomingCallPendingIntent} 717 * or {@code listener} is null 718 * @throws ImsException if calling the IMS service results in an error 719 * @see #getCallId 720 * @see #getServiceId 721 */ 722 public int open(int serviceClass, PendingIntent incomingCallPendingIntent, 723 ImsConnectionStateListener listener) throws ImsException { 724 checkAndThrowExceptionIfServiceUnavailable(); 725 726 if (incomingCallPendingIntent == null) { 727 throw new NullPointerException("incomingCallPendingIntent can't be null"); 728 } 729 730 if (listener == null) { 731 throw new NullPointerException("listener can't be null"); 732 } 733 734 int result = 0; 735 736 try { 737 result = mImsService.open(mPhoneId, serviceClass, incomingCallPendingIntent, 738 createRegistrationListenerProxy(serviceClass, listener)); 739 } catch (RemoteException e) { 740 throw new ImsException("open()", e, 741 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 742 } 743 744 if (result <= 0) { 745 // If the return value is a minus value, 746 // it means that an error occurred in the service. 747 // So, it needs to convert to the reason code specified in ImsReasonInfo. 748 throw new ImsException("open()", (result * (-1))); 749 } 750 751 return result; 752 } 753 754 /** 755 * Closes the specified service ({@link ImsServiceClass}) not to make/receive calls. 756 * All the resources that were allocated to the service are also released. 757 * 758 * @param serviceId a service id to be closed which is obtained from {@link ImsManager#open} 759 * @throws ImsException if calling the IMS service results in an error 760 */ 761 public void close(int serviceId) throws ImsException { 762 checkAndThrowExceptionIfServiceUnavailable(); 763 764 try { 765 mImsService.close(serviceId); 766 } catch (RemoteException e) { 767 throw new ImsException("close()", e, 768 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 769 } finally { 770 mUt = null; 771 mConfig = null; 772 mEcbm = null; 773 } 774 } 775 776 /** 777 * Gets the configuration interface to provision / withdraw the supplementary service settings. 778 * 779 * @param serviceId a service id which is obtained from {@link ImsManager#open} 780 * @return the Ut interface instance 781 * @throws ImsException if getting the Ut interface results in an error 782 */ 783 public ImsUtInterface getSupplementaryServiceConfiguration(int serviceId) 784 throws ImsException { 785 // FIXME: manage the multiple Ut interfaces based on the service id 786 if (mUt == null) { 787 checkAndThrowExceptionIfServiceUnavailable(); 788 789 try { 790 IImsUt iUt = mImsService.getUtInterface(serviceId); 791 792 if (iUt == null) { 793 throw new ImsException("getSupplementaryServiceConfiguration()", 794 ImsReasonInfo.CODE_UT_NOT_SUPPORTED); 795 } 796 797 mUt = new ImsUt(iUt); 798 } catch (RemoteException e) { 799 throw new ImsException("getSupplementaryServiceConfiguration()", e, 800 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 801 } 802 } 803 804 return mUt; 805 } 806 807 /** 808 * Checks if the IMS service has successfully registered to the IMS network 809 * with the specified service & call type. 810 * 811 * @param serviceId a service id which is obtained from {@link ImsManager#open} 812 * @param serviceType a service type that is specified in {@link ImsCallProfile} 813 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL} 814 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY} 815 * @param callType a call type that is specified in {@link ImsCallProfile} 816 * {@link ImsCallProfile#CALL_TYPE_VOICE_N_VIDEO} 817 * {@link ImsCallProfile#CALL_TYPE_VOICE} 818 * {@link ImsCallProfile#CALL_TYPE_VT} 819 * {@link ImsCallProfile#CALL_TYPE_VS} 820 * @return true if the specified service id is connected to the IMS network; 821 * false otherwise 822 * @throws ImsException if calling the IMS service results in an error 823 */ 824 public boolean isConnected(int serviceId, int serviceType, int callType) 825 throws ImsException { 826 checkAndThrowExceptionIfServiceUnavailable(); 827 828 try { 829 return mImsService.isConnected(serviceId, serviceType, callType); 830 } catch (RemoteException e) { 831 throw new ImsException("isServiceConnected()", e, 832 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 833 } 834 } 835 836 /** 837 * Checks if the specified IMS service is opend. 838 * 839 * @param serviceId a service id which is obtained from {@link ImsManager#open} 840 * @return true if the specified service id is opened; false otherwise 841 * @throws ImsException if calling the IMS service results in an error 842 */ 843 public boolean isOpened(int serviceId) throws ImsException { 844 checkAndThrowExceptionIfServiceUnavailable(); 845 846 try { 847 return mImsService.isOpened(serviceId); 848 } catch (RemoteException e) { 849 throw new ImsException("isOpened()", e, 850 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 851 } 852 } 853 854 /** 855 * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state. 856 * 857 * @param serviceId a service id which is obtained from {@link ImsManager#open} 858 * @param serviceType a service type that is specified in {@link ImsCallProfile} 859 * {@link ImsCallProfile#SERVICE_TYPE_NONE} 860 * {@link ImsCallProfile#SERVICE_TYPE_NORMAL} 861 * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY} 862 * @param callType a call type that is specified in {@link ImsCallProfile} 863 * {@link ImsCallProfile#CALL_TYPE_VOICE} 864 * {@link ImsCallProfile#CALL_TYPE_VT} 865 * {@link ImsCallProfile#CALL_TYPE_VT_TX} 866 * {@link ImsCallProfile#CALL_TYPE_VT_RX} 867 * {@link ImsCallProfile#CALL_TYPE_VT_NODIR} 868 * {@link ImsCallProfile#CALL_TYPE_VS} 869 * {@link ImsCallProfile#CALL_TYPE_VS_TX} 870 * {@link ImsCallProfile#CALL_TYPE_VS_RX} 871 * @return a {@link ImsCallProfile} object 872 * @throws ImsException if calling the IMS service results in an error 873 */ 874 public ImsCallProfile createCallProfile(int serviceId, 875 int serviceType, int callType) throws ImsException { 876 checkAndThrowExceptionIfServiceUnavailable(); 877 878 try { 879 return mImsService.createCallProfile(serviceId, serviceType, callType); 880 } catch (RemoteException e) { 881 throw new ImsException("createCallProfile()", e, 882 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 883 } 884 } 885 886 /** 887 * Creates a {@link ImsCall} to make a call. 888 * 889 * @param serviceId a service id which is obtained from {@link ImsManager#open} 890 * @param profile a call profile to make the call 891 * (it contains service type, call type, media information, etc.) 892 * @param participants participants to invite the conference call 893 * @param listener listen to the call events from {@link ImsCall} 894 * @return a {@link ImsCall} object 895 * @throws ImsException if calling the IMS service results in an error 896 */ 897 public ImsCall makeCall(int serviceId, ImsCallProfile profile, String[] callees, 898 ImsCall.Listener listener) throws ImsException { 899 if (DBG) { 900 log("makeCall :: serviceId=" + serviceId 901 + ", profile=" + profile + ", callees=" + callees); 902 } 903 904 checkAndThrowExceptionIfServiceUnavailable(); 905 906 ImsCall call = new ImsCall(mContext, profile); 907 908 call.setListener(listener); 909 ImsCallSession session = createCallSession(serviceId, profile); 910 911 if ((callees != null) && (callees.length == 1)) { 912 call.start(session, callees[0]); 913 } else { 914 call.start(session, callees); 915 } 916 917 return call; 918 } 919 920 /** 921 * Creates a {@link ImsCall} to take an incoming call. 922 * 923 * @param serviceId a service id which is obtained from {@link ImsManager#open} 924 * @param incomingCallIntent the incoming call broadcast intent 925 * @param listener to listen to the call events from {@link ImsCall} 926 * @return a {@link ImsCall} object 927 * @throws ImsException if calling the IMS service results in an error 928 */ 929 public ImsCall takeCall(int serviceId, Intent incomingCallIntent, 930 ImsCall.Listener listener) throws ImsException { 931 if (DBG) { 932 log("takeCall :: serviceId=" + serviceId 933 + ", incomingCall=" + incomingCallIntent); 934 } 935 936 checkAndThrowExceptionIfServiceUnavailable(); 937 938 if (incomingCallIntent == null) { 939 throw new ImsException("Can't retrieve session with null intent", 940 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT); 941 } 942 943 int incomingServiceId = getServiceId(incomingCallIntent); 944 945 if (serviceId != incomingServiceId) { 946 throw new ImsException("Service id is mismatched in the incoming call intent", 947 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT); 948 } 949 950 String callId = getCallId(incomingCallIntent); 951 952 if (callId == null) { 953 throw new ImsException("Call ID missing in the incoming call intent", 954 ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT); 955 } 956 957 try { 958 IImsCallSession session = mImsService.getPendingCallSession(serviceId, callId); 959 960 if (session == null) { 961 throw new ImsException("No pending session for the call", 962 ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL); 963 } 964 965 ImsCall call = new ImsCall(mContext, session.getCallProfile()); 966 967 call.attachSession(new ImsCallSession(session)); 968 call.setListener(listener); 969 970 return call; 971 } catch (Throwable t) { 972 throw new ImsException("takeCall()", t, ImsReasonInfo.CODE_UNSPECIFIED); 973 } 974 } 975 976 /** 977 * Gets the config interface to get/set service/capability parameters. 978 * 979 * @return the ImsConfig instance. 980 * @throws ImsException if getting the setting interface results in an error. 981 */ 982 public ImsConfig getConfigInterface() throws ImsException { 983 984 if (mConfig == null) { 985 checkAndThrowExceptionIfServiceUnavailable(); 986 987 try { 988 IImsConfig config = mImsService.getConfigInterface(mPhoneId); 989 if (config == null) { 990 throw new ImsException("getConfigInterface()", 991 ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE); 992 } 993 mConfig = new ImsConfig(config, mContext); 994 } catch (RemoteException e) { 995 throw new ImsException("getConfigInterface()", e, 996 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 997 } 998 } 999 if (DBG) log("getConfigInterface(), mConfig= " + mConfig); 1000 return mConfig; 1001 } 1002 1003 public void setUiTTYMode(Context context, int serviceId, int uiTtyMode, Message onComplete) 1004 throws ImsException { 1005 1006 checkAndThrowExceptionIfServiceUnavailable(); 1007 1008 try { 1009 mImsService.setUiTTYMode(serviceId, uiTtyMode, onComplete); 1010 } catch (RemoteException e) { 1011 throw new ImsException("setTTYMode()", e, 1012 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 1013 } 1014 1015 if (!getBooleanCarrierConfig(context, 1016 CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL)) { 1017 setAdvanced4GMode((uiTtyMode == TelecomManager.TTY_MODE_OFF) && 1018 isEnhanced4gLteModeSettingEnabledByUser(context)); 1019 } 1020 } 1021 1022 /** 1023 * Get the boolean config from carrier config manager. 1024 * 1025 * @param context the context to get carrier service 1026 * @param key config key defined in CarrierConfigManager 1027 * @return boolean value of corresponding key. 1028 */ 1029 private static boolean getBooleanCarrierConfig(Context context, String key) { 1030 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService( 1031 Context.CARRIER_CONFIG_SERVICE); 1032 PersistableBundle b = null; 1033 if (configManager != null) { 1034 b = configManager.getConfig(); 1035 } 1036 if (b != null) { 1037 return b.getBoolean(key); 1038 } else { 1039 // Return static default defined in CarrierConfigManager. 1040 return CarrierConfigManager.getDefaultConfig().getBoolean(key); 1041 } 1042 } 1043 1044 /** 1045 * Get the int config from carrier config manager. 1046 * 1047 * @param context the context to get carrier service 1048 * @param key config key defined in CarrierConfigManager 1049 * @return integer value of corresponding key. 1050 */ 1051 private static int getIntCarrierConfig(Context context, String key) { 1052 CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService( 1053 Context.CARRIER_CONFIG_SERVICE); 1054 PersistableBundle b = null; 1055 if (configManager != null) { 1056 b = configManager.getConfig(); 1057 } 1058 if (b != null) { 1059 return b.getInt(key); 1060 } else { 1061 // Return static default defined in CarrierConfigManager. 1062 return CarrierConfigManager.getDefaultConfig().getInt(key); 1063 } 1064 } 1065 1066 /** 1067 * Gets the call ID from the specified incoming call broadcast intent. 1068 * 1069 * @param incomingCallIntent the incoming call broadcast intent 1070 * @return the call ID or null if the intent does not contain it 1071 */ 1072 private static String getCallId(Intent incomingCallIntent) { 1073 if (incomingCallIntent == null) { 1074 return null; 1075 } 1076 1077 return incomingCallIntent.getStringExtra(EXTRA_CALL_ID); 1078 } 1079 1080 /** 1081 * Gets the service type from the specified incoming call broadcast intent. 1082 * 1083 * @param incomingCallIntent the incoming call broadcast intent 1084 * @return the service identifier or -1 if the intent does not contain it 1085 */ 1086 private static int getServiceId(Intent incomingCallIntent) { 1087 if (incomingCallIntent == null) { 1088 return (-1); 1089 } 1090 1091 return incomingCallIntent.getIntExtra(EXTRA_SERVICE_ID, -1); 1092 } 1093 1094 /** 1095 * Binds the IMS service only if the service is not created. 1096 */ 1097 private void checkAndThrowExceptionIfServiceUnavailable() 1098 throws ImsException { 1099 if (mImsService == null) { 1100 createImsService(true); 1101 1102 if (mImsService == null) { 1103 throw new ImsException("Service is unavailable", 1104 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 1105 } 1106 } 1107 } 1108 1109 private static String getImsServiceName(int phoneId) { 1110 // TODO: MSIM implementation needs to decide on service name as a function of phoneId 1111 return IMS_SERVICE; 1112 } 1113 1114 /** 1115 * Binds the IMS service to make/receive the call. 1116 */ 1117 private void createImsService(boolean checkService) { 1118 if (checkService) { 1119 IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId)); 1120 1121 if (binder == null) { 1122 return; 1123 } 1124 } 1125 1126 IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId)); 1127 1128 if (b != null) { 1129 try { 1130 b.linkToDeath(mDeathRecipient, 0); 1131 } catch (RemoteException e) { 1132 } 1133 } 1134 1135 mImsService = IImsService.Stub.asInterface(b); 1136 } 1137 1138 /** 1139 * Creates a {@link ImsCallSession} with the specified call profile. 1140 * Use other methods, if applicable, instead of interacting with 1141 * {@link ImsCallSession} directly. 1142 * 1143 * @param serviceId a service id which is obtained from {@link ImsManager#open} 1144 * @param profile a call profile to make the call 1145 */ 1146 private ImsCallSession createCallSession(int serviceId, 1147 ImsCallProfile profile) throws ImsException { 1148 try { 1149 return new ImsCallSession(mImsService.createCallSession(serviceId, profile, null)); 1150 } catch (RemoteException e) { 1151 return null; 1152 } 1153 } 1154 1155 private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass, 1156 ImsConnectionStateListener listener) { 1157 ImsRegistrationListenerProxy proxy = 1158 new ImsRegistrationListenerProxy(serviceClass, listener); 1159 return proxy; 1160 } 1161 1162 private static void log(String s) { 1163 Rlog.d(TAG, s); 1164 } 1165 1166 private static void loge(String s) { 1167 Rlog.e(TAG, s); 1168 } 1169 1170 private static void loge(String s, Throwable t) { 1171 Rlog.e(TAG, s, t); 1172 } 1173 1174 /** 1175 * Used for turning on IMS.if its off already 1176 */ 1177 private void turnOnIms() throws ImsException { 1178 checkAndThrowExceptionIfServiceUnavailable(); 1179 1180 try { 1181 mImsService.turnOnIms(mPhoneId); 1182 } catch (RemoteException e) { 1183 throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 1184 } 1185 } 1186 1187 private boolean isImsTurnOffAllowed() { 1188 return getBooleanCarrierConfig(mContext, 1189 CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL) 1190 && (!isWfcEnabledByPlatform(mContext) 1191 || !isWfcEnabledByUser(mContext)); 1192 } 1193 1194 private void setAdvanced4GMode(boolean turnOn) throws ImsException { 1195 checkAndThrowExceptionIfServiceUnavailable(); 1196 1197 try { 1198 ImsConfig config = getConfigInterface(); 1199 if (config != null && (turnOn || !isImsTurnOffAllowed())) { 1200 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE, 1201 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener); 1202 1203 if (isVtEnabledByPlatform(mContext)) { 1204 // TODO: once VT is available on platform: 1205 // - replace the '1' with the current user configuration of VT. 1206 // - separate exception checks for setFeatureValue() failures for VoLTE and VT. 1207 // I.e. if VoLTE fails still try to configure VT. 1208 config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE, 1209 TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener); 1210 } 1211 } 1212 } catch (ImsException e) { 1213 log("setAdvanced4GMode() : " + e); 1214 } 1215 if (turnOn) { 1216 turnOnIms(); 1217 } else if (isImsTurnOffAllowed()) { 1218 log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms"); 1219 turnOffIms(); 1220 } 1221 } 1222 1223 /** 1224 * Used for turning off IMS completely in order to make the device CSFB'ed. 1225 * Once turned off, all calls will be over CS. 1226 */ 1227 private void turnOffIms() throws ImsException { 1228 checkAndThrowExceptionIfServiceUnavailable(); 1229 1230 try { 1231 mImsService.turnOffIms(mPhoneId); 1232 } catch (RemoteException e) { 1233 throw new ImsException("turnOffIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 1234 } 1235 } 1236 1237 /** 1238 * Death recipient class for monitoring IMS service. 1239 */ 1240 private class ImsServiceDeathRecipient implements IBinder.DeathRecipient { 1241 @Override 1242 public void binderDied() { 1243 mImsService = null; 1244 mUt = null; 1245 mConfig = null; 1246 mEcbm = null; 1247 1248 if (mContext != null) { 1249 Intent intent = new Intent(ACTION_IMS_SERVICE_DOWN); 1250 intent.putExtra(EXTRA_PHONE_ID, mPhoneId); 1251 mContext.sendBroadcast(new Intent(intent)); 1252 } 1253 } 1254 } 1255 1256 /** 1257 * Adapter class for {@link IImsRegistrationListener}. 1258 */ 1259 private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub { 1260 private int mServiceClass; 1261 private ImsConnectionStateListener mListener; 1262 1263 public ImsRegistrationListenerProxy(int serviceClass, 1264 ImsConnectionStateListener listener) { 1265 mServiceClass = serviceClass; 1266 mListener = listener; 1267 } 1268 1269 public boolean isSameProxy(int serviceClass) { 1270 return (mServiceClass == serviceClass); 1271 } 1272 1273 @Deprecated 1274 public void registrationConnected() { 1275 if (DBG) { 1276 log("registrationConnected ::"); 1277 } 1278 1279 if (mListener != null) { 1280 mListener.onImsConnected(); 1281 } 1282 } 1283 1284 @Deprecated 1285 public void registrationProgressing() { 1286 if (DBG) { 1287 log("registrationProgressing ::"); 1288 } 1289 1290 if (mListener != null) { 1291 mListener.onImsProgressing(); 1292 } 1293 } 1294 1295 @Override 1296 public void registrationConnectedWithRadioTech(int imsRadioTech) { 1297 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY 1298 // values in ServiceState.java. 1299 if (DBG) { 1300 log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech); 1301 } 1302 1303 if (mListener != null) { 1304 mListener.onImsConnected(); 1305 } 1306 } 1307 1308 @Override 1309 public void registrationProgressingWithRadioTech(int imsRadioTech) { 1310 // Note: imsRadioTech value maps to RIL_RADIO_TECHNOLOGY 1311 // values in ServiceState.java. 1312 if (DBG) { 1313 log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech); 1314 } 1315 1316 if (mListener != null) { 1317 mListener.onImsProgressing(); 1318 } 1319 } 1320 1321 @Override 1322 public void registrationDisconnected(ImsReasonInfo imsReasonInfo) { 1323 if (DBG) { 1324 log("registrationDisconnected :: imsReasonInfo" + imsReasonInfo); 1325 } 1326 1327 if (mListener != null) { 1328 mListener.onImsDisconnected(imsReasonInfo); 1329 } 1330 } 1331 1332 @Override 1333 public void registrationResumed() { 1334 if (DBG) { 1335 log("registrationResumed ::"); 1336 } 1337 1338 if (mListener != null) { 1339 mListener.onImsResumed(); 1340 } 1341 } 1342 1343 @Override 1344 public void registrationSuspended() { 1345 if (DBG) { 1346 log("registrationSuspended ::"); 1347 } 1348 1349 if (mListener != null) { 1350 mListener.onImsSuspended(); 1351 } 1352 } 1353 1354 @Override 1355 public void registrationServiceCapabilityChanged(int serviceClass, int event) { 1356 log("registrationServiceCapabilityChanged :: serviceClass=" + 1357 serviceClass + ", event=" + event); 1358 1359 if (mListener != null) { 1360 mListener.onImsConnected(); 1361 } 1362 } 1363 1364 @Override 1365 public void registrationFeatureCapabilityChanged(int serviceClass, 1366 int[] enabledFeatures, int[] disabledFeatures) { 1367 log("registrationFeatureCapabilityChanged :: serviceClass=" + 1368 serviceClass); 1369 if (mListener != null) { 1370 mListener.onFeatureCapabilityChanged(serviceClass, 1371 enabledFeatures, disabledFeatures); 1372 } 1373 } 1374 1375 @Override 1376 public void voiceMessageCountUpdate(int count) { 1377 log("voiceMessageCountUpdate :: count=" + count); 1378 1379 if (mListener != null) { 1380 mListener.onVoiceMessageCountChanged(count); 1381 } 1382 } 1383 1384 @Override 1385 public void registrationAssociatedUriChanged(Uri[] uris) { 1386 if (DBG) log("registrationAssociatedUriChanged ::"); 1387 1388 if (mListener != null) { 1389 mListener.registrationAssociatedUriChanged(uris); 1390 } 1391 } 1392 } 1393 /** 1394 * Gets the ECBM interface to request ECBM exit. 1395 * 1396 * @param serviceId a service id which is obtained from {@link ImsManager#open} 1397 * @return the ECBM interface instance 1398 * @throws ImsException if getting the ECBM interface results in an error 1399 */ 1400 public ImsEcbm getEcbmInterface(int serviceId) throws ImsException { 1401 if (mEcbm == null) { 1402 checkAndThrowExceptionIfServiceUnavailable(); 1403 1404 try { 1405 IImsEcbm iEcbm = mImsService.getEcbmInterface(serviceId); 1406 1407 if (iEcbm == null) { 1408 throw new ImsException("getEcbmInterface()", 1409 ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED); 1410 } 1411 mEcbm = new ImsEcbm(iEcbm); 1412 } catch (RemoteException e) { 1413 throw new ImsException("getEcbmInterface()", e, 1414 ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); 1415 } 1416 } 1417 return mEcbm; 1418 } 1419 1420 /** 1421 * Resets ImsManager settings back to factory defaults. 1422 * 1423 * @hide 1424 */ 1425 public static void factoryReset(Context context) { 1426 // Set VoLTE to default 1427 android.provider.Settings.Global.putInt(context.getContentResolver(), 1428 android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, 1429 ImsConfig.FeatureValueConstants.ON); 1430 1431 // Set VoWiFi to default 1432 android.provider.Settings.Global.putInt(context.getContentResolver(), 1433 android.provider.Settings.Global.WFC_IMS_ENABLED, 1434 getBooleanCarrierConfig(context, 1435 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL) ? 1436 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); 1437 1438 // Set VoWiFi mode to default 1439 android.provider.Settings.Global.putInt(context.getContentResolver(), 1440 android.provider.Settings.Global.WFC_IMS_MODE, 1441 getIntCarrierConfig(context, 1442 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT)); 1443 1444 // Set VoWiFi roaming to default 1445 android.provider.Settings.Global.putInt(context.getContentResolver(), 1446 android.provider.Settings.Global.WFC_IMS_ROAMING_ENABLED, 1447 getBooleanCarrierConfig(context, 1448 CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL) ? 1449 ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF); 1450 1451 // Set VT to default 1452 SharedPreferences sharedPrefs = 1453 PreferenceManager.getDefaultSharedPreferences(context); 1454 SharedPreferences.Editor editor = sharedPrefs.edit(); 1455 editor.putBoolean(PREF_ENABLE_VIDEO_CALLING_KEY, true); 1456 editor.commit(); 1457 1458 // Push settings to ImsConfig 1459 ImsManager.updateImsServiceConfig(context, 1460 SubscriptionManager.getDefaultVoicePhoneId(), true); 1461 } 1462 1463 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1464 pw.println("ImsManager:"); 1465 pw.println(" mPhoneId = " + mPhoneId); 1466 pw.println(" mConfigUpdated = " + mConfigUpdated); 1467 pw.println(" mImsService = " + mImsService); 1468 1469 pw.println(" isGbaValid = " + isGbaValid(mContext)); 1470 pw.println(" isImsTurnOffAllowed = " + isImsTurnOffAllowed()); 1471 pw.println(" isNonTtyOrTtyOnVolteEnabled = " + isNonTtyOrTtyOnVolteEnabled(mContext)); 1472 1473 pw.println(" isVolteEnabledByPlatform = " + isVolteEnabledByPlatform(mContext)); 1474 pw.println(" isVolteProvisionedOnDevice = " + isVolteProvisionedOnDevice(mContext)); 1475 pw.println(" isEnhanced4gLteModeSettingEnabledByUser = " + 1476 isEnhanced4gLteModeSettingEnabledByUser(mContext)); 1477 pw.println(" isVtEnabledByPlatform = " + isVtEnabledByPlatform(mContext)); 1478 pw.println(" isVtEnabledByUser = " + isVtEnabledByUser(mContext)); 1479 1480 pw.println(" isWfcEnabledByPlatform = " + isWfcEnabledByPlatform(mContext)); 1481 pw.println(" isWfcEnabledByUser = " + isWfcEnabledByUser(mContext)); 1482 pw.println(" getWfcMode = " + getWfcMode(mContext)); 1483 pw.println(" isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser(mContext)); 1484 1485 pw.flush(); 1486 } 1487} 1488