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