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