1 /* 2 * Copyright (C) 2018 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 17 package android.telephony.ims; 18 19 20 import android.Manifest; 21 import android.annotation.CallbackExecutor; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SystemApi; 27 import android.content.Context; 28 import android.content.pm.IPackageManager; 29 import android.content.pm.PackageManager; 30 import android.net.Uri; 31 import android.os.Binder; 32 import android.os.RemoteException; 33 import android.os.ServiceManager; 34 import android.telephony.AccessNetworkConstants; 35 import android.telephony.SubscriptionManager; 36 import android.telephony.ims.aidl.IImsCapabilityCallback; 37 import android.telephony.ims.aidl.IImsRegistrationCallback; 38 import android.telephony.ims.feature.ImsFeature; 39 import android.telephony.ims.feature.MmTelFeature; 40 import android.telephony.ims.stub.ImsRegistrationImplBase; 41 import android.util.Log; 42 43 import com.android.internal.annotations.VisibleForTesting; 44 import com.android.internal.telephony.ITelephony; 45 46 import java.lang.annotation.Retention; 47 import java.lang.annotation.RetentionPolicy; 48 import java.util.HashMap; 49 import java.util.Map; 50 import java.util.concurrent.Executor; 51 52 /** 53 * A manager for the MmTel (Multimedia Telephony) feature of an IMS network, given an associated 54 * subscription. 55 * 56 * Allows a user to query the IMS MmTel feature information for a subscription, register for 57 * registration and MmTel capability status callbacks, as well as query/modify user settings for the 58 * associated subscription. 59 * 60 * @see #createForSubscriptionId(int) 61 * @hide 62 */ 63 @SystemApi 64 public class ImsMmTelManager { 65 66 private static final String TAG = "ImsMmTelManager"; 67 68 /** 69 * @hide 70 */ 71 @Retention(RetentionPolicy.SOURCE) 72 @IntDef(prefix = "WIFI_MODE_", value = { 73 WIFI_MODE_WIFI_ONLY, 74 WIFI_MODE_CELLULAR_PREFERRED, 75 WIFI_MODE_WIFI_PREFERRED 76 }) 77 public @interface WiFiCallingMode {} 78 79 /** 80 * Register for IMS over IWLAN if WiFi signal quality is high enough. Do not hand over to LTE 81 * registration if signal quality degrades. 82 */ 83 public static final int WIFI_MODE_WIFI_ONLY = 0; 84 85 /** 86 * Prefer registering for IMS over LTE if LTE signal quality is high enough. 87 */ 88 public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; 89 90 /** 91 * Prefer registering for IMS over IWLAN if possible if WiFi signal quality is high enough. 92 */ 93 public static final int WIFI_MODE_WIFI_PREFERRED = 2; 94 95 /** 96 * Callback class for receiving IMS network Registration callback events. 97 * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback) 98 * @see #unregisterImsRegistrationCallback(RegistrationCallback) 99 */ 100 public static class RegistrationCallback { 101 102 private static class RegistrationBinder extends IImsRegistrationCallback.Stub { 103 104 // Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN 105 // and WWAN are more accurate constants. 106 private static final Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP = 107 new HashMap<Integer, Integer>() {{ 108 // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE 109 // case, since it is defined. 110 put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1); 111 put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE, 112 AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 113 put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, 114 AccessNetworkConstants.TRANSPORT_TYPE_WLAN); 115 }}; 116 117 private final RegistrationCallback mLocalCallback; 118 private Executor mExecutor; 119 RegistrationBinder(RegistrationCallback localCallback)120 RegistrationBinder(RegistrationCallback localCallback) { 121 mLocalCallback = localCallback; 122 } 123 124 @Override onRegistered(int imsRadioTech)125 public void onRegistered(int imsRadioTech) { 126 if (mLocalCallback == null) return; 127 128 Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> 129 mLocalCallback.onRegistered(getAccessType(imsRadioTech)))); 130 } 131 132 @Override onRegistering(int imsRadioTech)133 public void onRegistering(int imsRadioTech) { 134 if (mLocalCallback == null) return; 135 136 Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> 137 mLocalCallback.onRegistering(getAccessType(imsRadioTech)))); 138 } 139 140 @Override onDeregistered(ImsReasonInfo info)141 public void onDeregistered(ImsReasonInfo info) { 142 if (mLocalCallback == null) return; 143 144 Binder.withCleanCallingIdentity(() -> 145 mExecutor.execute(() -> mLocalCallback.onUnregistered(info))); 146 } 147 148 @Override onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info)149 public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) { 150 if (mLocalCallback == null) return; 151 152 Binder.withCleanCallingIdentity(() -> 153 mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed( 154 getAccessType(imsRadioTech), info))); 155 } 156 157 @Override onSubscriberAssociatedUriChanged(Uri[] uris)158 public void onSubscriberAssociatedUriChanged(Uri[] uris) { 159 if (mLocalCallback == null) return; 160 161 Binder.withCleanCallingIdentity(() -> 162 mExecutor.execute(() -> 163 mLocalCallback.onSubscriberAssociatedUriChanged(uris))); 164 } 165 setExecutor(Executor executor)166 private void setExecutor(Executor executor) { 167 mExecutor = executor; 168 } 169 getAccessType(int regType)170 private static int getAccessType(int regType) { 171 if (!IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regType)) { 172 Log.w("ImsMmTelManager", "RegistrationBinder - invalid regType returned: " 173 + regType); 174 return -1; 175 } 176 return IMS_REG_TO_ACCESS_TYPE_MAP.get(regType); 177 } 178 } 179 180 private final RegistrationBinder mBinder = new RegistrationBinder(this); 181 182 /** 183 * Notifies the framework when the IMS Provider is registered to the IMS network. 184 * 185 * @param imsTransportType the radio access technology. Valid values are defined in 186 * {@link android.telephony.AccessNetworkConstants.TransportType}. 187 */ onRegistered(int imsTransportType)188 public void onRegistered(int imsTransportType) { 189 } 190 191 /** 192 * Notifies the framework when the IMS Provider is trying to register the IMS network. 193 * 194 * @param imsTransportType the radio access technology. Valid values are defined in 195 * {@link android.telephony.AccessNetworkConstants.TransportType}. 196 */ onRegistering(int imsTransportType)197 public void onRegistering(int imsTransportType) { 198 } 199 200 /** 201 * Notifies the framework when the IMS Provider is deregistered from the IMS network. 202 * 203 * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. 204 */ onUnregistered(@ullable ImsReasonInfo info)205 public void onUnregistered(@Nullable ImsReasonInfo info) { 206 } 207 208 /** 209 * A failure has occurred when trying to handover registration to another technology type, 210 * defined in {@link android.telephony.AccessNetworkConstants.TransportType} 211 * 212 * @param imsTransportType The 213 * {@link android.telephony.AccessNetworkConstants.TransportType} 214 * transport type that has failed to handover registration to. 215 * @param info A {@link ImsReasonInfo} that identifies the reason for failure. 216 */ onTechnologyChangeFailed(int imsTransportType, @Nullable ImsReasonInfo info)217 public void onTechnologyChangeFailed(int imsTransportType, @Nullable ImsReasonInfo info) { 218 } 219 220 /** 221 * Returns a list of subscriber {@link Uri}s associated with this IMS subscription when 222 * it changes. Per RFC3455, an associated URI is a URI that the service provider has 223 * allocated to a user for their own usage. A user's phone number is typically one of the 224 * associated URIs. 225 * @param uris new array of subscriber {@link Uri}s that are associated with this IMS 226 * subscription. 227 * @hide 228 */ onSubscriberAssociatedUriChanged(@ullable Uri[] uris)229 public void onSubscriberAssociatedUriChanged(@Nullable Uri[] uris) { 230 } 231 232 /**@hide*/ getBinder()233 public final IImsRegistrationCallback getBinder() { 234 return mBinder; 235 } 236 237 /**@hide*/ 238 //Only exposed as public for compatibility with deprecated ImsManager APIs. setExecutor(Executor executor)239 public void setExecutor(Executor executor) { 240 mBinder.setExecutor(executor); 241 } 242 } 243 244 /** 245 * Receives IMS capability status updates from the ImsService. This information is also 246 * available via the {@link #isAvailable(int, int)} method below. 247 * 248 * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback) 249 * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) 250 */ 251 public static class CapabilityCallback { 252 253 private static class CapabilityBinder extends IImsCapabilityCallback.Stub { 254 255 private final CapabilityCallback mLocalCallback; 256 private Executor mExecutor; 257 CapabilityBinder(CapabilityCallback c)258 CapabilityBinder(CapabilityCallback c) { 259 mLocalCallback = c; 260 } 261 262 @Override onCapabilitiesStatusChanged(int config)263 public void onCapabilitiesStatusChanged(int config) { 264 if (mLocalCallback == null) return; 265 266 Binder.withCleanCallingIdentity(() -> 267 mExecutor.execute(() -> mLocalCallback.onCapabilitiesStatusChanged( 268 new MmTelFeature.MmTelCapabilities(config)))); 269 } 270 271 @Override onQueryCapabilityConfiguration(int capability, int radioTech, boolean isEnabled)272 public void onQueryCapabilityConfiguration(int capability, int radioTech, 273 boolean isEnabled) { 274 // This is not used for public interfaces. 275 } 276 277 @Override onChangeCapabilityConfigurationError(int capability, int radioTech, @ImsFeature.ImsCapabilityError int reason)278 public void onChangeCapabilityConfigurationError(int capability, int radioTech, 279 @ImsFeature.ImsCapabilityError int reason) { 280 // This is not used for public interfaces 281 } 282 setExecutor(Executor executor)283 private void setExecutor(Executor executor) { 284 mExecutor = executor; 285 } 286 } 287 288 private final CapabilityBinder mBinder = new CapabilityBinder(this); 289 290 /** 291 * The status of the feature's capabilities has changed to either available or unavailable. 292 * If unavailable, the feature is not able to support the unavailable capability at this 293 * time. 294 * 295 * This information can also be queried using the {@link #isAvailable(int, int)} API. 296 * 297 * @param capabilities The new availability of the capabilities. 298 */ onCapabilitiesStatusChanged( @onNull MmTelFeature.MmTelCapabilities capabilities)299 public void onCapabilitiesStatusChanged( 300 @NonNull MmTelFeature.MmTelCapabilities capabilities) { 301 } 302 303 /**@hide*/ getBinder()304 public final IImsCapabilityCallback getBinder() { 305 return mBinder; 306 } 307 308 /**@hide*/ 309 // Only exposed as public method for compatibility with deprecated ImsManager APIs. 310 // TODO: clean up dependencies and change back to private visibility. setExecutor(Executor executor)311 public final void setExecutor(Executor executor) { 312 mBinder.setExecutor(executor); 313 } 314 } 315 316 private int mSubId; 317 318 /** 319 * Create an instance of {@link ImsMmTelManager} for the subscription id specified. 320 * 321 * @param subId The ID of the subscription that this ImsMmTelManager will use. 322 * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList() 323 * @throws IllegalArgumentException if the subscription is invalid. 324 */ createForSubscriptionId(int subId)325 public static @NonNull ImsMmTelManager createForSubscriptionId(int subId) { 326 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 327 throw new IllegalArgumentException("Invalid subscription ID"); 328 } 329 330 return new ImsMmTelManager(subId); 331 } 332 333 /** 334 * Only visible for testing, use {@link #createForSubscriptionId(int)} instead. 335 * @hide 336 */ 337 @VisibleForTesting ImsMmTelManager(int subId)338 public ImsMmTelManager(int subId) { 339 mSubId = subId; 340 } 341 342 /** 343 * Registers a {@link RegistrationCallback} with the system, which will provide registration 344 * updates for the subscription specified in {@link #createForSubscriptionId(int)}. Use 345 * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed 346 * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. 347 * 348 * When the callback is registered, it will initiate the callback c to be called with the 349 * current registration state. 350 * 351 * @param executor The executor the callback events should be run on. 352 * @param c The {@link RegistrationCallback} to be added. 353 * @see #unregisterImsRegistrationCallback(RegistrationCallback) 354 * @throws IllegalArgumentException if the subscription associated with this callback is not 355 * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or 356 * {@link CapabilityCallback} callback. 357 * @throws ImsException if the subscription associated with this callback is valid, but 358 * the {@link ImsService} associated with the subscription is not available. This can happen if 359 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed 360 * reason. 361 */ 362 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) registerImsRegistrationCallback(@onNull @allbackExecutor Executor executor, @NonNull RegistrationCallback c)363 public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, 364 @NonNull RegistrationCallback c) throws ImsException { 365 if (c == null) { 366 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 367 } 368 if (executor == null) { 369 throw new IllegalArgumentException("Must include a non-null Executor."); 370 } 371 if (!isImsAvailableOnDevice()) { 372 throw new ImsException("IMS not available on device.", 373 ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); 374 } 375 c.setExecutor(executor); 376 try { 377 getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder()); 378 } catch (RemoteException | IllegalStateException e) { 379 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 380 } 381 } 382 383 /** 384 * Removes an existing {@link RegistrationCallback}. 385 * 386 * When the subscription associated with this callback is removed (SIM removed, ESIM swap, 387 * etc...), this callback will automatically be removed. If this method is called for an 388 * inactive subscription, it will result in a no-op. 389 * 390 * @param c The {@link RegistrationCallback} to be removed. 391 * @see SubscriptionManager.OnSubscriptionsChangedListener 392 * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) 393 * @throws IllegalArgumentException if the subscription ID associated with this callback is 394 * invalid. 395 */ 396 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) unregisterImsRegistrationCallback(@onNull RegistrationCallback c)397 public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) { 398 if (c == null) { 399 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 400 } 401 try { 402 getITelephony().unregisterImsRegistrationCallback(mSubId, c.getBinder()); 403 } catch (RemoteException e) { 404 throw e.rethrowAsRuntimeException(); 405 } 406 } 407 408 /** 409 * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service 410 * availability updates for the subscription specified in 411 * {@link #createForSubscriptionId(int)}. The method {@link #isAvailable(int, int)} 412 * can also be used to query this information at any time. 413 * 414 * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to 415 * subscription changed events and call 416 * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. 417 * 418 * When the callback is registered, it will initiate the callback c to be called with the 419 * current capabilities. 420 * 421 * @param executor The executor the callback events should be run on. 422 * @param c The MmTel {@link CapabilityCallback} to be registered. 423 * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) 424 * @throws IllegalArgumentException if the subscription associated with this callback is not 425 * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or 426 * {@link CapabilityCallback} callback. 427 * @throws ImsException if the subscription associated with this callback is valid, but 428 * the {@link ImsService} associated with the subscription is not available. This can happen if 429 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed 430 * reason. 431 */ 432 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) registerMmTelCapabilityCallback(@onNull @allbackExecutor Executor executor, @NonNull CapabilityCallback c)433 public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor, 434 @NonNull CapabilityCallback c) throws ImsException { 435 if (c == null) { 436 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 437 } 438 if (executor == null) { 439 throw new IllegalArgumentException("Must include a non-null Executor."); 440 } 441 if (!isImsAvailableOnDevice()) { 442 throw new ImsException("IMS not available on device.", 443 ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); 444 } 445 c.setExecutor(executor); 446 try { 447 getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder()); 448 } catch (RemoteException e) { 449 throw e.rethrowAsRuntimeException(); 450 } catch (IllegalStateException e) { 451 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 452 } 453 } 454 455 /** 456 * Removes an existing MmTel {@link CapabilityCallback}. 457 * 458 * When the subscription associated with this callback is removed (SIM removed, ESIM swap, 459 * etc...), this callback will automatically be removed. If this method is called for an 460 * inactive subscription, it will result in a no-op. 461 * @param c The MmTel {@link CapabilityCallback} to be removed. 462 * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) 463 * @throws IllegalArgumentException if the subscription ID associated with this callback is 464 * invalid. 465 */ 466 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) unregisterMmTelCapabilityCallback(@onNull CapabilityCallback c)467 public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) { 468 if (c == null) { 469 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 470 } 471 try { 472 getITelephony().unregisterMmTelCapabilityCallback(mSubId, c.getBinder()); 473 } catch (RemoteException e) { 474 throw e.rethrowAsRuntimeException(); 475 } 476 } 477 478 /** 479 * Query the user’s setting for “Advanced Calling” or "Enhanced 4G LTE", which is used to 480 * enable MmTel IMS features, depending on the carrier configuration for the current 481 * subscription. If this setting is enabled, IMS voice and video telephony over IWLAN/LTE will 482 * be enabled as long as the carrier has provisioned these services for the specified 483 * subscription. Other IMS services (SMS/UT) are not affected by this user setting and depend on 484 * carrier requirements. 485 * 486 * Modifying this value may also trigger an IMS registration or deregistration, depending on 487 * whether or not the new value is enabled or disabled. 488 * 489 * Note: If the carrier configuration for advanced calling is not editable or hidden, this 490 * method will do nothing and will instead always use the default value. 491 * 492 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL 493 * @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL 494 * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL 495 * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL 496 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL 497 * @see #setAdvancedCallingSettingEnabled(boolean) 498 * @return true if the user's setting for advanced calling is enabled, false otherwise. 499 */ 500 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isAdvancedCallingSettingEnabled()501 public boolean isAdvancedCallingSettingEnabled() { 502 try { 503 return getITelephony().isAdvancedCallingSettingEnabled(mSubId); 504 } catch (RemoteException e) { 505 throw e.rethrowAsRuntimeException(); 506 } 507 } 508 509 /** 510 * Modify the user’s setting for “Advanced Calling” or "Enhanced 4G LTE", which is used to 511 * enable MmTel IMS features, depending on the carrier configuration for the current 512 * subscription. If this setting is enabled, IMS voice and video telephony over IWLAN/LTE will 513 * be enabled as long as the carrier has provisioned these services for the specified 514 * subscription. Other IMS services (SMS/UT) are not affected by this user setting and depend on 515 * carrier requirements. 516 * 517 * Modifying this value may also trigger an IMS registration or deregistration, depending on 518 * whether or not the new value is enabled or disabled. 519 * 520 * Note: If the carrier configuration for advanced calling is not editable or hidden, this 521 * method will do nothing and will instead always use the default value. 522 * 523 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL 524 * @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL 525 * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL 526 * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL 527 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL 528 * @see #isAdvancedCallingSettingEnabled() 529 */ 530 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setAdvancedCallingSettingEnabled(boolean isEnabled)531 public void setAdvancedCallingSettingEnabled(boolean isEnabled) { 532 try { 533 getITelephony().setAdvancedCallingSettingEnabled(mSubId, isEnabled); 534 return; 535 } catch (RemoteException e) { 536 throw e.rethrowAsRuntimeException(); 537 } 538 } 539 540 /** 541 * Query the IMS MmTel capability for a given registration technology. This does not 542 * necessarily mean that we are registered and the capability is available, but rather the 543 * subscription is capable of this service over IMS. 544 * 545 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL 546 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VT_AVAILABLE_BOOL 547 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_IMS_GBA_REQUIRED_BOOL 548 * @see #isAvailable(int, int) 549 * 550 * @param imsRegTech The IMS registration technology, can be one of the following: 551 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}, 552 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} 553 * @param capability The IMS MmTel capability to query, can be one of the following: 554 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, 555 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO, 556 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, 557 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} 558 * @return {@code true} if the MmTel IMS capability is capable for this subscription, false 559 * otherwise. 560 */ 561 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isCapable(@mTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech)562 public boolean isCapable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, 563 @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) { 564 try { 565 return getITelephony().isCapable(mSubId, capability, imsRegTech); 566 } catch (RemoteException e) { 567 throw e.rethrowAsRuntimeException(); 568 } 569 } 570 571 /** 572 * Query the availability of an IMS MmTel capability for a given registration technology. If 573 * a capability is available, IMS is registered and the service is currently available over IMS. 574 * 575 * @see #isCapable(int, int) 576 * 577 * @param imsRegTech The IMS registration technology, can be one of the following: 578 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}, 579 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} 580 * @param capability The IMS MmTel capability to query, can be one of the following: 581 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, 582 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO, 583 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, 584 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} 585 * @return {@code true} if the MmTel IMS capability is available for this subscription, false 586 * otherwise. 587 */ 588 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isAvailable(@mTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech)589 public boolean isAvailable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, 590 @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) { 591 try { 592 return getITelephony().isAvailable(mSubId, capability, imsRegTech); 593 } catch (RemoteException e) { 594 throw e.rethrowAsRuntimeException(); 595 } 596 } 597 598 /** 599 * The user's setting for whether or not they have enabled the "Video Calling" setting. 600 * @return true if the user’s “Video Calling” setting is currently enabled. 601 * @see #setVtSettingEnabled(boolean) 602 */ 603 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isVtSettingEnabled()604 public boolean isVtSettingEnabled() { 605 try { 606 return getITelephony().isVtSettingEnabled(mSubId); 607 } catch (RemoteException e) { 608 throw e.rethrowAsRuntimeException(); 609 } 610 } 611 612 /** 613 * Change the user's setting for Video Telephony and enable the Video Telephony capability. 614 * @see #isVtSettingEnabled() 615 */ 616 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVtSettingEnabled(boolean isEnabled)617 public void setVtSettingEnabled(boolean isEnabled) { 618 try { 619 getITelephony().setVtSettingEnabled(mSubId, isEnabled); 620 return; 621 } catch (RemoteException e) { 622 throw e.rethrowAsRuntimeException(); 623 } 624 } 625 626 /** 627 * @return true if the user's setting for Voice over WiFi is enabled and false if it is not. 628 * @see #setVoWiFiSettingEnabled(boolean) 629 */ 630 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isVoWiFiSettingEnabled()631 public boolean isVoWiFiSettingEnabled() { 632 try { 633 return getITelephony().isVoWiFiSettingEnabled(mSubId); 634 } catch (RemoteException e) { 635 throw e.rethrowAsRuntimeException(); 636 } 637 } 638 639 /** 640 * Sets the user's setting for whether or not Voice over WiFi is enabled. 641 * @param isEnabled true if the user's setting for Voice over WiFi is enabled, false otherwise= 642 * @see #isVoWiFiSettingEnabled() 643 */ 644 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiSettingEnabled(boolean isEnabled)645 public void setVoWiFiSettingEnabled(boolean isEnabled) { 646 try { 647 getITelephony().setVoWiFiSettingEnabled(mSubId, isEnabled); 648 return; 649 } catch (RemoteException e) { 650 throw e.rethrowAsRuntimeException(); 651 } 652 } 653 654 /** 655 * @return true if the user's setting for Voice over WiFi while roaming is enabled, false 656 * if disabled. 657 * @see #setVoWiFiRoamingSettingEnabled(boolean) 658 */ 659 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isVoWiFiRoamingSettingEnabled()660 public boolean isVoWiFiRoamingSettingEnabled() { 661 try { 662 return getITelephony().isVoWiFiRoamingSettingEnabled(mSubId); 663 } catch (RemoteException e) { 664 throw e.rethrowAsRuntimeException(); 665 } 666 } 667 668 /** 669 * Change the user's setting for Voice over WiFi while roaming. 670 * @param isEnabled true if the user's setting for Voice over WiFi while roaming is enabled, 671 * false otherwise. 672 * @see #isVoWiFiRoamingSettingEnabled() 673 */ 674 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiRoamingSettingEnabled(boolean isEnabled)675 public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) { 676 try { 677 getITelephony().setVoWiFiRoamingSettingEnabled(mSubId, isEnabled); 678 return; 679 } catch (RemoteException e) { 680 throw e.rethrowAsRuntimeException(); 681 } 682 } 683 684 /** 685 * Overrides the Voice over WiFi capability to true for IMS, but do not persist the setting. 686 * Typically used during the Voice over WiFi registration process for some carriers. 687 * 688 * @param isCapable true if the IMS stack should try to register for IMS over IWLAN, false 689 * otherwise. 690 * @param mode the Voice over WiFi mode preference to set, which can be one of the following: 691 * - {@link #WIFI_MODE_WIFI_ONLY} 692 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 693 * - {@link #WIFI_MODE_WIFI_PREFERRED} 694 * @see #setVoWiFiSettingEnabled(boolean) 695 */ 696 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiNonPersistent(boolean isCapable, int mode)697 public void setVoWiFiNonPersistent(boolean isCapable, int mode) { 698 try { 699 getITelephony().setVoWiFiNonPersistent(mSubId, isCapable, mode); 700 return; 701 } catch (RemoteException e) { 702 throw e.rethrowAsRuntimeException(); 703 } 704 } 705 706 /** 707 * @return The Voice over WiFi Mode preference set by the user, which can be one of the 708 * following: 709 * - {@link #WIFI_MODE_WIFI_ONLY} 710 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 711 * - {@link #WIFI_MODE_WIFI_PREFERRED} 712 * @see #setVoWiFiSettingEnabled(boolean) 713 */ 714 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getVoWiFiModeSetting()715 public @WiFiCallingMode int getVoWiFiModeSetting() { 716 try { 717 return getITelephony().getVoWiFiModeSetting(mSubId); 718 } catch (RemoteException e) { 719 throw e.rethrowAsRuntimeException(); 720 } 721 } 722 723 /** 724 * Set the user's preference for Voice over WiFi calling mode. 725 * @param mode The user's preference for the technology to register for IMS over, can be one of 726 * the following: 727 * - {@link #WIFI_MODE_WIFI_ONLY} 728 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 729 * - {@link #WIFI_MODE_WIFI_PREFERRED} 730 * @see #getVoWiFiModeSetting() 731 */ 732 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiModeSetting(@iFiCallingMode int mode)733 public void setVoWiFiModeSetting(@WiFiCallingMode int mode) { 734 try { 735 getITelephony().setVoWiFiModeSetting(mSubId, mode); 736 return; 737 } catch (RemoteException e) { 738 throw e.rethrowAsRuntimeException(); 739 } 740 } 741 742 /** 743 * Set the user's preference for Voice over WiFi calling mode while the device is roaming on 744 * another network. 745 * 746 * @return The user's preference for the technology to register for IMS over when roaming on 747 * another network, can be one of the following: 748 * - {@link #WIFI_MODE_WIFI_ONLY} 749 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 750 * - {@link #WIFI_MODE_WIFI_PREFERRED} 751 * @see #setVoWiFiRoamingSettingEnabled(boolean) 752 */ 753 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getVoWiFiRoamingModeSetting()754 public @WiFiCallingMode int getVoWiFiRoamingModeSetting() { 755 try { 756 return getITelephony().getVoWiFiRoamingModeSetting(mSubId); 757 } catch (RemoteException e) { 758 throw e.rethrowAsRuntimeException(); 759 } 760 } 761 762 /** 763 * Set the user's preference for Voice over WiFi mode while the device is roaming on another 764 * network. 765 * 766 * @param mode The user's preference for the technology to register for IMS over when roaming on 767 * another network, can be one of the following: 768 * - {@link #WIFI_MODE_WIFI_ONLY} 769 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 770 * - {@link #WIFI_MODE_WIFI_PREFERRED} 771 * @see #getVoWiFiRoamingModeSetting() 772 */ 773 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiRoamingModeSetting(@iFiCallingMode int mode)774 public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) { 775 try { 776 getITelephony().setVoWiFiRoamingModeSetting(mSubId, mode); 777 return; 778 } catch (RemoteException e) { 779 throw e.rethrowAsRuntimeException(); 780 } 781 } 782 783 /** 784 * Sets the capability of RTT for IMS calls placed on this subscription. 785 * 786 * Note: This does not affect the value of 787 * {@link android.provider.Settings.Secure#RTT_CALLING_MODE}, which is the global user setting 788 * for RTT. That value is enabled/disabled separately by the user through the Accessibility 789 * settings. 790 * @param isEnabled if true RTT should be enabled during calls made on this subscription. 791 */ 792 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setRttCapabilitySetting(boolean isEnabled)793 public void setRttCapabilitySetting(boolean isEnabled) { 794 try { 795 getITelephony().setRttCapabilitySetting(mSubId, isEnabled); 796 return; 797 } catch (RemoteException e) { 798 throw e.rethrowAsRuntimeException(); 799 } 800 } 801 802 /** 803 * @return true if TTY over VoLTE is supported 804 * @see android.telecom.TelecomManager#getCurrentTtyMode 805 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL 806 */ 807 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isTtyOverVolteEnabled()808 boolean isTtyOverVolteEnabled() { 809 try { 810 return getITelephony().isTtyOverVolteEnabled(mSubId); 811 } catch (RemoteException e) { 812 throw e.rethrowAsRuntimeException(); 813 } 814 } 815 isImsAvailableOnDevice()816 private static boolean isImsAvailableOnDevice() { 817 IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 818 if (pm == null) { 819 // For some reason package manger is not available.. This will fail internally anyways, 820 // so do not throw error and allow. 821 return true; 822 } 823 try { 824 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0); 825 } catch (RemoteException e) { 826 // For some reason package manger is not available.. This will fail internally anyways, 827 // so do not throw error and allow. 828 } 829 return true; 830 } 831 getITelephony()832 private static ITelephony getITelephony() { 833 ITelephony binder = ITelephony.Stub.asInterface( 834 ServiceManager.getService(Context.TELEPHONY_SERVICE)); 835 if (binder == null) { 836 throw new RuntimeException("Could not find Telephony Service."); 837 } 838 return binder; 839 } 840 } 841