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