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