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 import android.Manifest; 20 import android.annotation.CallbackExecutor; 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.RequiresPermission; 24 import android.annotation.SystemApi; 25 import android.content.Context; 26 import android.net.Uri; 27 import android.os.Binder; 28 import android.os.IBinder; 29 import android.os.RemoteException; 30 import android.os.ServiceSpecificException; 31 import android.telephony.TelephonyFrameworkInitializer; 32 import android.telephony.ims.aidl.IImsRcsController; 33 import android.telephony.ims.aidl.IRcsUceControllerCallback; 34 import android.telephony.ims.aidl.IRcsUcePublishStateCallback; 35 import android.util.Log; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 import java.util.ArrayList; 40 import java.util.Collection; 41 import java.util.HashMap; 42 import java.util.List; 43 import java.util.Map; 44 import java.util.concurrent.Executor; 45 46 /** 47 * Manages RCS User Capability Exchange for the subscription specified. 48 * 49 * @see ImsRcsManager#getUceAdapter() for information on creating an instance of this class. 50 */ 51 public class RcsUceAdapter { 52 private static final String TAG = "RcsUceAdapter"; 53 54 /** 55 * This carrier supports User Capability Exchange as, defined by the framework using 56 * SIP OPTIONS. If set, the RcsFeature should support capability exchange. If not set, this 57 * RcsFeature should not publish capabilities or service capability requests. 58 * @deprecated Use {@link ImsRcsManager#CAPABILITY_TYPE_OPTIONS_UCE} instead. 59 * @hide 60 */ 61 @Deprecated 62 public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0; 63 64 /** 65 * This carrier supports User Capability Exchange as, defined by the framework using a 66 * presence server. If set, the RcsFeature should support capability exchange. If not set, this 67 * RcsFeature should not publish capabilities or service capability requests. 68 * @deprecated Use {@link ImsRcsManager#CAPABILITY_TYPE_PRESENCE_UCE} instead. 69 * @hide 70 */ 71 @Deprecated 72 @SystemApi 73 public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; 74 75 /** 76 * @deprecated Use {@link ImsRcsManager.RcsImsCapabilityFlag} instead. 77 * @hide 78 */ 79 @Deprecated 80 @Retention(RetentionPolicy.SOURCE) 81 @IntDef(prefix = "CAPABILITY_TYPE_", value = { 82 CAPABILITY_TYPE_OPTIONS_UCE, 83 CAPABILITY_TYPE_PRESENCE_UCE 84 }) 85 public @interface RcsImsCapabilityFlag {} 86 87 /** 88 * An unknown error has caused the request to fail. 89 * @hide 90 */ 91 @SystemApi 92 public static final int ERROR_GENERIC_FAILURE = 1; 93 94 /** 95 * The carrier network does not have UCE support enabled for this subscriber. 96 * @hide 97 */ 98 @SystemApi 99 public static final int ERROR_NOT_ENABLED = 2; 100 101 /** 102 * The data network that the device is connected to does not support UCE currently (e.g. it is 103 * 1x only currently). 104 * @hide 105 */ 106 @SystemApi 107 public static final int ERROR_NOT_AVAILABLE = 3; 108 109 /** 110 * The network has responded with SIP 403 error and a reason "User not registered." 111 * @hide 112 */ 113 @SystemApi 114 public static final int ERROR_NOT_REGISTERED = 4; 115 116 /** 117 * The network has responded to this request with a SIP 403 error and reason "not authorized for 118 * presence" for this subscriber. 119 * @hide 120 */ 121 @SystemApi 122 public static final int ERROR_NOT_AUTHORIZED = 5; 123 124 /** 125 * The network has responded to this request with a SIP 403 error and no reason. 126 * @hide 127 */ 128 @SystemApi 129 public static final int ERROR_FORBIDDEN = 6; 130 131 /** 132 * The contact URI requested is not provisioned for voice or it is not known as an IMS 133 * subscriber to the carrier network. 134 * @hide 135 */ 136 @SystemApi 137 public static final int ERROR_NOT_FOUND = 7; 138 139 /** 140 * The capabilities request contained too many URIs for the carrier network to handle. Retry 141 * with a lower number of contact numbers. The number varies per carrier. 142 * @hide 143 */ 144 @SystemApi 145 // TODO: Try to integrate this into the API so that the service will split based on carrier. 146 public static final int ERROR_REQUEST_TOO_LARGE = 8; 147 148 /** 149 * The network did not respond to the capabilities request before the request timed out. 150 * @hide 151 */ 152 @SystemApi 153 public static final int ERROR_REQUEST_TIMEOUT = 9; 154 155 /** 156 * The request failed due to the service having insufficient memory. 157 * @hide 158 */ 159 @SystemApi 160 public static final int ERROR_INSUFFICIENT_MEMORY = 10; 161 162 /** 163 * The network was lost while trying to complete the request. 164 * @hide 165 */ 166 @SystemApi 167 public static final int ERROR_LOST_NETWORK = 11; 168 169 /** 170 * The network is temporarily unavailable or busy. Retries should only be done after the retry 171 * time returned in {@link CapabilitiesCallback#onError} has elapsed. 172 * @hide 173 */ 174 @SystemApi 175 public static final int ERROR_SERVER_UNAVAILABLE = 12; 176 177 /**@hide*/ 178 @Retention(RetentionPolicy.SOURCE) 179 @IntDef(prefix = "ERROR_", value = { 180 ERROR_GENERIC_FAILURE, 181 ERROR_NOT_ENABLED, 182 ERROR_NOT_AVAILABLE, 183 ERROR_NOT_REGISTERED, 184 ERROR_NOT_AUTHORIZED, 185 ERROR_FORBIDDEN, 186 ERROR_NOT_FOUND, 187 ERROR_REQUEST_TOO_LARGE, 188 ERROR_REQUEST_TIMEOUT, 189 ERROR_INSUFFICIENT_MEMORY, 190 ERROR_LOST_NETWORK, 191 ERROR_SERVER_UNAVAILABLE 192 }) 193 public @interface ErrorCode {} 194 195 /** 196 * A capability update has been requested but the reason is unknown. 197 * @hide 198 */ 199 @SystemApi 200 public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 0; 201 202 /** 203 * A capability update has been requested due to the Entity Tag (ETag) expiring. 204 * @hide 205 */ 206 @SystemApi 207 public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 1; 208 209 /** 210 * A capability update has been requested due to moving to LTE with VoPS disabled. 211 * @hide 212 */ 213 @SystemApi 214 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 2; 215 216 /** 217 * A capability update has been requested due to moving to LTE with VoPS enabled. 218 * @hide 219 */ 220 @SystemApi 221 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 3; 222 223 /** 224 * A capability update has been requested due to moving to eHRPD. 225 * @hide 226 */ 227 @SystemApi 228 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 4; 229 230 /** 231 * A capability update has been requested due to moving to HSPA+. 232 * @hide 233 */ 234 @SystemApi 235 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 5; 236 237 /** 238 * A capability update has been requested due to moving to 3G. 239 * @hide 240 */ 241 @SystemApi 242 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 6; 243 244 /** 245 * A capability update has been requested due to moving to 2G. 246 * @hide 247 */ 248 @SystemApi 249 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 7; 250 251 /** 252 * A capability update has been requested due to moving to WLAN 253 * @hide 254 */ 255 @SystemApi 256 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 8; 257 258 /** 259 * A capability update has been requested due to moving to IWLAN 260 * @hide 261 */ 262 @SystemApi 263 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 9; 264 265 /** 266 * A capability update has been requested due to moving to 5G NR with VoPS disabled. 267 * @hide 268 */ 269 @SystemApi 270 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; 271 272 /** 273 * A capability update has been requested due to moving to 5G NR with VoPS enabled. 274 * @hide 275 */ 276 @SystemApi 277 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; 278 279 /** 280 * A capability update has been requested due to IMS being registered over INTERNET PDN. 281 * @hide 282 */ 283 @SystemApi 284 public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN = 12; 285 286 /**@hide*/ 287 @Retention(RetentionPolicy.SOURCE) 288 @IntDef(prefix = "ERROR_", value = { 289 CAPABILITY_UPDATE_TRIGGER_UNKNOWN, 290 CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED, 291 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED, 292 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED, 293 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD, 294 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS, 295 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G, 296 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G, 297 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN, 298 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN, 299 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED, 300 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED, 301 CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN 302 }) 303 public @interface StackPublishTriggerType {} 304 305 /** 306 * The last publish has resulted in a "200 OK" response or the device is using SIP OPTIONS for 307 * UCE. 308 * @hide 309 */ 310 @SystemApi 311 public static final int PUBLISH_STATE_OK = 1; 312 313 /** 314 * The hasn't published its capabilities since boot or hasn't gotten any publish response yet. 315 * @hide 316 */ 317 @SystemApi 318 public static final int PUBLISH_STATE_NOT_PUBLISHED = 2; 319 320 /** 321 * The device has tried to publish its capabilities, which has resulted in an error. This error 322 * is related to the fact that the device is not provisioned for voice. 323 * @hide 324 */ 325 @SystemApi 326 public static final int PUBLISH_STATE_VOICE_PROVISION_ERROR = 3; 327 328 /** 329 * The device has tried to publish its capabilities, which has resulted in an error. This error 330 * is related to the fact that the device is not RCS or UCE provisioned. 331 * @hide 332 */ 333 @SystemApi 334 public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4; 335 336 /** 337 * The last publish resulted in a "408 Request Timeout" response. 338 * @hide 339 */ 340 @SystemApi 341 public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5; 342 343 /** 344 * The last publish resulted in another unknown error, such as SIP 503 - "Service Unavailable" 345 * or SIP 423 - "Interval too short". 346 * <p> 347 * Device shall retry with exponential back-off. 348 * @hide 349 */ 350 @SystemApi 351 public static final int PUBLISH_STATE_OTHER_ERROR = 6; 352 353 /** 354 * The device is currently trying to publish its capabilities to the network. 355 * @hide 356 */ 357 @SystemApi 358 public static final int PUBLISH_STATE_PUBLISHING = 7; 359 360 361 /**@hide*/ 362 @Retention(RetentionPolicy.SOURCE) 363 @IntDef(prefix = "PUBLISH_STATE_", value = { 364 PUBLISH_STATE_OK, 365 PUBLISH_STATE_NOT_PUBLISHED, 366 PUBLISH_STATE_VOICE_PROVISION_ERROR, 367 PUBLISH_STATE_RCS_PROVISION_ERROR, 368 PUBLISH_STATE_REQUEST_TIMEOUT, 369 PUBLISH_STATE_OTHER_ERROR, 370 PUBLISH_STATE_PUBLISHING 371 }) 372 public @interface PublishState {} 373 374 /** 375 * An application can use {@link #addOnPublishStateChangedListener} to register a 376 * {@link OnPublishStateChangedListener ), which will notify the user when the publish state to 377 * the network changes. 378 * @hide 379 */ 380 @SystemApi 381 public interface OnPublishStateChangedListener { 382 /** 383 * Notifies the callback when the publish state has changed. 384 * @param publishState The latest update to the publish state. 385 */ onPublishStateChange(@ublishState int publishState)386 void onPublishStateChange(@PublishState int publishState); 387 } 388 389 /** 390 * An application can use {@link #addOnPublishStateChangedListener} to register a 391 * {@link OnPublishStateChangedListener ), which will notify the user when the publish state to 392 * the network changes. 393 * @hide 394 */ 395 public static class PublishStateCallbackAdapter { 396 397 private static class PublishStateBinder extends IRcsUcePublishStateCallback.Stub { 398 private final OnPublishStateChangedListener mPublishStateChangeListener; 399 private final Executor mExecutor; 400 PublishStateBinder(Executor executor, OnPublishStateChangedListener listener)401 PublishStateBinder(Executor executor, OnPublishStateChangedListener listener) { 402 mExecutor = executor; 403 mPublishStateChangeListener = listener; 404 } 405 406 @Override onPublishStateChanged(int publishState)407 public void onPublishStateChanged(int publishState) { 408 if (mPublishStateChangeListener == null) return; 409 410 final long callingIdentity = Binder.clearCallingIdentity(); 411 try { 412 mExecutor.execute(() -> 413 mPublishStateChangeListener.onPublishStateChange(publishState)); 414 } finally { 415 restoreCallingIdentity(callingIdentity); 416 } 417 } 418 } 419 420 private final PublishStateBinder mBinder; 421 PublishStateCallbackAdapter(@onNull Executor executor, @NonNull OnPublishStateChangedListener listener)422 public PublishStateCallbackAdapter(@NonNull Executor executor, 423 @NonNull OnPublishStateChangedListener listener) { 424 mBinder = new PublishStateBinder(executor, listener); 425 } 426 427 /**@hide*/ getBinder()428 public final IRcsUcePublishStateCallback getBinder() { 429 return mBinder; 430 } 431 } 432 433 /** 434 * A callback for the response to a UCE request. The method 435 * {@link CapabilitiesCallback#onCapabilitiesReceived} will be called zero or more times as the 436 * capabilities are received for each requested contact. 437 * <p> 438 * This request will take a varying amount of time depending on if the contacts requested are 439 * cached or if it requires a network query. The timeout time of these requests can vary 440 * depending on the network, however in poor cases it could take up to a minute for a request 441 * to timeout. In that time only a subset of capabilities may have been retrieved. 442 * <p> 443 * After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has 444 * been called, the reference to this callback will be discarded on the service side. 445 * @see #requestCapabilities(Collection, Executor, CapabilitiesCallback) 446 * @hide 447 */ 448 @SystemApi 449 public interface CapabilitiesCallback { 450 451 /** 452 * Notify this application that the pending capability request has returned successfully 453 * for one or more of the requested contacts. 454 * @param contactCapabilities List of capabilities associated with each contact requested. 455 */ onCapabilitiesReceived(@onNull List<RcsContactUceCapability> contactCapabilities)456 void onCapabilitiesReceived(@NonNull List<RcsContactUceCapability> contactCapabilities); 457 458 /** 459 * The pending request has completed successfully due to all requested contacts information 460 * being delivered. The callback {@link #onCapabilitiesReceived(List)} 461 * for each contacts is required to be called before {@link #onComplete} is called. 462 */ onComplete()463 void onComplete(); 464 465 /** 466 * The pending request has resulted in an error and may need to be retried, depending on the 467 * error code. 468 * @param errorCode The reason for the framework being unable to process the request. 469 * @param retryIntervalMillis The time in milliseconds the requesting application should 470 * wait before retrying, if non-zero. 471 */ onError(@rrorCode int errorCode, long retryIntervalMillis)472 void onError(@ErrorCode int errorCode, long retryIntervalMillis); 473 } 474 475 private final Context mContext; 476 private final int mSubId; 477 private final Map<OnPublishStateChangedListener, PublishStateCallbackAdapter> 478 mPublishStateCallbacks; 479 480 /** 481 * Not to be instantiated directly, use {@link ImsRcsManager#getUceAdapter()} to instantiate 482 * this manager class. 483 * @hide 484 */ RcsUceAdapter(Context context, int subId)485 RcsUceAdapter(Context context, int subId) { 486 mContext = context; 487 mSubId = subId; 488 mPublishStateCallbacks = new HashMap<>(); 489 } 490 491 /** 492 * Request the RCS capabilities for one or more contacts using RCS User Capability Exchange. 493 * <p> 494 * This API will first check a local cache for the requested numbers and return the cached 495 * RCS capabilities of each number if the cache exists and is not stale. If the cache for a 496 * number is stale or there is no cached information about the requested number, the device will 497 * then perform a query to the carrier's network to request the RCS capabilities of the 498 * requested numbers. 499 * <p> 500 * Depending on the number of requests being sent, this API may throttled internally as the 501 * operations are queued to be executed by the carrier's network. 502 * <p> 503 * Be sure to check the availability of this feature using 504 * {@link ImsRcsManager#isAvailable(int, int)} and ensuring 505 * {@link 506 * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or 507 * {@link 508 * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is 509 * enabled or else this operation will fail with {@link #ERROR_NOT_AVAILABLE} or 510 * {@link #ERROR_NOT_ENABLED}. 511 * 512 * @param contactNumbers A list of numbers that the capabilities are being requested for. 513 * @param executor The executor that will be used when the request is completed and the 514 * {@link CapabilitiesCallback} is called. 515 * @param c A one-time callback for when the request for capabilities completes or there is an 516 * error processing the request. 517 * @throws ImsException if the subscription associated with this instance of 518 * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not 519 * available. This can happen if the ImsService has crashed, for example, or if the subscription 520 * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. 521 * @hide 522 */ 523 @SystemApi 524 @RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, 525 Manifest.permission.READ_CONTACTS}) requestCapabilities(@onNull Collection<Uri> contactNumbers, @NonNull @CallbackExecutor Executor executor, @NonNull CapabilitiesCallback c)526 public void requestCapabilities(@NonNull Collection<Uri> contactNumbers, 527 @NonNull @CallbackExecutor Executor executor, 528 @NonNull CapabilitiesCallback c) throws ImsException { 529 if (c == null) { 530 throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback."); 531 } 532 if (executor == null) { 533 throw new IllegalArgumentException("Must include a non-null Executor."); 534 } 535 if (contactNumbers == null) { 536 throw new IllegalArgumentException("Must include non-null contact number list."); 537 } 538 539 IImsRcsController imsRcsController = getIImsRcsController(); 540 if (imsRcsController == null) { 541 Log.e(TAG, "requestCapabilities: IImsRcsController is null"); 542 throw new ImsException("Can not find remote IMS service", 543 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 544 } 545 546 IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { 547 @Override 548 public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { 549 final long callingIdentity = Binder.clearCallingIdentity(); 550 try { 551 executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities)); 552 } finally { 553 restoreCallingIdentity(callingIdentity); 554 } 555 } 556 @Override 557 public void onComplete() { 558 final long callingIdentity = Binder.clearCallingIdentity(); 559 try { 560 executor.execute(() -> c.onComplete()); 561 } finally { 562 restoreCallingIdentity(callingIdentity); 563 } 564 } 565 @Override 566 public void onError(int errorCode, long retryAfterMilliseconds) { 567 final long callingIdentity = Binder.clearCallingIdentity(); 568 try { 569 executor.execute(() -> c.onError(errorCode, retryAfterMilliseconds)); 570 } finally { 571 restoreCallingIdentity(callingIdentity); 572 } 573 } 574 }; 575 576 try { 577 imsRcsController.requestCapabilities(mSubId, mContext.getOpPackageName(), 578 mContext.getAttributionTag(), new ArrayList(contactNumbers), internalCallback); 579 } catch (ServiceSpecificException e) { 580 throw new ImsException(e.toString(), e.errorCode); 581 } catch (RemoteException e) { 582 Log.e(TAG, "Error calling IImsRcsController#requestCapabilities", e); 583 throw new ImsException("Remote IMS Service is not available", 584 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 585 } 586 } 587 588 /** 589 * Request the RCS capabilities for a phone number using User Capability Exchange. 590 * <p> 591 * Unlike {@link #requestCapabilities(Collection, Executor, CapabilitiesCallback)}, which caches 592 * the result received from the network for a certain amount of time and uses that cached result 593 * for subsequent requests for RCS capabilities of the same phone number, this API will always 594 * request the RCS capabilities of a contact from the carrier's network. 595 * <p> 596 * Depending on the number of requests, this API may throttled internally as the operations are 597 * queued to be executed by the carrier's network. 598 * <p> 599 * Be sure to check the availability of this feature using 600 * {@link ImsRcsManager#isAvailable(int, int)} and ensuring 601 * {@link 602 * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or 603 * {@link 604 * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is 605 * enabled or else this operation will fail with 606 * {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}. 607 * 608 * @param contactNumber The contact of the capabilities is being requested for. 609 * @param executor The executor that will be used when the request is completed and the 610 * {@link CapabilitiesCallback} is called. 611 * @param c A one-time callback for when the request for capabilities completes or there is 612 * an error processing the request. 613 * @throws ImsException if the subscription associated with this instance of 614 * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not 615 * available. This can happen if the ImsService has crashed, for example, or if the subscription 616 * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. 617 * @hide 618 */ 619 @SystemApi 620 @RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, 621 Manifest.permission.READ_CONTACTS}) requestAvailability(@onNull Uri contactNumber, @NonNull @CallbackExecutor Executor executor, @NonNull CapabilitiesCallback c)622 public void requestAvailability(@NonNull Uri contactNumber, 623 @NonNull @CallbackExecutor Executor executor, 624 @NonNull CapabilitiesCallback c) throws ImsException { 625 if (executor == null) { 626 throw new IllegalArgumentException("Must include a non-null Executor."); 627 } 628 if (contactNumber == null) { 629 throw new IllegalArgumentException("Must include non-null contact number."); 630 } 631 if (c == null) { 632 throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback."); 633 } 634 635 IImsRcsController imsRcsController = getIImsRcsController(); 636 if (imsRcsController == null) { 637 Log.e(TAG, "requestAvailability: IImsRcsController is null"); 638 throw new ImsException("Cannot find remote IMS service", 639 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 640 } 641 642 IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { 643 @Override 644 public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { 645 final long callingIdentity = Binder.clearCallingIdentity(); 646 try { 647 executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities)); 648 } finally { 649 restoreCallingIdentity(callingIdentity); 650 } 651 } 652 @Override 653 public void onComplete() { 654 final long callingIdentity = Binder.clearCallingIdentity(); 655 try { 656 executor.execute(() -> c.onComplete()); 657 } finally { 658 restoreCallingIdentity(callingIdentity); 659 } 660 } 661 @Override 662 public void onError(int errorCode, long retryAfterMilliseconds) { 663 final long callingIdentity = Binder.clearCallingIdentity(); 664 try { 665 executor.execute(() -> c.onError(errorCode, retryAfterMilliseconds)); 666 } finally { 667 restoreCallingIdentity(callingIdentity); 668 } 669 } 670 }; 671 672 try { 673 imsRcsController.requestAvailability(mSubId, mContext.getOpPackageName(), 674 mContext.getAttributionTag(), contactNumber, internalCallback); 675 } catch (ServiceSpecificException e) { 676 throw new ImsException(e.toString(), e.errorCode); 677 } catch (RemoteException e) { 678 Log.e(TAG, "Error calling IImsRcsController#requestAvailability", e); 679 throw new ImsException("Remote IMS Service is not available", 680 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 681 } 682 } 683 684 /** 685 * Gets the last publish result from the UCE service if the device is using an RCS presence 686 * server. 687 * @return The last publish result from the UCE service. If the device is using SIP OPTIONS, 688 * this method will return {@link #PUBLISH_STATE_OK} as well. 689 * @throws ImsException if the subscription associated with this instance of 690 * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not 691 * available. This can happen if the ImsService has crashed, for example, or if the subscription 692 * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. 693 * @hide 694 */ 695 @SystemApi 696 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getUcePublishState()697 public @PublishState int getUcePublishState() throws ImsException { 698 IImsRcsController imsRcsController = getIImsRcsController(); 699 if (imsRcsController == null) { 700 Log.e(TAG, "getUcePublishState: IImsRcsController is null"); 701 throw new ImsException("Can not find remote IMS service", 702 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 703 } 704 705 try { 706 return imsRcsController.getUcePublishState(mSubId); 707 } catch (ServiceSpecificException e) { 708 throw new ImsException(e.getMessage(), e.errorCode); 709 } catch (RemoteException e) { 710 Log.e(TAG, "Error calling IImsRcsController#getUcePublishState", e); 711 throw new ImsException("Remote IMS Service is not available", 712 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 713 } 714 } 715 716 /** 717 * Registers a {@link OnPublishStateChangedListener} with the system, which will provide publish 718 * state updates for the subscription specified in {@link ImsManager@getRcsManager(subid)}. 719 * <p> 720 * Use {@link android.telephony.SubscriptionManager.OnSubscriptionsChangedListener} to listen 721 * to subscription 722 * changed events and call 723 * {@link #removeOnPublishStateChangedListener(OnPublishStateChangedListener)} to clean up. 724 * <p> 725 * The registered {@link OnPublishStateChangedListener} will also receive a callback when it is 726 * registered with the current publish state. 727 * 728 * @param executor The executor the listener callback events should be run on. 729 * @param listener The {@link OnPublishStateChangedListener} to be added. 730 * @throws ImsException if the subscription associated with this callback is valid, but 731 * the {@link ImsService} associated with the subscription is not available. This can happen if 732 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed 733 * reason. 734 * @hide 735 */ 736 @SystemApi 737 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) addOnPublishStateChangedListener(@onNull @allbackExecutor Executor executor, @NonNull OnPublishStateChangedListener listener)738 public void addOnPublishStateChangedListener(@NonNull @CallbackExecutor Executor executor, 739 @NonNull OnPublishStateChangedListener listener) throws ImsException { 740 if (executor == null) { 741 throw new IllegalArgumentException("Must include a non-null Executor."); 742 } 743 if (listener == null) { 744 throw new IllegalArgumentException( 745 "Must include a non-null OnPublishStateChangedListener."); 746 } 747 748 IImsRcsController imsRcsController = getIImsRcsController(); 749 if (imsRcsController == null) { 750 Log.e(TAG, "addOnPublishStateChangedListener : IImsRcsController is null"); 751 throw new ImsException("Cannot find remote IMS service", 752 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 753 } 754 755 PublishStateCallbackAdapter stateCallback = addPublishStateCallback(executor, listener); 756 try { 757 imsRcsController.registerUcePublishStateCallback(mSubId, stateCallback.getBinder()); 758 } catch (ServiceSpecificException e) { 759 throw new ImsException(e.getMessage(), e.errorCode); 760 } catch (RemoteException e) { 761 Log.e(TAG, "Error calling IImsRcsController#registerUcePublishStateCallback", e); 762 throw new ImsException("Remote IMS Service is not available", 763 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 764 } 765 } 766 767 /** 768 * Removes an existing {@link OnPublishStateChangedListener}. 769 * <p> 770 * When the subscription associated with this callback is removed 771 * (SIM removed, ESIM swap,etc...), this callback will automatically be removed. If this method 772 * is called for an inactive subscription, it will result in a no-op. 773 * 774 * @param listener The callback to be unregistered. 775 * @throws ImsException if the subscription associated with this callback is valid, but 776 * the {@link ImsService} associated with the subscription is not available. This can happen if 777 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed 778 * reason. 779 * @hide 780 */ 781 @SystemApi 782 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) removeOnPublishStateChangedListener( @onNull OnPublishStateChangedListener listener)783 public void removeOnPublishStateChangedListener( 784 @NonNull OnPublishStateChangedListener listener) throws ImsException { 785 if (listener == null) { 786 throw new IllegalArgumentException( 787 "Must include a non-null OnPublishStateChangedListener."); 788 } 789 IImsRcsController imsRcsController = getIImsRcsController(); 790 if (imsRcsController == null) { 791 Log.e(TAG, "removeOnPublishStateChangedListener: IImsRcsController is null"); 792 throw new ImsException("Cannot find remote IMS service", 793 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 794 } 795 796 PublishStateCallbackAdapter callback = removePublishStateCallback(listener); 797 if (callback == null) { 798 return; 799 } 800 801 try { 802 imsRcsController.unregisterUcePublishStateCallback(mSubId, callback.getBinder()); 803 } catch (android.os.ServiceSpecificException e) { 804 throw new ImsException(e.getMessage(), e.errorCode); 805 } catch (RemoteException e) { 806 Log.e(TAG, "Error calling IImsRcsController#unregisterUcePublishStateCallback", e); 807 throw new ImsException("Remote IMS Service is not available", 808 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 809 } 810 } 811 812 /** 813 * The setting for whether or not the user has opted in to the automatic refresh of the RCS 814 * capabilities associated with the contacts in the user's contact address book. By default, 815 * this setting is disabled and must be enabled after the user has seen the opt-in dialog shown 816 * by {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}. 817 * <p> 818 * If this feature is enabled, the device will periodically share the phone numbers of all of 819 * the contacts in the user's address book with the carrier to refresh the RCS capabilities 820 * cache associated with those contacts as the local cache becomes stale. 821 * <p> 822 * This setting will only enable this feature if 823 * {@link android.telephony.CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is 824 * also enabled. 825 * <p> 826 * Note: This setting does not affect whether or not the device publishes its service 827 * capabilities if the subscription supports presence publication. 828 * 829 * @return true if the user has opted in for automatic refresh of the RCS capabilities of their 830 * contacts, false otherwise. 831 * @throws ImsException if the subscription associated with this instance of 832 * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not 833 * available. This can happen if the ImsService has crashed, for example, or if the subscription 834 * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. 835 */ 836 @RequiresPermission(Manifest.permission.READ_PHONE_STATE) isUceSettingEnabled()837 public boolean isUceSettingEnabled() throws ImsException { 838 IImsRcsController imsRcsController = getIImsRcsController(); 839 if (imsRcsController == null) { 840 Log.e(TAG, "isUceSettingEnabled: IImsRcsController is null"); 841 throw new ImsException("Can not find remote IMS service", 842 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 843 } 844 try { 845 // Telephony.SimInfo#IMS_RCS_UCE_ENABLED can also be used to listen to changes to this. 846 return imsRcsController.isUceSettingEnabled(mSubId, mContext.getOpPackageName(), 847 mContext.getAttributionTag()); 848 } catch (RemoteException e) { 849 Log.e(TAG, "Error calling IImsRcsController#isUceSettingEnabled", e); 850 throw new ImsException("Remote IMS Service is not available", 851 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 852 } 853 } 854 855 /** 856 * Change the user’s setting for whether or not the user has opted in to the automatic 857 * refresh of the RCS capabilities associated with the contacts in the user's contact address 858 * book. By default, this setting is disabled and must be enabled using this method after the 859 * user has seen the opt-in dialog shown by 860 * {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}. 861 * <p> 862 * If an application wishes to request that the user enable this feature, they must launch an 863 * Activity using the Intent {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}, 864 * which will ask the user if they wish to enable this feature. This setting must only be 865 * enabled after the user has opted-in to this feature. 866 * <p> 867 * This must not affect the 868 * {@link #requestCapabilities(Collection, Executor, CapabilitiesCallback)} or 869 * {@link #requestAvailability(Uri, Executor, CapabilitiesCallback)} API, 870 * as those APIs are still required for per-contact RCS capability queries of phone numbers 871 * required for operations such as placing a Video Telephony call or starting an RCS chat 872 * session. 873 * <p> 874 * This setting will only enable this feature if 875 * {@link android.telephony.CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is 876 * also enabled. 877 * <p> 878 * Note: This setting does not affect whether or not the device publishes its service 879 * capabilities if the subscription supports presence publication. 880 * 881 * @param isEnabled true if the user has opted in for automatic refresh of the RCS capabilities 882 * of their contacts, or false if they have chosen to opt-out. By default this 883 * setting is disabled. 884 * @throws ImsException if the subscription associated with this instance of 885 * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not 886 * available. This can happen if the ImsService has crashed, for example, or if the subscription 887 * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. 888 * @hide 889 */ 890 @SystemApi 891 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setUceSettingEnabled(boolean isEnabled)892 public void setUceSettingEnabled(boolean isEnabled) throws ImsException { 893 IImsRcsController imsRcsController = getIImsRcsController(); 894 if (imsRcsController == null) { 895 Log.e(TAG, "setUceSettingEnabled: IImsRcsController is null"); 896 throw new ImsException("Can not find remote IMS service", 897 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 898 } 899 900 try { 901 imsRcsController.setUceSettingEnabled(mSubId, isEnabled); 902 } catch (RemoteException e) { 903 Log.e(TAG, "Error calling IImsRcsController#setUceSettingEnabled", e); 904 throw new ImsException("Remote IMS Service is not available", 905 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 906 } 907 } 908 909 /** 910 * Add the {@link OnPublishStateChangedListener} to collection for tracking. 911 * @param executor The executor that will be used when the publish state is changed and the 912 * {@link OnPublishStateChangedListener} is called. 913 * @param listener The {@link OnPublishStateChangedListener} to call the publish state changed. 914 * @return The {@link PublishStateCallbackAdapter} to wrapper the 915 * {@link OnPublishStateChangedListener} 916 */ addPublishStateCallback(@onNull Executor executor, @NonNull OnPublishStateChangedListener listener)917 private PublishStateCallbackAdapter addPublishStateCallback(@NonNull Executor executor, 918 @NonNull OnPublishStateChangedListener listener) { 919 PublishStateCallbackAdapter adapter = new PublishStateCallbackAdapter(executor, listener); 920 synchronized (mPublishStateCallbacks) { 921 mPublishStateCallbacks.put(listener, adapter); 922 } 923 return adapter; 924 } 925 926 /** 927 * Remove the existing {@link OnPublishStateChangedListener}. 928 * @param listener The {@link OnPublishStateChangedListener} to remove from the collection. 929 * @return The wrapper class {@link PublishStateCallbackAdapter} associated with the 930 * {@link OnPublishStateChangedListener}. 931 */ removePublishStateCallback( @onNull OnPublishStateChangedListener listener)932 private PublishStateCallbackAdapter removePublishStateCallback( 933 @NonNull OnPublishStateChangedListener listener) { 934 synchronized (mPublishStateCallbacks) { 935 return mPublishStateCallbacks.remove(listener); 936 } 937 } 938 getIImsRcsController()939 private IImsRcsController getIImsRcsController() { 940 IBinder binder = TelephonyFrameworkInitializer 941 .getTelephonyServiceManager() 942 .getTelephonyImsServiceRegisterer() 943 .get(); 944 return IImsRcsController.Stub.asInterface(binder); 945 } 946 } 947