1 /* 2 * Copyright (C) 2020 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.IntDef; 21 import android.annotation.IntRange; 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.os.RemoteException; 30 import android.os.ServiceSpecificException; 31 import android.telephony.BinderCacheManager; 32 import android.telephony.ims.aidl.IImsRcsController; 33 import android.telephony.ims.aidl.SipDelegateConnectionAidlWrapper; 34 import android.telephony.ims.feature.ImsFeature; 35 import android.telephony.ims.stub.DelegateConnectionMessageCallback; 36 import android.telephony.ims.stub.DelegateConnectionStateCallback; 37 import android.telephony.ims.stub.SipDelegate; 38 import android.util.ArrayMap; 39 40 import com.android.internal.annotations.VisibleForTesting; 41 import com.android.internal.telephony.ITelephony; 42 43 import java.lang.annotation.Retention; 44 import java.lang.annotation.RetentionPolicy; 45 import java.util.Objects; 46 import java.util.concurrent.Executor; 47 48 /** 49 * Manages the creation and destruction of SipDelegates for the {@link ImsService} managing IMS 50 * for the subscription ID that this SipDelegateManager has been created for. 51 * 52 * This allows multiple IMS applications to forward SIP messages to/from their application for the 53 * purposes of providing a single IMS registration to the carrier's IMS network from potentially 54 * many IMS stacks implementing a subset of the supported MMTEL/RCS features. 55 * <p> 56 * This API is only supported if the device supports the 57 * {@link PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION} feature. 58 * @hide 59 */ 60 @SystemApi 61 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION) 62 public class SipDelegateManager { 63 64 /** 65 * The SIP message has failed being sent or received for an unknown reason. 66 * <p> 67 * The caller should retry a message that failed with this response. 68 */ 69 public static final int MESSAGE_FAILURE_REASON_UNKNOWN = 0; 70 71 /** 72 * The remote service associated with this connection has died and the message was not 73 * properly sent/received. 74 * <p> 75 * This is considered a permanent error and the system will automatically begin the teardown and 76 * destruction of the SipDelegate. No further messages should be sent on this transport. 77 */ 78 public static final int MESSAGE_FAILURE_REASON_DELEGATE_DEAD = 1; 79 80 /** 81 * The message has not been sent/received because the delegate is in the process of closing and 82 * has become unavailable. No further messages should be sent/received on this delegate. 83 */ 84 public static final int MESSAGE_FAILURE_REASON_DELEGATE_CLOSED = 2; 85 86 /** 87 * The SIP message has an invalid start line and the message can not be sent or the start line 88 * failed validation due to the request containing a restricted SIP request method. 89 * {@link SipDelegateConnection}s can not send SIP requests for the methods: REGISTER, PUBLISH, 90 * or OPTIONS. 91 */ 92 public static final int MESSAGE_FAILURE_REASON_INVALID_START_LINE = 3; 93 94 /** 95 * One or more of the header fields in the header section of the outgoing SIP message is invalid 96 * or contains a restricted header value and the SIP message can not be sent. 97 * {@link SipDelegateConnection}s can not send SIP SUBSCRIBE requests for the "Event" header 98 * value of "presence". 99 */ 100 public static final int MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS = 4; 101 102 /** 103 * The body content of the SIP message is invalid and the message can not be sent. 104 */ 105 public static final int MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT = 5; 106 107 /** 108 * The feature tag associated with the outgoing message does not match any known feature tags 109 * or it matches a denied tag and this message can not be sent. 110 */ 111 public static final int MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG = 6; 112 113 /** 114 * The feature tag associated with the outgoing message is not enabled for the associated 115 * SipDelegateConnection and can not be sent. 116 */ 117 public static final int MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE = 7; 118 119 /** 120 * The link to the network has been lost and the outgoing message has failed to send. 121 * <p> 122 * This message should be retried when connectivity to the network is re-established. See 123 * {@link android.net.ConnectivityManager.NetworkCallback} for how this can be determined. 124 */ 125 public static final int MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE = 8; 126 127 /** 128 * The outgoing SIP message has not been sent due to the SipDelegate not being registered for 129 * IMS at this time. 130 * <p> 131 * This is considered a temporary failure, the message should not be retried until an IMS 132 * registration change callback is received via 133 * {@link DelegateConnectionStateCallback#onFeatureTagStatusChanged} 134 */ 135 public static final int MESSAGE_FAILURE_REASON_NOT_REGISTERED = 9; 136 137 /** 138 * The outgoing SIP message has not been sent because the {@link SipDelegateConfiguration} 139 * version associated with the outgoing {@link SipMessage} is now stale and has failed 140 * validation checks. 141 * <p> 142 * The @link SipMessage} should be recreated using the newest 143 * {@link SipDelegateConfiguration} and sent again. 144 */ 145 public static final int MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION = 10; 146 147 /** 148 * The outgoing SIP message has not been sent because the internal state of the associated 149 * {@link SipDelegate} is changing and has temporarily brought the transport down. 150 * <p> 151 * This is considered a temporary error and the {@link SipDelegateConnection} should resend the 152 * message once {@link DelegateRegistrationState#DEREGISTERING_REASON_FEATURE_TAGS_CHANGING} is 153 * no longer reported. 154 */ 155 public static final int MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION = 11; 156 157 /** @hide */ 158 @Retention(RetentionPolicy.SOURCE) 159 @IntDef(prefix = "MESSAGE_FAILURE_REASON_", value = { 160 MESSAGE_FAILURE_REASON_UNKNOWN, 161 MESSAGE_FAILURE_REASON_DELEGATE_DEAD, 162 MESSAGE_FAILURE_REASON_DELEGATE_CLOSED, 163 MESSAGE_FAILURE_REASON_INVALID_START_LINE, 164 MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS, 165 MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT, 166 MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG, 167 MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE, 168 MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE, 169 MESSAGE_FAILURE_REASON_NOT_REGISTERED, 170 MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION, 171 MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION 172 }) 173 public @interface MessageFailureReason {} 174 175 /**@hide*/ 176 public static final ArrayMap<Integer, String> MESSAGE_FAILURE_REASON_STRING_MAP = 177 new ArrayMap<>(11); 178 static { MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_UNKNOWN, "MESSAGE_FAILURE_REASON_UNKNOWN")179 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_UNKNOWN, 180 "MESSAGE_FAILURE_REASON_UNKNOWN"); MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_DEAD, "MESSAGE_FAILURE_REASON_DELEGATE_DEAD")181 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_DEAD, 182 "MESSAGE_FAILURE_REASON_DELEGATE_DEAD"); MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_CLOSED, "MESSAGE_FAILURE_REASON_DELEGATE_CLOSED")183 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_CLOSED, 184 "MESSAGE_FAILURE_REASON_DELEGATE_CLOSED"); MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS, "MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS")185 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS, 186 "MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS"); MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT, "MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT")187 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT, 188 "MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT"); MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG, "MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG")189 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG, 190 "MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG"); MESSAGE_FAILURE_REASON_STRING_MAP.append( MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE, "MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE")191 MESSAGE_FAILURE_REASON_STRING_MAP.append( 192 MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE, 193 "MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE"); MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE, "MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE")194 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE, 195 "MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE"); MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NOT_REGISTERED, "MESSAGE_FAILURE_REASON_NOT_REGISTERED")196 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NOT_REGISTERED, 197 "MESSAGE_FAILURE_REASON_NOT_REGISTERED"); MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION, "MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION")198 MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION, 199 "MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION"); MESSAGE_FAILURE_REASON_STRING_MAP.append( MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION, "MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION")200 MESSAGE_FAILURE_REASON_STRING_MAP.append( 201 MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION, 202 "MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION"); 203 } 204 205 /** 206 * Access to use this feature tag has been denied for an unknown reason. 207 */ 208 public static final int DENIED_REASON_UNKNOWN = 0; 209 210 /** 211 * This feature tag is allowed to be used by this SipDelegateConnection, but it is in use by 212 * another SipDelegateConnection and can not be associated with this delegate. The feature tag 213 * will stay in this state until the feature tag is release by the other application. 214 */ 215 public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1; 216 217 /** 218 * Access to use this feature tag has been denied because this application does not have the 219 * permissions required to access this feature tag. 220 */ 221 public static final int DENIED_REASON_NOT_ALLOWED = 2; 222 223 /** 224 * Access to use this feature tag has been denied because single registration is not allowed by 225 * the carrier at this time. The application should fall back to dual registration if 226 * applicable. 227 */ 228 public static final int DENIED_REASON_SINGLE_REGISTRATION_NOT_ALLOWED = 3; 229 230 /** 231 * This feature tag is not recognized as a valid feature tag by the SipDelegate and has been 232 * denied. 233 */ 234 public static final int DENIED_REASON_INVALID = 4; 235 236 /** @hide */ 237 @Retention(RetentionPolicy.SOURCE) 238 @IntDef(prefix = "DENIED_REASON_", value = { 239 DENIED_REASON_UNKNOWN, 240 DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, 241 DENIED_REASON_NOT_ALLOWED, 242 DENIED_REASON_SINGLE_REGISTRATION_NOT_ALLOWED, 243 DENIED_REASON_INVALID 244 }) 245 public @interface DeniedReason {} 246 247 /** 248 * The SipDelegate has closed due to an unknown reason. 249 */ 250 public static final int SIP_DELEGATE_DESTROY_REASON_UNKNOWN = 0; 251 252 /** 253 * The SipDelegate has closed because the IMS service has died unexpectedly. 254 */ 255 public static final int SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD = 1; 256 257 /** 258 * The SipDelegate has closed because the IMS application has requested that the connection be 259 * destroyed. 260 */ 261 public static final int SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP = 2; 262 263 /** 264 * The SipDelegate has been closed due to the user disabling RCS. 265 */ 266 public static final int SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS = 3; 267 268 /** 269 * The SipDelegate has been closed due to the subscription associated with this delegate being 270 * torn down. 271 */ 272 public static final int SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN = 4; 273 274 /** @hide */ 275 @Retention(RetentionPolicy.SOURCE) 276 @IntDef(prefix = "SIP_DELEGATE_DESTROY_REASON", value = { 277 SIP_DELEGATE_DESTROY_REASON_UNKNOWN, 278 SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD, 279 SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP, 280 SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS, 281 SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN 282 }) 283 public @interface SipDelegateDestroyReason {} 284 285 private final Context mContext; 286 private final int mSubId; 287 private final BinderCacheManager<IImsRcsController> mBinderCache; 288 private final BinderCacheManager<ITelephony> mTelephonyBinderCache; 289 290 /** 291 * Only visible for testing. To instantiate an instance of this class, please use 292 * {@link ImsManager#getSipDelegateManager(int)}. 293 * @hide 294 */ 295 @VisibleForTesting SipDelegateManager(Context context, int subId, BinderCacheManager<IImsRcsController> binderCache, BinderCacheManager<ITelephony> telephonyBinderCache)296 public SipDelegateManager(Context context, int subId, 297 BinderCacheManager<IImsRcsController> binderCache, 298 BinderCacheManager<ITelephony> telephonyBinderCache) { 299 mContext = context; 300 mSubId = subId; 301 mBinderCache = binderCache; 302 mTelephonyBinderCache = telephonyBinderCache; 303 } 304 305 /** 306 * Determines if creating SIP delegates are supported for the subscription specified. 307 * <p> 308 * If SIP delegates are not supported on this device or the carrier associated with this 309 * subscription, creating a SIP delegate will always fail, as this feature is not supported. 310 * @return true if this device supports creating a SIP delegate and the carrier associated with 311 * this subscription supports single registration, false if creating SIP delegates is not 312 * supported. 313 * @throws ImsException If the remote ImsService is not available for any reason or the 314 * subscription associated with this instance is no longer active. See 315 * {@link ImsException#getCode()} for more information. 316 * 317 * @see CarrierConfigManager.Ims#KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL 318 * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION 319 */ 320 @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 321 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) isSupported()322 public boolean isSupported() throws ImsException { 323 try { 324 IImsRcsController controller = mBinderCache.getBinder(); 325 if (controller == null) { 326 throw new ImsException("Telephony server is down", 327 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 328 } 329 return controller.isSipDelegateSupported(mSubId); 330 } catch (ServiceSpecificException e) { 331 throw new ImsException(e.getMessage(), e.errorCode); 332 } catch (RemoteException e) { 333 throw new ImsException(e.getMessage(), 334 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 335 } 336 } 337 338 /** 339 * Request that the ImsService implementation create a SipDelegate, which will configure the 340 * ImsService to forward SIP traffic that matches the filtering criteria set in supplied 341 * {@link DelegateRequest} to the application that the supplied callbacks are registered for. 342 * <p> 343 * This API requires that the caller is running as part of a long-running process and will 344 * always be available to handle incoming messages. One mechanism that can be used for this is 345 * the {@link android.service.carrier.CarrierMessagingClientService}, which the framework keeps 346 * a persistent binding to when the app is the default SMS application. 347 * <p> 348 * Note: the ability to create SipDelegates is only available applications running as the 349 * primary user. 350 * @param request The parameters that are associated with the SipDelegate creation request that 351 * will be used to create the SipDelegate connection. 352 * @param executor The executor that will be used to call the callbacks associated with this 353 * SipDelegate. 354 * @param dc The callback that will be used to notify the listener of the creation/destruction 355 * of the remote SipDelegate as well as changes to the state of the remote SipDelegate 356 * connection. 357 * @param mc The callback that will be used to notify the listener of new incoming SIP messages 358 * as well as the status of messages that were sent by the associated 359 * SipDelegateConnection. 360 * @throws ImsException Thrown if there was a problem communicating with the ImsService 361 * associated with this SipDelegateManager. See {@link ImsException#getCode()}. 362 */ 363 @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) createSipDelegate(@onNull DelegateRequest request, @NonNull Executor executor, @NonNull DelegateConnectionStateCallback dc, @NonNull DelegateConnectionMessageCallback mc)364 public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor executor, 365 @NonNull DelegateConnectionStateCallback dc, 366 @NonNull DelegateConnectionMessageCallback mc) throws ImsException { 367 Objects.requireNonNull(request, "The DelegateRequest must not be null."); 368 Objects.requireNonNull(executor, "The Executor must not be null."); 369 Objects.requireNonNull(dc, "The DelegateConnectionStateCallback must not be null."); 370 Objects.requireNonNull(mc, "The DelegateConnectionMessageCallback must not be null."); 371 try { 372 SipDelegateConnectionAidlWrapper wrapper = 373 new SipDelegateConnectionAidlWrapper(executor, dc, mc); 374 IImsRcsController controller = mBinderCache.listenOnBinder(wrapper, 375 wrapper::binderDied); 376 if (controller == null) { 377 throw new ImsException("Telephony server is down", 378 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 379 } 380 controller.createSipDelegate(mSubId, request, mContext.getOpPackageName(), 381 wrapper.getStateCallbackBinder(), wrapper.getMessageCallbackBinder()); 382 } catch (ServiceSpecificException e) { 383 throw new ImsException(e.getMessage(), e.errorCode); 384 } catch (RemoteException e) { 385 throw new ImsException(e.getMessage(), 386 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 387 } 388 } 389 390 /** 391 * Destroy a previously created {@link SipDelegateConnection} that was created using 392 * {@link #createSipDelegate}. 393 * <p> 394 * This will also clean up all related callbacks in the associated ImsService. 395 * @param delegateConnection The SipDelegateConnection to destroy. 396 * @param reason The reason for why this SipDelegateConnection was destroyed. 397 */ 398 @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) destroySipDelegate(@onNull SipDelegateConnection delegateConnection, @SipDelegateDestroyReason int reason)399 public void destroySipDelegate(@NonNull SipDelegateConnection delegateConnection, 400 @SipDelegateDestroyReason int reason) { 401 Objects.requireNonNull(delegateConnection, "SipDelegateConnection can not be null."); 402 if (delegateConnection instanceof SipDelegateConnectionAidlWrapper) { 403 SipDelegateConnectionAidlWrapper w = 404 (SipDelegateConnectionAidlWrapper) delegateConnection; 405 try { 406 IImsRcsController c = mBinderCache.removeRunnable(w); 407 c.destroySipDelegate(mSubId, w.getSipDelegateBinder(), reason); 408 } catch (RemoteException e) { 409 // Connection to telephony died, but this will signal destruction of SipDelegate 410 // eventually anyway, so return normally. 411 try { 412 w.getStateCallbackBinder().onDestroyed( 413 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 414 } catch (RemoteException ignore) { 415 // Local to process. 416 } 417 } 418 } else { 419 throw new IllegalArgumentException("Unknown SipDelegateConnection implementation passed" 420 + " into this method"); 421 } 422 } 423 424 /** 425 * Trigger a full network registration as required by receiving a SIP message containing a 426 * permanent error from the network or never receiving a response to a SIP transaction request. 427 * 428 * @param connection The {@link SipDelegateConnection} that was being used when this error was 429 * received. 430 * @param sipCode The SIP code response associated with the SIP message request that 431 * triggered this condition. 432 * @param sipReason The SIP reason code associated with the SIP message request that triggered 433 * this condition. May be {@code null} if there was no reason String provided from the 434 * network. 435 */ 436 @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) triggerFullNetworkRegistration(@onNull SipDelegateConnection connection, @IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason)437 public void triggerFullNetworkRegistration(@NonNull SipDelegateConnection connection, 438 @IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason) { 439 Objects.requireNonNull(connection, "SipDelegateConnection can not be null."); 440 if (connection instanceof SipDelegateConnectionAidlWrapper) { 441 SipDelegateConnectionAidlWrapper w = (SipDelegateConnectionAidlWrapper) connection; 442 try { 443 IImsRcsController controller = mBinderCache.getBinder(); 444 controller.triggerNetworkRegistration(mSubId, w.getSipDelegateBinder(), sipCode, 445 sipReason); 446 } catch (RemoteException e) { 447 // Connection to telephony died, but this will signal destruction of SipDelegate 448 // eventually anyway, so return. 449 } 450 } else { 451 throw new IllegalArgumentException("Unknown SipDelegateConnection implementation passed" 452 + " into this method"); 453 } 454 } 455 456 /** 457 * Register a new callback, which is used to notify the registrant of changes to 458 * the state of the underlying IMS service that is attached to telephony to 459 * implement IMS functionality. If the manager is created for 460 * the {@link android.telephony.SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, 461 * this throws an {@link ImsException}. 462 * 463 * <p>Requires Permission: 464 * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE READ_PRECISE_PHONE_STATE} 465 * or that the calling app has carrier privileges 466 * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). 467 * 468 * @param executor the Executor that will be used to call the {@link ImsStateCallback}. 469 * @param callback The callback instance being registered. 470 * @throws ImsException in the case that the callback can not be registered. 471 * See {@link ImsException#getCode} for more information on when this is called. 472 */ 473 @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 474 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) registerImsStateCallback(@onNull Executor executor, @NonNull ImsStateCallback callback)475 public void registerImsStateCallback(@NonNull Executor executor, 476 @NonNull ImsStateCallback callback) throws ImsException { 477 Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback."); 478 Objects.requireNonNull(executor, "Must include a non-null Executor."); 479 480 callback.init(executor); 481 ITelephony telephony = mTelephonyBinderCache.listenOnBinder(callback, callback::binderDied); 482 if (telephony == null) { 483 throw new ImsException("Telephony server is down", 484 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 485 } 486 487 try { 488 telephony.registerImsStateCallback( 489 mSubId, ImsFeature.FEATURE_RCS, 490 callback.getCallbackBinder(), mContext.getOpPackageName()); 491 } catch (ServiceSpecificException e) { 492 throw new ImsException(e.getMessage(), e.errorCode); 493 } catch (RemoteException | IllegalStateException e) { 494 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 495 } 496 } 497 498 /** 499 * Unregisters a previously registered callback. 500 * 501 * @param callback The callback instance to be unregistered. 502 */ unregisterImsStateCallback(@onNull ImsStateCallback callback)503 public void unregisterImsStateCallback(@NonNull ImsStateCallback callback) { 504 Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback."); 505 506 ITelephony telephony = mTelephonyBinderCache.removeRunnable(callback); 507 508 try { 509 if (telephony != null) { 510 telephony.unregisterImsStateCallback(callback.getCallbackBinder()); 511 } 512 } catch (RemoteException ignore) { 513 // ignore it 514 } 515 } 516 517 /** 518 * Register a new callback, which is used to notify the registrant of changes 519 * to the state of the Sip Sessions managed remotely by the IMS stack. 520 * 521 * <p>Requires Permission: 522 * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} 523 * 524 * @param executor the Executor that will be used to call the {@link SipDialogStateCallback}. 525 * @param callback The callback instance being registered. 526 * @throws ImsException in the case that the callback can not be registered. 527 * See {@link ImsException#getCode} for more information on when this is called. 528 * @throws UnsupportedOperationException If the device does not have 529 * {@link PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION}. 530 */ 531 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) registerSipDialogStateCallback(@onNull Executor executor, @NonNull SipDialogStateCallback callback)532 public void registerSipDialogStateCallback(@NonNull Executor executor, 533 @NonNull SipDialogStateCallback callback) throws ImsException { 534 Objects.requireNonNull(callback, "Must include a non-null SipDialogStateCallback."); 535 Objects.requireNonNull(executor, "Must include a non-null Executor."); 536 537 callback.attachExecutor(executor); 538 try { 539 IImsRcsController controller = mBinderCache.listenOnBinder( 540 callback, callback::binderDied); 541 if (controller == null) { 542 throw new ImsException("Telephony server is down", 543 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 544 } 545 controller.registerSipDialogStateCallback(mSubId, callback.getCallbackBinder()); 546 } catch (ServiceSpecificException e) { 547 throw new ImsException(e.getMessage(), e.errorCode); 548 } catch (RemoteException e) { 549 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 550 } catch (IllegalStateException e) { 551 throw new IllegalStateException(e.getMessage()); 552 } 553 } 554 555 /** 556 * Unregisters a previously registered callback. 557 * 558 * <p>Requires Permission: 559 * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} 560 * 561 * @param callback The callback instance to be unregistered. 562 * 563 * @throws UnsupportedOperationException If the device does not have 564 * {@link PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION}. 565 */ 566 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) unregisterSipDialogStateCallback(@onNull SipDialogStateCallback callback)567 public void unregisterSipDialogStateCallback(@NonNull SipDialogStateCallback callback) 568 throws ImsException { 569 Objects.requireNonNull(callback, "Must include a non-null SipDialogStateCallback."); 570 571 IImsRcsController controller = mBinderCache.removeRunnable(callback); 572 try { 573 if (controller == null) { 574 throw new ImsException("Telephony server is down", 575 ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 576 } 577 controller.unregisterSipDialogStateCallback(mSubId, callback.getCallbackBinder()); 578 } catch (ServiceSpecificException e) { 579 throw new ImsException(e.getMessage(), e.errorCode); 580 } catch (RemoteException e) { 581 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 582 } catch (IllegalStateException e) { 583 throw new IllegalStateException(e.getMessage()); 584 } 585 } 586 } 587