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