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