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