1 /* 2 * Copyright (C) 2019 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.pm.PackageManager; 29 import android.net.Uri; 30 import android.os.Binder; 31 import android.os.Bundle; 32 import android.telephony.AccessNetworkConstants; 33 import android.telephony.NetworkRegistrationInfo; 34 import android.telephony.ims.aidl.IImsRegistrationCallback; 35 import android.telephony.ims.stub.ImsRegistrationImplBase; 36 import android.util.Log; 37 38 import com.android.internal.telephony.flags.Flags; 39 40 import java.lang.annotation.Retention; 41 import java.lang.annotation.RetentionPolicy; 42 import java.util.Map; 43 import java.util.concurrent.Executor; 44 import java.util.function.Consumer; 45 46 /** 47 * Manages IMS Service registration state for associated {@code ImsFeature}s. 48 */ 49 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS) 50 public interface RegistrationManager { 51 52 /** 53 * @hide 54 */ 55 // Defines the underlying radio technology type that we have registered for IMS over. 56 @IntDef(prefix = "REGISTRATION_STATE_", 57 value = { 58 REGISTRATION_STATE_NOT_REGISTERED, 59 REGISTRATION_STATE_REGISTERING, 60 REGISTRATION_STATE_REGISTERED 61 }) 62 @Retention(RetentionPolicy.SOURCE) 63 public @interface ImsRegistrationState {} 64 65 /** 66 * The IMS service is currently not registered to the carrier network. 67 */ 68 int REGISTRATION_STATE_NOT_REGISTERED = 0; 69 70 /** 71 * The IMS service is currently in the process of registering to the carrier network. 72 */ 73 int REGISTRATION_STATE_REGISTERING = 1; 74 75 /** 76 * The IMS service is currently registered to the carrier network. 77 */ 78 int REGISTRATION_STATE_REGISTERED = 2; 79 80 /** @hide */ 81 @IntDef(prefix = {"SUGGESTED_ACTION_"}, 82 value = { 83 SUGGESTED_ACTION_NONE, 84 SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK, 85 SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK_WITH_TIMEOUT, 86 SUGGESTED_ACTION_TRIGGER_RAT_BLOCK, 87 SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS 88 }) 89 @Retention(RetentionPolicy.SOURCE) 90 public @interface SuggestedAction {} 91 92 /** 93 * Default value. No action is suggested when IMS registration fails. 94 * @hide 95 */ 96 @SystemApi 97 public static final int SUGGESTED_ACTION_NONE = 0; 98 99 /** 100 * Indicates that the IMS registration is failed with fatal error such as 403 or 404 101 * on all P-CSCF addresses. The radio shall block the current PLMN or disable 102 * the RAT as per the carrier requirements. 103 * @hide 104 */ 105 @SystemApi 106 public static final int SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK = 1; 107 108 /** 109 * Indicates that the IMS registration on current PLMN failed multiple times. 110 * The radio shall block the current PLMN or disable the RAT during EPS or 5GS mobility 111 * management timer value as per the carrier requirements. 112 * @hide 113 */ 114 @SystemApi 115 public static final int SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK_WITH_TIMEOUT = 2; 116 117 /** 118 * Indicates that the IMS registration on current RAT failed multiple times. 119 * The radio shall block the {@link ImsRegistrationImplBase.ImsRegistrationTech} 120 * included with this and search for other available RATs in the background. 121 * If no other RAT is available that meets the carrier requirements, the 122 * radio may remain on the blocked RAT for internet service. The radio clears all 123 * RATs marked as unavailable if the IMS service is registered to the carrier network. 124 * @hide 125 */ 126 @SystemApi 127 @FlaggedApi(Flags.FLAG_ADD_RAT_RELATED_SUGGESTED_ACTION_TO_IMS_REGISTRATION) 128 int SUGGESTED_ACTION_TRIGGER_RAT_BLOCK = 3; 129 130 /** 131 * Indicates that the radio clears all RATs marked as unavailable and tries to find 132 * an available RAT that meets the carrier requirements. 133 * @hide 134 */ 135 @SystemApi 136 @FlaggedApi(Flags.FLAG_ADD_RAT_RELATED_SUGGESTED_ACTION_TO_IMS_REGISTRATION) 137 int SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS = 4; 138 139 /**@hide*/ 140 // Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN 141 // and WWAN are more accurate constants. 142 Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP = Map.of( 143 // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE 144 // case, since it is defined. 145 ImsRegistrationImplBase.REGISTRATION_TECH_NONE, 146 AccessNetworkConstants.TRANSPORT_TYPE_INVALID, 147 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, 148 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 149 ImsRegistrationImplBase.REGISTRATION_TECH_NR, 150 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 151 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, 152 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, 153 /* As the cross sim will be using ePDG tunnel over internet, it behaves 154 like IWLAN in most cases. Hence setting the access type as IWLAN 155 */ 156 ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM, 157 AccessNetworkConstants.TRANSPORT_TYPE_WLAN); 158 159 /** @hide */ 160 @NonNull registrationStateToString( final @NetworkRegistrationInfo.RegistrationState int value)161 static String registrationStateToString( 162 final @NetworkRegistrationInfo.RegistrationState int value) { 163 switch (value) { 164 case REGISTRATION_STATE_NOT_REGISTERED: 165 return "REGISTRATION_STATE_NOT_REGISTERED"; 166 case REGISTRATION_STATE_REGISTERING: 167 return "REGISTRATION_STATE_REGISTERING"; 168 case REGISTRATION_STATE_REGISTERED: 169 return "REGISTRATION_STATE_REGISTERED"; 170 default: 171 return Integer.toString(value); 172 } 173 } 174 175 /** 176 * @param regtech The registration technology. 177 * @return The Access Network type from registration technology. 178 * @hide 179 */ getAccessType(int regtech)180 static int getAccessType(int regtech) { 181 if (!RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regtech)) { 182 Log.w("RegistrationManager", "getAccessType - invalid regType returned: " 183 + regtech); 184 return AccessNetworkConstants.TRANSPORT_TYPE_INVALID; 185 } 186 return RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(regtech); 187 } 188 189 /** 190 * Callback class for receiving IMS network Registration callback events. 191 * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) 192 * @see #unregisterImsRegistrationCallback(RegistrationCallback) 193 */ 194 class RegistrationCallback { 195 196 private static class RegistrationBinder extends IImsRegistrationCallback.Stub { 197 198 private final RegistrationCallback mLocalCallback; 199 private Executor mExecutor; 200 private Bundle mBundle = new Bundle(); 201 RegistrationBinder(RegistrationCallback localCallback)202 RegistrationBinder(RegistrationCallback localCallback) { 203 mLocalCallback = localCallback; 204 } 205 206 @Override onRegistered(ImsRegistrationAttributes attr)207 public void onRegistered(ImsRegistrationAttributes attr) { 208 if (mLocalCallback == null) return; 209 210 final long callingIdentity = Binder.clearCallingIdentity(); 211 try { 212 mExecutor.execute(() -> mLocalCallback.onRegistered(attr)); 213 } finally { 214 restoreCallingIdentity(callingIdentity); 215 } 216 } 217 218 @Override onRegistering(ImsRegistrationAttributes attr)219 public void onRegistering(ImsRegistrationAttributes attr) { 220 if (mLocalCallback == null) return; 221 222 final long callingIdentity = Binder.clearCallingIdentity(); 223 try { 224 mExecutor.execute(() -> mLocalCallback.onRegistering(attr)); 225 } finally { 226 restoreCallingIdentity(callingIdentity); 227 } 228 } 229 230 @Override onDeregistered(ImsReasonInfo info, @SuggestedAction int suggestedAction, @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech)231 public void onDeregistered(ImsReasonInfo info, 232 @SuggestedAction int suggestedAction, 233 @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) { 234 if (mLocalCallback == null) return; 235 236 final long callingIdentity = Binder.clearCallingIdentity(); 237 try { 238 mExecutor.execute(() -> mLocalCallback.onUnregistered(info, 239 suggestedAction, imsRadioTech)); 240 } finally { 241 restoreCallingIdentity(callingIdentity); 242 } 243 } 244 245 @Override onDeregisteredWithDetails(ImsReasonInfo info, @SuggestedAction int suggestedAction, @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech, @NonNull SipDetails details)246 public void onDeregisteredWithDetails(ImsReasonInfo info, 247 @SuggestedAction int suggestedAction, 248 @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech, 249 @NonNull SipDetails details) { 250 if (mLocalCallback == null) return; 251 252 final long callingIdentity = Binder.clearCallingIdentity(); 253 try { 254 mExecutor.execute(() -> mLocalCallback.onUnregistered(info, suggestedAction, 255 imsRadioTech)); 256 mExecutor.execute(() -> mLocalCallback.onUnregistered(info, details)); 257 } finally { 258 restoreCallingIdentity(callingIdentity); 259 } 260 } 261 262 @Override onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info)263 public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) { 264 if (mLocalCallback == null) return; 265 266 final long callingIdentity = Binder.clearCallingIdentity(); 267 try { 268 mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed( 269 getAccessType(imsRadioTech), info)); 270 } finally { 271 restoreCallingIdentity(callingIdentity); 272 } 273 } 274 onSubscriberAssociatedUriChanged(Uri[] uris)275 public void onSubscriberAssociatedUriChanged(Uri[] uris) { 276 if (mLocalCallback == null) return; 277 278 final long callingIdentity = Binder.clearCallingIdentity(); 279 try { 280 mExecutor.execute(() -> mLocalCallback.onSubscriberAssociatedUriChanged(uris)); 281 } finally { 282 restoreCallingIdentity(callingIdentity); 283 } 284 } 285 setExecutor(Executor executor)286 private void setExecutor(Executor executor) { 287 mExecutor = executor; 288 } 289 } 290 291 private final RegistrationBinder mBinder = new RegistrationBinder(this); 292 293 /** 294 * Notifies the framework when the IMS Provider is registered to the IMS network. 295 * 296 * @param imsTransportType the radio access technology. 297 * @deprecated Use {@link #onRegistered(ImsRegistrationAttributes)} instead. 298 */ 299 @Deprecated onRegistered(@ccessNetworkConstants.TransportType int imsTransportType)300 public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) { 301 } 302 303 /** 304 * Notifies the framework when the IMS Provider is registered to the IMS network 305 * with corresponding attributes. 306 * 307 * @param attributes The attributes associated with this IMS registration. 308 */ onRegistered(@onNull ImsRegistrationAttributes attributes)309 public void onRegistered(@NonNull ImsRegistrationAttributes attributes) { 310 // Default impl to keep backwards compatibility with old implementations 311 onRegistered(attributes.getTransportType()); 312 } 313 314 /** 315 * Notifies the framework when the IMS Provider is trying to register the IMS network. 316 * 317 * @param imsTransportType the radio access technology. 318 * @deprecated Use {@link #onRegistering(ImsRegistrationAttributes)} instead. 319 */ onRegistering(@ccessNetworkConstants.TransportType int imsTransportType)320 public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) { 321 } 322 323 /** 324 * Notifies the framework when the IMS Provider is trying to register the IMS network. 325 * 326 * @param attributes The attributes associated with this IMS registration. 327 */ onRegistering(@onNull ImsRegistrationAttributes attributes)328 public void onRegistering(@NonNull ImsRegistrationAttributes attributes) { 329 // Default impl to keep backwards compatibility with old implementations 330 onRegistering(attributes.getTransportType()); 331 } 332 333 /** 334 * Notifies the framework when the IMS Provider is unregistered from the IMS network. 335 * 336 * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. 337 */ onUnregistered(@onNull ImsReasonInfo info)338 public void onUnregistered(@NonNull ImsReasonInfo info) { 339 } 340 341 /** 342 * Notifies the framework when the IMS Provider is unregistered from the IMS network. 343 * 344 * Since this callback is only required for the communication between telephony framework 345 * and ImsService, it is made hidden. 346 * 347 * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. 348 * @param suggestedAction the expected behavior of radio protocol stack. 349 * @param imsRadioTech the network type on which IMS registration has failed. 350 * @hide 351 */ onUnregistered(@onNull ImsReasonInfo info, @SuggestedAction int suggestedAction, @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech)352 public void onUnregistered(@NonNull ImsReasonInfo info, 353 @SuggestedAction int suggestedAction, 354 @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) { 355 // Default impl to keep backwards compatibility with old implementations 356 onUnregistered(info); 357 } 358 359 /** 360 * Notifies the framework when the IMS Provider is unregistered from the IMS network. 361 * 362 * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. 363 * @param details the {@link SipDetails} related to disconnected Ims registration. 364 * 365 * @hide 366 */ 367 @SystemApi onUnregistered(@onNull ImsReasonInfo info, @NonNull SipDetails details)368 public void onUnregistered(@NonNull ImsReasonInfo info, 369 @NonNull SipDetails details) { 370 } 371 372 /** 373 * A failure has occurred when trying to handover registration to another technology type. 374 * 375 * @param imsTransportType The transport type that has failed to handover registration to. 376 * @param info A {@link ImsReasonInfo} that identifies the reason for failure. 377 */ onTechnologyChangeFailed( @ccessNetworkConstants.TransportType int imsTransportType, @NonNull ImsReasonInfo info)378 public void onTechnologyChangeFailed( 379 @AccessNetworkConstants.TransportType int imsTransportType, 380 @NonNull ImsReasonInfo info) { 381 } 382 383 /** 384 * Returns a list of subscriber {@link Uri}s associated with this IMS subscription when 385 * it changes. Per RFC3455, an associated URI is a URI that the service provider has 386 * allocated to a user for their own usage. A user's phone number is typically one of the 387 * associated URIs. 388 * @param uris new array of subscriber {@link Uri}s that are associated with this IMS 389 * subscription. 390 * @hide 391 */ onSubscriberAssociatedUriChanged(@ullable Uri[] uris)392 public void onSubscriberAssociatedUriChanged(@Nullable Uri[] uris) { 393 } 394 395 /**@hide*/ getBinder()396 public final IImsRegistrationCallback getBinder() { 397 return mBinder; 398 } 399 400 /**@hide*/ 401 //Only exposed as public for compatibility with deprecated ImsManager APIs. setExecutor(Executor executor)402 public void setExecutor(Executor executor) { 403 mBinder.setExecutor(executor); 404 } 405 } 406 407 /** 408 * Registers a {@link RegistrationCallback} with the system. Use 409 * @param executor The {@link Executor} that will be used to call the IMS registration state 410 * callback. 411 * @param c A callback called on the supplied {@link Executor} that will contain the 412 * registration state of the IMS service, which will be one of the 413 * {@see SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed 414 * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. 415 * 416 * When the callback is registered, it will initiate the callback c to be called with the 417 * current registration state. 418 * 419 * @param executor The executor the callback events should be run on. 420 * @param c The {@link RegistrationCallback} to be added. 421 * @see #unregisterImsRegistrationCallback(RegistrationCallback) 422 * @throws ImsException if the subscription associated with this callback is valid, but 423 * the {@code ImsService} associated with the subscription is not available. This can happen if 424 * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed 425 * reason. 426 */ 427 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) registerImsRegistrationCallback(@onNull @allbackExecutor Executor executor, @NonNull RegistrationCallback c)428 void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, 429 @NonNull RegistrationCallback c) throws ImsException; 430 431 /** 432 * Removes an existing {@link RegistrationCallback}. 433 * 434 * When the subscription associated with this callback is removed (SIM removed, ESIM swap, 435 * etc...), this callback will automatically be removed. If this method is called for an 436 * inactive subscription, it will result in a no-op. 437 * 438 * @param c The {@link RegistrationCallback} to be removed. 439 * @see android.telephony.SubscriptionManager.OnSubscriptionsChangedListener 440 * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) 441 */ 442 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) unregisterImsRegistrationCallback(@onNull RegistrationCallback c)443 void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c); 444 445 /** 446 * Gets the registration state of the IMS service. 447 * @param executor The {@link Executor} that will be used to call the IMS registration state 448 * callback. 449 * @param stateCallback A callback called on the supplied {@link Executor} that will contain the 450 * registration state of the IMS service, which will be one of the 451 * following: {@link #REGISTRATION_STATE_NOT_REGISTERED}, 452 * {@link #REGISTRATION_STATE_REGISTERING}, or 453 * {@link #REGISTRATION_STATE_REGISTERED}. 454 */ 455 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getRegistrationState(@onNull @allbackExecutor Executor executor, @NonNull @ImsRegistrationState Consumer<Integer> stateCallback)456 void getRegistrationState(@NonNull @CallbackExecutor Executor executor, 457 @NonNull @ImsRegistrationState Consumer<Integer> stateCallback); 458 459 /** 460 * Gets the Transport Type associated with the current IMS registration. 461 * @param executor The {@link Executor} that will be used to call the transportTypeCallback. 462 * @param transportTypeCallback The transport type associated with the current IMS registration, 463 * which will be one of following: 464 * {@see AccessNetworkConstants#TRANSPORT_TYPE_WWAN}, 465 * {@see AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or 466 * {@see AccessNetworkConstants#TRANSPORT_TYPE_INVALID}. 467 */ 468 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getRegistrationTransportType( @onNull @allbackExecutor Executor executor, @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback)469 void getRegistrationTransportType( 470 @NonNull @CallbackExecutor Executor executor, 471 @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback); 472 } 473