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