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