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.RequiresPermission; 25 import android.annotation.SuppressAutoDoc; 26 import android.annotation.SuppressLint; 27 import android.annotation.SystemApi; 28 import android.annotation.TestApi; 29 import android.os.Binder; 30 import android.os.RemoteException; 31 import android.os.ServiceSpecificException; 32 import android.telephony.AccessNetworkConstants; 33 import android.telephony.CarrierConfigManager; 34 import android.telephony.SubscriptionManager; 35 import android.telephony.TelephonyFrameworkInitializer; 36 import android.telephony.ims.aidl.IImsCapabilityCallback; 37 import android.telephony.ims.feature.ImsFeature; 38 import android.telephony.ims.feature.MmTelFeature; 39 import android.telephony.ims.stub.ImsRegistrationImplBase; 40 41 import com.android.internal.annotations.VisibleForTesting; 42 import com.android.internal.telephony.IIntegerConsumer; 43 import com.android.internal.telephony.ITelephony; 44 45 import java.lang.annotation.Retention; 46 import java.lang.annotation.RetentionPolicy; 47 import java.util.concurrent.Executor; 48 import java.util.function.Consumer; 49 50 /** 51 * A manager for the MmTel (Multimedia Telephony) feature of an IMS network, given an associated 52 * subscription. 53 * 54 * Allows a user to query the IMS MmTel feature information for a subscription, register for 55 * registration and MmTel capability status callbacks, as well as query/modify user settings for the 56 * associated subscription. 57 * 58 * Use {@link android.telephony.ims.ImsManager#getImsMmTelManager(int)} to get an instance of this 59 * manager. 60 */ 61 public class ImsMmTelManager implements RegistrationManager { 62 63 /** 64 * @hide 65 */ 66 @Retention(RetentionPolicy.SOURCE) 67 @IntDef(prefix = "WIFI_MODE_", value = { 68 WIFI_MODE_WIFI_ONLY, 69 WIFI_MODE_CELLULAR_PREFERRED, 70 WIFI_MODE_WIFI_PREFERRED 71 }) 72 public @interface WiFiCallingMode {} 73 74 /** 75 * Register for IMS over IWLAN if WiFi signal quality is high enough. Do not hand over to LTE 76 * registration if signal quality degrades. 77 */ 78 public static final int WIFI_MODE_WIFI_ONLY = 0; 79 80 /** 81 * Prefer registering for IMS over LTE if LTE signal quality is high enough. 82 */ 83 public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; 84 85 /** 86 * Prefer registering for IMS over IWLAN if possible if WiFi signal quality is high enough. 87 */ 88 public static final int WIFI_MODE_WIFI_PREFERRED = 2; 89 90 /** 91 * Callback class for receiving IMS network Registration callback events. 92 * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback) 93 * @see #unregisterImsRegistrationCallback(RegistrationCallback) 94 * @deprecated Use {@link RegistrationManager.RegistrationCallback} instead. 95 * @hide 96 */ 97 // Do not add to this class, add to RegistrationManager.RegistrationCallback instead. 98 @Deprecated 99 @SystemApi @TestApi 100 public static class RegistrationCallback extends RegistrationManager.RegistrationCallback { 101 102 /** 103 * Notifies the framework when the IMS Provider is registered to the IMS network. 104 * 105 * @param imsTransportType the radio access technology. 106 */ 107 @Override onRegistered(@ccessNetworkConstants.TransportType int imsTransportType)108 public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) { 109 } 110 111 /** 112 * Notifies the framework when the IMS Provider is trying to register the IMS network. 113 * 114 * @param imsTransportType the radio access technology. 115 */ 116 @Override onRegistering(@ccessNetworkConstants.TransportType int imsTransportType)117 public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) { 118 } 119 120 /** 121 * Notifies the framework when the IMS Provider is deregistered from the IMS network. 122 * 123 * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. 124 */ 125 @Override onUnregistered(@onNull ImsReasonInfo info)126 public void onUnregistered(@NonNull ImsReasonInfo info) { 127 } 128 129 /** 130 * A failure has occurred when trying to handover registration to another technology type. 131 * 132 * @param imsTransportType The transport type that has failed to handover registration to. 133 * @param info A {@link ImsReasonInfo} that identifies the reason for failure. 134 */ 135 @Override onTechnologyChangeFailed( @ccessNetworkConstants.TransportType int imsTransportType, @NonNull ImsReasonInfo info)136 public void onTechnologyChangeFailed( 137 @AccessNetworkConstants.TransportType int imsTransportType, 138 @NonNull ImsReasonInfo info) { 139 } 140 } 141 142 /** 143 * Receives IMS capability status updates from the ImsService. 144 * 145 * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback) 146 * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) 147 */ 148 public static class CapabilityCallback { 149 150 private static class CapabilityBinder extends IImsCapabilityCallback.Stub { 151 152 private final CapabilityCallback mLocalCallback; 153 private Executor mExecutor; 154 CapabilityBinder(CapabilityCallback c)155 CapabilityBinder(CapabilityCallback c) { 156 mLocalCallback = c; 157 } 158 159 @Override onCapabilitiesStatusChanged(int config)160 public void onCapabilitiesStatusChanged(int config) { 161 if (mLocalCallback == null) return; 162 163 long callingIdentity = Binder.clearCallingIdentity(); 164 try { 165 mExecutor.execute(() -> mLocalCallback.onCapabilitiesStatusChanged( 166 new MmTelFeature.MmTelCapabilities(config))); 167 } finally { 168 restoreCallingIdentity(callingIdentity); 169 } 170 } 171 172 @Override onQueryCapabilityConfiguration(int capability, int radioTech, boolean isEnabled)173 public void onQueryCapabilityConfiguration(int capability, int radioTech, 174 boolean isEnabled) { 175 // This is not used for public interfaces. 176 } 177 178 @Override onChangeCapabilityConfigurationError(int capability, int radioTech, @ImsFeature.ImsCapabilityError int reason)179 public void onChangeCapabilityConfigurationError(int capability, int radioTech, 180 @ImsFeature.ImsCapabilityError int reason) { 181 // This is not used for public interfaces 182 } 183 setExecutor(Executor executor)184 private void setExecutor(Executor executor) { 185 mExecutor = executor; 186 } 187 } 188 189 private final CapabilityBinder mBinder = new CapabilityBinder(this); 190 191 /** 192 * The status of the feature's capabilities has changed to either available or unavailable. 193 * If unavailable, the feature is not able to support the unavailable capability at this 194 * time. 195 * 196 * @param capabilities The new availability of the capabilities. 197 */ onCapabilitiesStatusChanged( @onNull MmTelFeature.MmTelCapabilities capabilities)198 public void onCapabilitiesStatusChanged( 199 @NonNull MmTelFeature.MmTelCapabilities capabilities) { 200 } 201 202 /**@hide*/ getBinder()203 public final IImsCapabilityCallback getBinder() { 204 return mBinder; 205 } 206 207 /**@hide*/ 208 // Only exposed as public method for compatibility with deprecated ImsManager APIs. 209 // TODO: clean up dependencies and change back to private visibility. setExecutor(Executor executor)210 public final void setExecutor(Executor executor) { 211 mBinder.setExecutor(executor); 212 } 213 } 214 215 private final int mSubId; 216 217 /** 218 * Create an instance of {@link ImsMmTelManager} for the subscription id specified. 219 * 220 * @param subId The ID of the subscription that this ImsMmTelManager will use. 221 * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList() 222 * 223 * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE 224 * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges 225 * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). 226 * 227 * @throws IllegalArgumentException if the subscription is invalid. 228 * @deprecated Use {@link android.telephony.ims.ImsManager#getImsMmTelManager(int)} to get an 229 * instance of this class. 230 * @hide 231 */ 232 @SystemApi 233 @TestApi 234 @Deprecated 235 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 236 @RequiresPermission(anyOf = { 237 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 238 android.Manifest.permission.READ_PRECISE_PHONE_STATE 239 }) 240 @SuppressLint("ManagerLookup") createForSubscriptionId(int subId)241 public static @NonNull ImsMmTelManager createForSubscriptionId(int subId) { 242 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 243 throw new IllegalArgumentException("Invalid subscription ID"); 244 } 245 246 return new ImsMmTelManager(subId); 247 } 248 249 /** 250 * Only visible for testing, use {@link ImsManager#getImsMmTelManager(int)} instead. 251 * @hide 252 */ 253 @VisibleForTesting ImsMmTelManager(int subId)254 public ImsMmTelManager(int subId) { 255 mSubId = subId; 256 } 257 258 /** 259 * Registers a {@link RegistrationCallback} with the system, which will provide registration 260 * updates for the subscription specified in {@link ImsManager#getImsMmTelManager(int)}. Use 261 * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed 262 * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. 263 * 264 * When the callback is registered, it will initiate the callback c to be called with the 265 * current registration state. 266 * 267 * @param executor The executor the callback events should be run on. 268 * @param c The {@link RegistrationCallback} to be added. 269 * @see #unregisterImsRegistrationCallback(RegistrationCallback) 270 * @throws IllegalArgumentException if the subscription associated with this callback is not 271 * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or 272 * {@link CapabilityCallback} callback. 273 * @throws ImsException if the subscription associated with this callback is valid, but 274 * the {@link ImsService} associated with the subscription is not available. This can happen if 275 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed 276 * reason. 277 * @deprecated Use {@link RegistrationManager#registerImsRegistrationCallback(Executor, 278 * RegistrationManager.RegistrationCallback)} instead. 279 * @hide 280 */ 281 @Deprecated 282 @SystemApi @TestApi 283 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) registerImsRegistrationCallback(@onNull @allbackExecutor Executor executor, @NonNull RegistrationCallback c)284 public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, 285 @NonNull RegistrationCallback c) throws ImsException { 286 if (c == null) { 287 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 288 } 289 if (executor == null) { 290 throw new IllegalArgumentException("Must include a non-null Executor."); 291 } 292 c.setExecutor(executor); 293 294 ITelephony iTelephony = getITelephony(); 295 if (iTelephony == null) { 296 throw new ImsException("Could not find Telephony Service.", 297 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 298 } 299 300 try { 301 iTelephony.registerImsRegistrationCallback(mSubId, c.getBinder()); 302 } catch (ServiceSpecificException e) { 303 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 304 // Rethrow as runtime error to keep API compatible. 305 throw new IllegalArgumentException(e.getMessage()); 306 } else { 307 throw new ImsException(e.getMessage(), e.errorCode); 308 } 309 } catch (RemoteException | IllegalStateException e) { 310 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 311 } 312 } 313 314 /** 315 * 316 * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE 317 * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges 318 * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). 319 * 320 * {@inheritDoc} 321 * 322 */ 323 @Override 324 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 325 @RequiresPermission(anyOf = { 326 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 327 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) registerImsRegistrationCallback(@onNull @allbackExecutor Executor executor, @NonNull RegistrationManager.RegistrationCallback c)328 public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, 329 @NonNull RegistrationManager.RegistrationCallback c) throws ImsException { 330 if (c == null) { 331 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 332 } 333 if (executor == null) { 334 throw new IllegalArgumentException("Must include a non-null Executor."); 335 } 336 c.setExecutor(executor); 337 338 ITelephony iTelephony = getITelephony(); 339 if (iTelephony == null) { 340 throw new ImsException("Could not find Telephony Service.", 341 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 342 } 343 344 try { 345 iTelephony.registerImsRegistrationCallback(mSubId, c.getBinder()); 346 } catch (ServiceSpecificException e) { 347 throw new ImsException(e.getMessage(), e.errorCode); 348 } catch (RemoteException | IllegalStateException e) { 349 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 350 } 351 } 352 353 /** 354 * Removes an existing {@link RegistrationCallback}. 355 * 356 * When the subscription associated with this callback is removed (SIM removed, ESIM swap, 357 * etc...), this callback will automatically be removed. If this method is called for an 358 * inactive subscription, it will result in a no-op. 359 * 360 * @param c The {@link RegistrationCallback} to be removed. 361 * @see SubscriptionManager.OnSubscriptionsChangedListener 362 * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) 363 * @deprecated Use {@link #unregisterImsRegistrationCallback( 364 * RegistrationManager.RegistrationCallback)}. 365 * @hide 366 */ 367 @Deprecated 368 @SystemApi @TestApi 369 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) unregisterImsRegistrationCallback(@onNull RegistrationCallback c)370 public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) { 371 if (c == null) { 372 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 373 } 374 375 ITelephony iTelephony = getITelephony(); 376 if (iTelephony == null) { 377 throw new RuntimeException("Could not find Telephony Service."); 378 } 379 380 try { 381 iTelephony.unregisterImsRegistrationCallback(mSubId, c.getBinder()); 382 } catch (RemoteException e) { 383 throw e.rethrowAsRuntimeException(); 384 } 385 } 386 387 /** 388 * 389 * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE 390 * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges 391 * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). 392 * Access by profile owners is deprecated and will be removed in a future release. 393 * 394 *{@inheritDoc} 395 */ 396 @Override 397 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 398 @RequiresPermission(anyOf = { 399 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 400 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) unregisterImsRegistrationCallback( @onNull RegistrationManager.RegistrationCallback c)401 public void unregisterImsRegistrationCallback( 402 @NonNull RegistrationManager.RegistrationCallback c) { 403 if (c == null) { 404 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 405 } 406 407 ITelephony iTelephony = getITelephony(); 408 if (iTelephony == null) { 409 throw new RuntimeException("Could not find Telephony Service."); 410 } 411 412 try { 413 iTelephony.unregisterImsRegistrationCallback(mSubId, c.getBinder()); 414 } catch (RemoteException e) { 415 throw e.rethrowAsRuntimeException(); 416 } 417 } 418 419 /** 420 * {@inheritDoc} 421 * @hide 422 */ 423 @Override 424 @SystemApi @TestApi 425 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getRegistrationState(@onNull @allbackExecutor Executor executor, @NonNull @ImsRegistrationState Consumer<Integer> stateCallback)426 public void getRegistrationState(@NonNull @CallbackExecutor Executor executor, 427 @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) { 428 if (stateCallback == null) { 429 throw new IllegalArgumentException("Must include a non-null callback."); 430 } 431 if (executor == null) { 432 throw new IllegalArgumentException("Must include a non-null Executor."); 433 } 434 435 ITelephony iTelephony = getITelephony(); 436 if (iTelephony == null) { 437 throw new RuntimeException("Could not find Telephony Service."); 438 } 439 440 try { 441 iTelephony.getImsMmTelRegistrationState(mSubId, new IIntegerConsumer.Stub() { 442 @Override 443 public void accept(int result) { 444 executor.execute(() -> stateCallback.accept(result)); 445 } 446 }); 447 } catch (RemoteException e) { 448 throw e.rethrowAsRuntimeException(); 449 } 450 } 451 452 /** 453 * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE 454 * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges 455 * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). 456 * Access by profile owners is deprecated and will be removed in a future release. 457 * 458 *{@inheritDoc} 459 */ 460 @Override 461 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 462 @RequiresPermission(anyOf = { 463 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 464 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) getRegistrationTransportType(@onNull @allbackExecutor Executor executor, @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback)465 public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor, 466 @NonNull @AccessNetworkConstants.TransportType 467 Consumer<Integer> transportTypeCallback) { 468 if (transportTypeCallback == null) { 469 throw new IllegalArgumentException("Must include a non-null callback."); 470 } 471 if (executor == null) { 472 throw new IllegalArgumentException("Must include a non-null Executor."); 473 } 474 475 ITelephony iTelephony = getITelephony(); 476 if (iTelephony == null) { 477 throw new RuntimeException("Could not find Telephony Service."); 478 } 479 480 try { 481 iTelephony.getImsMmTelRegistrationTransportType(mSubId, 482 new IIntegerConsumer.Stub() { 483 @Override 484 public void accept(int result) { 485 executor.execute(() -> transportTypeCallback.accept(result)); 486 } 487 }); 488 } catch (RemoteException e) { 489 throw e.rethrowAsRuntimeException(); 490 } 491 } 492 493 /** 494 * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service 495 * availability updates for the subscription specified in 496 * {@link ImsManager#getImsMmTelManager(int)}. 497 * 498 * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to 499 * subscription changed events and call 500 * {@link #unregisterMmTelCapabilityCallback(CapabilityCallback)} to clean up. 501 * <p>This API requires one of the following: 502 * <ul> 503 * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> 504 * <li>If the caller is the device or profile owner, the caller holds the 505 * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> 506 * <li>The caller has carrier privileges (see 507 * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any 508 * active subscription.</li> 509 * <li>The caller is the default SMS app for the device.</li> 510 * </ul> 511 * <p>The profile owner is an app that owns a managed profile on the device; for more details 512 * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. 513 * Access by profile owners is deprecated and will be removed in a future release. 514 * 515 * When the callback is registered, it will initiate the callback c to be called with the 516 * current capabilities. 517 * 518 * @param executor The executor the callback events should be run on. 519 * @param c The MmTel {@link CapabilityCallback} to be registered. 520 * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) 521 * @throws ImsException if the subscription associated with this callback is valid, but 522 * the {@link ImsService} associated with the subscription is not available. This can happen if 523 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed 524 * reason. 525 */ 526 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 527 @RequiresPermission(anyOf = { 528 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 529 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) registerMmTelCapabilityCallback(@onNull @allbackExecutor Executor executor, @NonNull CapabilityCallback c)530 public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor, 531 @NonNull CapabilityCallback c) throws ImsException { 532 if (c == null) { 533 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 534 } 535 if (executor == null) { 536 throw new IllegalArgumentException("Must include a non-null Executor."); 537 } 538 c.setExecutor(executor); 539 540 ITelephony iTelephony = getITelephony(); 541 if (iTelephony == null) { 542 throw new ImsException("Could not find Telephony Service.", 543 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 544 } 545 546 try { 547 iTelephony.registerMmTelCapabilityCallback(mSubId, c.getBinder()); 548 } catch (ServiceSpecificException e) { 549 throw new ImsException(e.getMessage(), e.errorCode); 550 } catch (RemoteException e) { 551 throw e.rethrowAsRuntimeException(); 552 } catch (IllegalStateException e) { 553 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 554 } 555 } 556 557 /** 558 * Removes an existing MmTel {@link CapabilityCallback}. 559 * 560 * When the subscription associated with this callback is removed (SIM removed, ESIM swap, 561 * etc...), this callback will automatically be removed. If this method is called for an 562 * inactive subscription, it will result in a no-op. 563 * <p>This API requires one of the following: 564 * <ul> 565 * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> 566 * <li>If the caller is the device or profile owner, the caller holds the 567 * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> 568 * <li>The caller has carrier privileges (see 569 * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any 570 * active subscription.</li> 571 * <li>The caller is the default SMS app for the device.</li> 572 * </ul> 573 * <p>The profile owner is an app that owns a managed profile on the device; for more details 574 * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. 575 * Access by profile owners is deprecated and will be removed in a future release. 576 * 577 * @param c The MmTel {@link CapabilityCallback} to be removed. 578 * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) 579 */ 580 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 581 @RequiresPermission(anyOf = { 582 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 583 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) unregisterMmTelCapabilityCallback(@onNull CapabilityCallback c)584 public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) { 585 if (c == null) { 586 throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); 587 } 588 589 ITelephony iTelephony = getITelephony(); 590 if (iTelephony == null) { 591 throw new RuntimeException("Could not find Telephony Service."); 592 } 593 594 try { 595 iTelephony.unregisterMmTelCapabilityCallback(mSubId, c.getBinder()); 596 } catch (RemoteException e) { 597 throw e.rethrowAsRuntimeException(); 598 } 599 } 600 601 /** 602 * Query the user’s setting for “Advanced Calling” or "Enhanced 4G LTE", which is used to 603 * enable MmTel IMS features, depending on the carrier configuration for the current 604 * subscription. If this setting is enabled, IMS voice and video telephony over IWLAN/LTE will 605 * be enabled as long as the carrier has provisioned these services for the specified 606 * subscription. Other IMS services (SMS/UT) are not affected by this user setting and depend on 607 * carrier requirements. 608 * <p> 609 * Note: If the carrier configuration for advanced calling is not editable or hidden, this 610 * method will always return the default value. 611 * <p>This API requires one of the following: 612 * <ul> 613 * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> 614 * <li>If the caller is the device or profile owner, the caller holds the 615 * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> 616 * <li>The caller has carrier privileges (see 617 * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any 618 * active subscription.</li> 619 * <li>The caller is the default SMS app for the device.</li> 620 * </ul> 621 * <p>The profile owner is an app that owns a managed profile on the device; for more details 622 * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. 623 * Access by profile owners is deprecated and will be removed in a future release. 624 * 625 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL 626 * @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL 627 * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL 628 * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL 629 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL 630 * @throws IllegalArgumentException if the subscription associated with this operation is not 631 * active (SIM is not inserted, ESIM inactive) or invalid. 632 * @return true if the user's setting for advanced calling is enabled, false otherwise. 633 */ 634 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 635 @RequiresPermission(anyOf = { 636 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 637 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) isAdvancedCallingSettingEnabled()638 public boolean isAdvancedCallingSettingEnabled() { 639 ITelephony iTelephony = getITelephony(); 640 if (iTelephony == null) { 641 throw new RuntimeException("Could not find Telephony Service."); 642 } 643 644 try { 645 return iTelephony.isAdvancedCallingSettingEnabled(mSubId); 646 } catch (ServiceSpecificException e) { 647 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 648 // Rethrow as runtime error to keep API compatible. 649 throw new IllegalArgumentException(e.getMessage()); 650 } else { 651 throw new RuntimeException(e.getMessage()); 652 } 653 } catch (RemoteException e) { 654 throw e.rethrowAsRuntimeException(); 655 } 656 } 657 658 /** 659 * Modify the user’s setting for “Advanced Calling” or "Enhanced 4G LTE", which is used to 660 * enable MmTel IMS features, depending on the carrier configuration for the current 661 * subscription. If this setting is enabled, IMS voice and video telephony over IWLAN/LTE will 662 * be enabled as long as the carrier has provisioned these services for the specified 663 * subscription. Other IMS services (SMS/UT) are not affected by this user setting and depend on 664 * carrier requirements. 665 * 666 * Modifying this value may also trigger an IMS registration or deregistration, depending on 667 * whether or not the new value is enabled or disabled. 668 * 669 * Note: If the carrier configuration for advanced calling is not editable or hidden, this 670 * method will do nothing and will instead always use the default value. 671 * 672 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL 673 * @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL 674 * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL 675 * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL 676 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL 677 * @see #isAdvancedCallingSettingEnabled() 678 * @throws IllegalArgumentException if the subscription associated with this operation is not 679 * active (SIM is not inserted, ESIM inactive) or invalid. 680 * @hide 681 */ 682 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) 683 @SystemApi @TestApi setAdvancedCallingSettingEnabled(boolean isEnabled)684 public void setAdvancedCallingSettingEnabled(boolean isEnabled) { 685 ITelephony iTelephony = getITelephony(); 686 if (iTelephony == null) { 687 throw new RuntimeException("Could not find Telephony Service."); 688 } 689 690 try { 691 iTelephony.setAdvancedCallingSettingEnabled(mSubId, isEnabled); 692 } catch (ServiceSpecificException e) { 693 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 694 // Rethrow as runtime error to keep API compatible. 695 throw new IllegalArgumentException(e.getMessage()); 696 } else { 697 throw new RuntimeException(e.getMessage()); 698 } 699 } catch (RemoteException e) { 700 throw e.rethrowAsRuntimeException(); 701 } 702 } 703 704 /** 705 * Query the IMS MmTel capability for a given registration technology. This does not 706 * necessarily mean that we are registered and the capability is available, but rather the 707 * subscription is capable of this service over IMS. 708 * 709 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL 710 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VT_AVAILABLE_BOOL 711 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_IMS_GBA_REQUIRED_BOOL 712 * @see #isAvailable(int, int) 713 * 714 * @param imsRegTech The IMS registration technology, can be one of the following: 715 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}, 716 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} 717 * @param capability The IMS MmTel capability to query, can be one of the following: 718 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, 719 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, 720 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, 721 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} 722 * @return {@code true} if the MmTel IMS capability is capable for this subscription, false 723 * otherwise. 724 * @hide 725 */ 726 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 727 @SystemApi @TestApi isCapable(@mTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech)728 public boolean isCapable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, 729 @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) { 730 ITelephony iTelephony = getITelephony(); 731 if (iTelephony == null) { 732 throw new RuntimeException("Could not find Telephony Service."); 733 } 734 735 try { 736 return iTelephony.isCapable(mSubId, capability, imsRegTech); 737 } catch (RemoteException e) { 738 throw e.rethrowAsRuntimeException(); 739 } 740 } 741 742 /** 743 * Query the availability of an IMS MmTel capability for a given registration technology. If 744 * a capability is available, IMS is registered and the service is currently available over IMS. 745 * 746 * @see #isCapable(int, int) 747 * 748 * @param imsRegTech The IMS registration technology, can be one of the following: 749 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}, 750 * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} 751 * @param capability The IMS MmTel capability to query, can be one of the following: 752 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, 753 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, 754 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, 755 * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} 756 * @return {@code true} if the MmTel IMS capability is available for this subscription, false 757 * otherwise. 758 * @hide 759 */ 760 @SystemApi @TestApi 761 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isAvailable(@mTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech)762 public boolean isAvailable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, 763 @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) { 764 ITelephony iTelephony = getITelephony(); 765 if (iTelephony == null) { 766 throw new RuntimeException("Could not find Telephony Service."); 767 } 768 769 try { 770 return iTelephony.isAvailable(mSubId, capability, imsRegTech); 771 } catch (RemoteException e) { 772 throw e.rethrowAsRuntimeException(); 773 } 774 } 775 776 /** 777 * Query whether or not the requested MmTel capability is supported by the carrier on the 778 * specified network transport. 779 * <p> 780 * This is a configuration option and does not change. The only time this may change is if a 781 * new IMS configuration is loaded when there is a 782 * {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} broadcast for this subscription. 783 * @param capability The capability that is being queried for support on the carrier network. 784 * @param transportType The transport type of the capability to check support for. 785 * @param executor The executor that the callback will be called with. 786 * @param callback A consumer containing a Boolean result specifying whether or not the 787 * capability is supported on this carrier network for the transport specified. 788 * @throws ImsException if the subscription is no longer valid or the IMS service is not 789 * available. 790 * @hide 791 */ 792 @SystemApi @TestApi 793 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isSupported(@mTelFeature.MmTelCapabilities.MmTelCapability int capability, @AccessNetworkConstants.TransportType int transportType, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)794 public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, 795 @AccessNetworkConstants.TransportType int transportType, 796 @NonNull @CallbackExecutor Executor executor, 797 @NonNull Consumer<Boolean> callback) throws ImsException { 798 if (callback == null) { 799 throw new IllegalArgumentException("Must include a non-null Consumer."); 800 } 801 if (executor == null) { 802 throw new IllegalArgumentException("Must include a non-null Executor."); 803 } 804 805 ITelephony iTelephony = getITelephony(); 806 if (iTelephony == null) { 807 throw new ImsException("Could not find Telephony Service.", 808 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 809 } 810 811 try { 812 getITelephony().isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() { 813 @Override 814 public void accept(int result) { 815 executor.execute(() -> callback.accept(result == 1)); 816 } 817 }, capability, transportType); 818 } catch (ServiceSpecificException sse) { 819 throw new ImsException(sse.getMessage(), sse.errorCode); 820 } catch (RemoteException e) { 821 e.rethrowAsRuntimeException(); 822 } 823 } 824 825 /** 826 * The user's setting for whether or not they have enabled the "Video Calling" setting. 827 * 828 * <p> 829 * Note: If the carrier configuration for advanced calling is not editable or hidden, this 830 * method will always return the default value. 831 * <p>This API requires one of the following: 832 * <ul> 833 * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> 834 * <li>If the caller is the device or profile owner, the caller holds the 835 * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> 836 * <li>The caller has carrier privileges (see 837 * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any 838 * active subscription.</li> 839 * <li>The caller is the default SMS app for the device.</li> 840 * </ul> 841 * <p>The profile owner is an app that owns a managed profile on the device; for more details 842 * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. 843 * Access by profile owners is deprecated and will be removed in a future release. 844 * 845 * @throws IllegalArgumentException if the subscription associated with this operation is not 846 * active (SIM is not inserted, ESIM inactive) or invalid. 847 * @return true if the user’s “Video Calling” setting is currently enabled. 848 */ 849 @RequiresPermission(anyOf = { 850 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 851 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) 852 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). isVtSettingEnabled()853 public boolean isVtSettingEnabled() { 854 ITelephony iTelephony = getITelephony(); 855 if (iTelephony == null) { 856 throw new RuntimeException("Could not find Telephony Service."); 857 } 858 859 try { 860 return iTelephony.isVtSettingEnabled(mSubId); 861 } catch (ServiceSpecificException e) { 862 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 863 // Rethrow as runtime error to keep API compatible. 864 throw new IllegalArgumentException(e.getMessage()); 865 } else { 866 throw new RuntimeException(e.getMessage()); 867 } 868 } catch (RemoteException e) { 869 throw e.rethrowAsRuntimeException(); 870 } 871 } 872 873 /** 874 * Change the user's setting for Video Telephony and enable the Video Telephony capability. 875 * 876 * @throws IllegalArgumentException if the subscription associated with this operation is not 877 * active (SIM is not inserted, ESIM inactive) or invalid. 878 * @see #isVtSettingEnabled() 879 * @hide 880 */ 881 @SystemApi @TestApi 882 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVtSettingEnabled(boolean isEnabled)883 public void setVtSettingEnabled(boolean isEnabled) { 884 ITelephony iTelephony = getITelephony(); 885 if (iTelephony == null) { 886 throw new RuntimeException("Could not find Telephony Service."); 887 } 888 889 try { 890 iTelephony.setVtSettingEnabled(mSubId, isEnabled); 891 } catch (ServiceSpecificException e) { 892 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 893 // Rethrow as runtime error to keep API compatible. 894 throw new IllegalArgumentException(e.getMessage()); 895 } else { 896 throw new RuntimeException(e.getMessage()); 897 } 898 } catch (RemoteException e) { 899 throw e.rethrowAsRuntimeException(); 900 } 901 } 902 903 /** 904 * @return true if the user's setting for Voice over WiFi is enabled and false if it is not. 905 * 906 * <p>This API requires one of the following: 907 * <ul> 908 * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> 909 * <li>If the caller is the device or profile owner, the caller holds the 910 * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> 911 * <li>The caller has carrier privileges (see 912 * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any 913 * active subscription.</li> 914 * <li>The caller is the default SMS app for the device.</li> 915 * </ul> 916 * <p>The profile owner is an app that owns a managed profile on the device; for more details 917 * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. 918 * Access by profile owners is deprecated and will be removed in a future release. 919 * 920 * @throws IllegalArgumentException if the subscription associated with this operation is not 921 * active (SIM is not inserted, ESIM inactive) or invalid. 922 */ 923 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 924 @RequiresPermission(anyOf = { 925 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 926 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) isVoWiFiSettingEnabled()927 public boolean isVoWiFiSettingEnabled() { 928 ITelephony iTelephony = getITelephony(); 929 if (iTelephony == null) { 930 throw new RuntimeException("Could not find Telephony Service."); 931 } 932 933 try { 934 return iTelephony.isVoWiFiSettingEnabled(mSubId); 935 } catch (ServiceSpecificException e) { 936 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 937 // Rethrow as runtime error to keep API compatible. 938 throw new IllegalArgumentException(e.getMessage()); 939 } else { 940 throw new RuntimeException(e.getMessage()); 941 } 942 } catch (RemoteException e) { 943 throw e.rethrowAsRuntimeException(); 944 } 945 } 946 947 /** 948 * Sets the user's setting for whether or not Voice over WiFi is enabled. 949 * 950 * @throws IllegalArgumentException if the subscription associated with this operation is not 951 * active (SIM is not inserted, ESIM inactive) or invalid. 952 * @param isEnabled true if the user's setting for Voice over WiFi is enabled, false otherwise= 953 * @see #isVoWiFiSettingEnabled() 954 * @hide 955 */ 956 @SystemApi @TestApi 957 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiSettingEnabled(boolean isEnabled)958 public void setVoWiFiSettingEnabled(boolean isEnabled) { 959 ITelephony iTelephony = getITelephony(); 960 if (iTelephony == null) { 961 throw new RuntimeException("Could not find Telephony Service."); 962 } 963 964 try { 965 iTelephony.setVoWiFiSettingEnabled(mSubId, isEnabled); 966 } catch (ServiceSpecificException e) { 967 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 968 // Rethrow as runtime error to keep API compatible. 969 throw new IllegalArgumentException(e.getMessage()); 970 } else { 971 throw new RuntimeException(e.getMessage()); 972 } 973 } catch (RemoteException e) { 974 throw e.rethrowAsRuntimeException(); 975 } 976 } 977 978 /** 979 * Returns the user's voice over WiFi roaming setting associated with the current subscription. 980 * 981 * <p>This API requires one of the following: 982 * <ul> 983 * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> 984 * <li>If the caller is the device or profile owner, the caller holds the 985 * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> 986 * <li>The caller has carrier privileges (see 987 * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any 988 * active subscription.</li> 989 * <li>The caller is the default SMS app for the device.</li> 990 * </ul> 991 * <p>The profile owner is an app that owns a managed profile on the device; for more details 992 * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. 993 * Access by profile owners is deprecated and will be removed in a future release. 994 * 995 * @throws IllegalArgumentException if the subscription associated with this operation is not 996 * active (SIM is not inserted, ESIM inactive) or invalid. 997 * @return true if the user's setting for Voice over WiFi while roaming is enabled, false 998 * if disabled. 999 */ 1000 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 1001 @RequiresPermission(anyOf = { 1002 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1003 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) isVoWiFiRoamingSettingEnabled()1004 public boolean isVoWiFiRoamingSettingEnabled() { 1005 ITelephony iTelephony = getITelephony(); 1006 if (iTelephony == null) { 1007 throw new RuntimeException("Could not find Telephony Service."); 1008 } 1009 1010 try { 1011 return iTelephony.isVoWiFiRoamingSettingEnabled(mSubId); 1012 } catch (ServiceSpecificException e) { 1013 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1014 // Rethrow as runtime error to keep API compatible. 1015 throw new IllegalArgumentException(e.getMessage()); 1016 } else { 1017 throw new RuntimeException(e.getMessage()); 1018 } 1019 } catch (RemoteException e) { 1020 throw e.rethrowAsRuntimeException(); 1021 } 1022 } 1023 1024 /** 1025 * Change the user's setting for Voice over WiFi while roaming. 1026 * 1027 * @param isEnabled true if the user's setting for Voice over WiFi while roaming is enabled, 1028 * false otherwise. 1029 * @throws IllegalArgumentException if the subscription associated with this operation is not 1030 * active (SIM is not inserted, ESIM inactive) or invalid. 1031 * @see #isVoWiFiRoamingSettingEnabled() 1032 * @hide 1033 */ 1034 @SystemApi @TestApi 1035 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiRoamingSettingEnabled(boolean isEnabled)1036 public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) { 1037 ITelephony iTelephony = getITelephony(); 1038 if (iTelephony == null) { 1039 throw new RuntimeException("Could not find Telephony Service."); 1040 } 1041 1042 try { 1043 iTelephony.setVoWiFiRoamingSettingEnabled(mSubId, isEnabled); 1044 } catch (ServiceSpecificException e) { 1045 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1046 // Rethrow as runtime error to keep API compatible. 1047 throw new IllegalArgumentException(e.getMessage()); 1048 } else { 1049 throw new RuntimeException(e.getMessage()); 1050 } 1051 } catch (RemoteException e) { 1052 throw e.rethrowAsRuntimeException(); 1053 } 1054 } 1055 1056 /** 1057 * Overrides the Voice over WiFi capability to true for IMS, but do not persist the setting. 1058 * Typically used during the Voice over WiFi registration process for some carriers. 1059 * 1060 * @param isCapable true if the IMS stack should try to register for IMS over IWLAN, false 1061 * otherwise. 1062 * @param mode the Voice over WiFi mode preference to set, which can be one of the following: 1063 * - {@link #WIFI_MODE_WIFI_ONLY} 1064 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 1065 * - {@link #WIFI_MODE_WIFI_PREFERRED} 1066 * @throws IllegalArgumentException if the subscription associated with this operation is not 1067 * active (SIM is not inserted, ESIM inactive) or invalid. 1068 * @see #setVoWiFiSettingEnabled(boolean) 1069 * @hide 1070 */ 1071 @SystemApi @TestApi 1072 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiNonPersistent(boolean isCapable, int mode)1073 public void setVoWiFiNonPersistent(boolean isCapable, int mode) { 1074 ITelephony iTelephony = getITelephony(); 1075 if (iTelephony == null) { 1076 throw new RuntimeException("Could not find Telephony Service."); 1077 } 1078 1079 try { 1080 iTelephony.setVoWiFiNonPersistent(mSubId, isCapable, mode); 1081 } catch (ServiceSpecificException e) { 1082 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1083 // Rethrow as runtime error to keep API compatible. 1084 throw new IllegalArgumentException(e.getMessage()); 1085 } else { 1086 throw new RuntimeException(e.getMessage()); 1087 } 1088 } catch (RemoteException e) { 1089 throw e.rethrowAsRuntimeException(); 1090 } 1091 } 1092 1093 /** 1094 * Returns the user's voice over WiFi Roaming mode setting associated with the device. 1095 * 1096 * <p>This API requires one of the following: 1097 * <ul> 1098 * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> 1099 * <li>If the caller is the device or profile owner, the caller holds the 1100 * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> 1101 * <li>The caller has carrier privileges (see 1102 * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any 1103 * active subscription.</li> 1104 * <li>The caller is the default SMS app for the device.</li> 1105 * </ul> 1106 * <p>The profile owner is an app that owns a managed profile on the device; for more details 1107 * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. 1108 * Access by profile owners is deprecated and will be removed in a future release. 1109 * 1110 * @throws IllegalArgumentException if the subscription associated with this operation is not 1111 * active (SIM is not inserted, ESIM inactive) or invalid. 1112 * @return The Voice over WiFi Mode preference set by the user, which can be one of the 1113 * following: 1114 * - {@link #WIFI_MODE_WIFI_ONLY} 1115 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 1116 * - {@link #WIFI_MODE_WIFI_PREFERRED} 1117 */ 1118 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 1119 @RequiresPermission(anyOf = { 1120 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1121 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) getVoWiFiModeSetting()1122 public @WiFiCallingMode int getVoWiFiModeSetting() { 1123 ITelephony iTelephony = getITelephony(); 1124 if (iTelephony == null) { 1125 throw new RuntimeException("Could not find Telephony Service."); 1126 } 1127 1128 try { 1129 return iTelephony.getVoWiFiModeSetting(mSubId); 1130 } catch (ServiceSpecificException e) { 1131 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1132 // Rethrow as runtime error to keep API compatible. 1133 throw new IllegalArgumentException(e.getMessage()); 1134 } else { 1135 throw new RuntimeException(e.getMessage()); 1136 } 1137 } catch (RemoteException e) { 1138 throw e.rethrowAsRuntimeException(); 1139 } 1140 } 1141 1142 /** 1143 * Set the user's preference for Voice over WiFi calling mode. 1144 * @param mode The user's preference for the technology to register for IMS over, can be one of 1145 * the following: 1146 * - {@link #WIFI_MODE_WIFI_ONLY} 1147 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 1148 * - {@link #WIFI_MODE_WIFI_PREFERRED} 1149 * @throws IllegalArgumentException if the subscription associated with this operation is not 1150 * active (SIM is not inserted, ESIM inactive) or invalid. 1151 * @see #getVoWiFiModeSetting() 1152 * @hide 1153 */ 1154 @SystemApi @TestApi 1155 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiModeSetting(@iFiCallingMode int mode)1156 public void setVoWiFiModeSetting(@WiFiCallingMode int mode) { 1157 ITelephony iTelephony = getITelephony(); 1158 if (iTelephony == null) { 1159 throw new RuntimeException("Could not find Telephony Service."); 1160 } 1161 1162 try { 1163 iTelephony.setVoWiFiModeSetting(mSubId, mode); 1164 } catch (ServiceSpecificException e) { 1165 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1166 // Rethrow as runtime error to keep API compatible. 1167 throw new IllegalArgumentException(e.getMessage()); 1168 } else { 1169 throw new RuntimeException(e.getMessage()); 1170 } 1171 } catch (RemoteException e) { 1172 throw e.rethrowAsRuntimeException(); 1173 } 1174 } 1175 1176 /** 1177 * Set the user's preference for Voice over WiFi calling mode while the device is roaming on 1178 * another network. 1179 * 1180 * @return The user's preference for the technology to register for IMS over when roaming on 1181 * another network, can be one of the following: 1182 * - {@link #WIFI_MODE_WIFI_ONLY} 1183 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 1184 * - {@link #WIFI_MODE_WIFI_PREFERRED} 1185 * @throws IllegalArgumentException if the subscription associated with this operation is not 1186 * active (SIM is not inserted, ESIM inactive) or invalid. 1187 * @see #setVoWiFiRoamingSettingEnabled(boolean) 1188 * @hide 1189 */ 1190 @SystemApi @TestApi 1191 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getVoWiFiRoamingModeSetting()1192 public @WiFiCallingMode int getVoWiFiRoamingModeSetting() { 1193 ITelephony iTelephony = getITelephony(); 1194 if (iTelephony == null) { 1195 throw new RuntimeException("Could not find Telephony Service."); 1196 } 1197 1198 try { 1199 return iTelephony.getVoWiFiRoamingModeSetting(mSubId); 1200 } catch (ServiceSpecificException e) { 1201 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1202 // Rethrow as runtime error to keep API compatible. 1203 throw new IllegalArgumentException(e.getMessage()); 1204 } else { 1205 throw new RuntimeException(e.getMessage()); 1206 } 1207 } catch (RemoteException e) { 1208 throw e.rethrowAsRuntimeException(); 1209 } 1210 } 1211 1212 /** 1213 * Set the user's preference for Voice over WiFi mode while the device is roaming on another 1214 * network. 1215 * 1216 * @param mode The user's preference for the technology to register for IMS over when roaming on 1217 * another network, can be one of the following: 1218 * - {@link #WIFI_MODE_WIFI_ONLY} 1219 * - {@link #WIFI_MODE_CELLULAR_PREFERRED} 1220 * - {@link #WIFI_MODE_WIFI_PREFERRED} 1221 * @throws IllegalArgumentException if the subscription associated with this operation is not 1222 * active (SIM is not inserted, ESIM inactive) or invalid. 1223 * @see #getVoWiFiRoamingModeSetting() 1224 * @hide 1225 */ 1226 @SystemApi @TestApi 1227 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setVoWiFiRoamingModeSetting(@iFiCallingMode int mode)1228 public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) { 1229 ITelephony iTelephony = getITelephony(); 1230 if (iTelephony == null) { 1231 throw new RuntimeException("Could not find Telephony Service."); 1232 } 1233 1234 try { 1235 iTelephony.setVoWiFiRoamingModeSetting(mSubId, mode); 1236 } catch (ServiceSpecificException e) { 1237 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1238 // Rethrow as runtime error to keep API compatible. 1239 throw new IllegalArgumentException(e.getMessage()); 1240 } else { 1241 throw new RuntimeException(e.getMessage()); 1242 } 1243 } catch (RemoteException e) { 1244 throw e.rethrowAsRuntimeException(); 1245 } 1246 } 1247 1248 /** 1249 * Sets the capability of RTT for IMS calls placed on this subscription. 1250 * 1251 * Note: This does not affect the value of 1252 * {@link android.provider.Settings.Secure#RTT_CALLING_MODE}, which is the global user setting 1253 * for RTT. That value is enabled/disabled separately by the user through the Accessibility 1254 * settings. 1255 * @throws IllegalArgumentException if the subscription associated with this operation is not 1256 * active (SIM is not inserted, ESIM inactive) or invalid. 1257 * @param isEnabled if true RTT should be enabled during calls made on this subscription. 1258 * @hide 1259 */ 1260 @SystemApi @TestApi 1261 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setRttCapabilitySetting(boolean isEnabled)1262 public void setRttCapabilitySetting(boolean isEnabled) { 1263 ITelephony iTelephony = getITelephony(); 1264 if (iTelephony == null) { 1265 throw new RuntimeException("Could not find Telephony Service."); 1266 } 1267 1268 try { 1269 iTelephony.setRttCapabilitySetting(mSubId, isEnabled); 1270 } catch (ServiceSpecificException e) { 1271 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1272 // Rethrow as runtime error to keep API compatible. 1273 throw new IllegalArgumentException(e.getMessage()); 1274 } else { 1275 throw new RuntimeException(e.getMessage()); 1276 } 1277 } catch (RemoteException e) { 1278 throw e.rethrowAsRuntimeException(); 1279 } 1280 } 1281 1282 /** 1283 * @return true if TTY over VoLTE is supported 1284 * 1285 * <p>This API requires one of the following: 1286 * <ul> 1287 * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> 1288 * <li>If the caller is the device or profile owner, the caller holds the 1289 * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> 1290 * <li>The caller has carrier privileges (see 1291 * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any 1292 * active subscription.</li> 1293 * <li>The caller is the default SMS app for the device.</li> 1294 * </ul> 1295 * <p>The profile owner is an app that owns a managed profile on the device; for more details 1296 * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. 1297 * Access by profile owners is deprecated and will be removed in a future release. 1298 * 1299 * @throws IllegalArgumentException if the subscription associated with this operation is not 1300 * active (SIM is not inserted, ESIM inactive) or invalid. 1301 * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL 1302 */ 1303 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). 1304 @RequiresPermission(anyOf = { 1305 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1306 android.Manifest.permission.READ_PRECISE_PHONE_STATE}) isTtyOverVolteEnabled()1307 public boolean isTtyOverVolteEnabled() { 1308 ITelephony iTelephony = getITelephony(); 1309 if (iTelephony == null) { 1310 throw new RuntimeException("Could not find Telephony Service."); 1311 } 1312 1313 try { 1314 return iTelephony.isTtyOverVolteEnabled(mSubId); 1315 } catch (ServiceSpecificException e) { 1316 if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { 1317 // Rethrow as runtime error to keep API compatible. 1318 throw new IllegalArgumentException(e.getMessage()); 1319 } else { 1320 throw new RuntimeException(e.getMessage()); 1321 } 1322 } catch (RemoteException e) { 1323 throw e.rethrowAsRuntimeException(); 1324 } 1325 } 1326 1327 /** 1328 * Get the status of the MmTel Feature registered on this subscription. 1329 * @param executor The executor that will be used to call the callback. 1330 * @param callback A callback containing an Integer describing the current state of the 1331 * MmTel feature, Which will be one of the following: 1332 * {@link ImsFeature#STATE_UNAVAILABLE}, 1333 * {@link ImsFeature#STATE_INITIALIZING}, 1334 * {@link ImsFeature#STATE_READY}. Will be called using the executor 1335 * specified when the service state has been retrieved from the IMS service. 1336 * @throws ImsException if the IMS service associated with this subscription is not available or 1337 * the IMS service is not available. 1338 * @hide 1339 */ 1340 @SystemApi @TestApi 1341 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getFeatureState(@onNull @allbackExecutor Executor executor, @NonNull @ImsFeature.ImsState Consumer<Integer> callback)1342 public void getFeatureState(@NonNull @CallbackExecutor Executor executor, 1343 @NonNull @ImsFeature.ImsState Consumer<Integer> callback) throws ImsException { 1344 if (executor == null) { 1345 throw new IllegalArgumentException("Must include a non-null Executor."); 1346 } 1347 if (callback == null) { 1348 throw new IllegalArgumentException("Must include a non-null Consumer."); 1349 } 1350 1351 ITelephony iTelephony = getITelephony(); 1352 if (iTelephony == null) { 1353 throw new ImsException("Could not find Telephony Service.", 1354 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 1355 } 1356 1357 try { 1358 iTelephony.getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() { 1359 @Override 1360 public void accept(int result) { 1361 executor.execute(() -> callback.accept(result)); 1362 } 1363 }); 1364 } catch (ServiceSpecificException sse) { 1365 throw new ImsException(sse.getMessage(), sse.errorCode); 1366 } catch (RemoteException e) { 1367 e.rethrowAsRuntimeException(); 1368 } 1369 } 1370 getITelephony()1371 private static ITelephony getITelephony() { 1372 ITelephony binder = ITelephony.Stub.asInterface( 1373 TelephonyFrameworkInitializer 1374 .getTelephonyServiceManager() 1375 .getTelephonyServiceRegisterer() 1376 .get()); 1377 return binder; 1378 } 1379 } 1380