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