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