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