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