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