• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.stub;
18 
19 import android.annotation.IntDef;
20 import android.annotation.SystemApi;
21 import android.net.Uri;
22 import android.os.RemoteCallbackList;
23 import android.os.RemoteException;
24 import android.telephony.ims.ImsReasonInfo;
25 import android.telephony.ims.aidl.IImsRegistration;
26 import android.telephony.ims.aidl.IImsRegistrationCallback;
27 import android.util.Log;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 
34 /**
35  * Controls IMS registration for this ImsService and notifies the framework when the IMS
36  * registration for this ImsService has changed status.
37  * @hide
38  */
39 @SystemApi
40 public class ImsRegistrationImplBase {
41 
42     private static final String LOG_TAG = "ImsRegistrationImplBase";
43 
44     /**
45      * @hide
46      */
47     // Defines the underlying radio technology type that we have registered for IMS over.
48     @IntDef(flag = true,
49             value = {
50                     REGISTRATION_TECH_NONE,
51                     REGISTRATION_TECH_LTE,
52                     REGISTRATION_TECH_IWLAN
53             })
54     @Retention(RetentionPolicy.SOURCE)
55     public @interface ImsRegistrationTech {}
56     /**
57      * No registration technology specified, used when we are not registered.
58      */
59     public static final int REGISTRATION_TECH_NONE = -1;
60     /**
61      * IMS is registered to IMS via LTE.
62      */
63     public static final int REGISTRATION_TECH_LTE = 0;
64     /**
65      * IMS is registered to IMS via IWLAN.
66      */
67     public static final int REGISTRATION_TECH_IWLAN = 1;
68 
69     // Registration states, used to notify new ImsRegistrationImplBase#Callbacks of the current
70     // state.
71     // The unknown state is set as the initialization state. This is so that we do not call back
72     // with NOT_REGISTERED in the case where the ImsService has not updated the registration state
73     // yet.
74     private static final int REGISTRATION_STATE_UNKNOWN = -1;
75     private static final int REGISTRATION_STATE_NOT_REGISTERED = 0;
76     private static final int REGISTRATION_STATE_REGISTERING = 1;
77     private static final int REGISTRATION_STATE_REGISTERED = 2;
78 
79     private final IImsRegistration mBinder = new IImsRegistration.Stub() {
80 
81         @Override
82         public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException {
83             return getConnectionType();
84         }
85 
86         @Override
87         public void addRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
88             ImsRegistrationImplBase.this.addRegistrationCallback(c);
89         }
90 
91         @Override
92         public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
93             ImsRegistrationImplBase.this.removeRegistrationCallback(c);
94         }
95     };
96 
97     private final RemoteCallbackList<IImsRegistrationCallback> mCallbacks
98             = new RemoteCallbackList<>();
99     private final Object mLock = new Object();
100     // Locked on mLock
101     private @ImsRegistrationTech
102     int mConnectionType = REGISTRATION_TECH_NONE;
103     // Locked on mLock
104     private int mRegistrationState = REGISTRATION_STATE_UNKNOWN;
105     // Locked on mLock, create unspecified disconnect cause.
106     private ImsReasonInfo mLastDisconnectCause = new ImsReasonInfo();
107 
108     /**
109      * @hide
110      */
getBinder()111     public final IImsRegistration getBinder() {
112         return mBinder;
113     }
114 
addRegistrationCallback(IImsRegistrationCallback c)115     private void addRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
116         mCallbacks.register(c);
117         updateNewCallbackWithState(c);
118     }
119 
removeRegistrationCallback(IImsRegistrationCallback c)120     private void removeRegistrationCallback(IImsRegistrationCallback c) {
121         mCallbacks.unregister(c);
122     }
123 
124     /**
125      * Notify the framework that the device is connected to the IMS network.
126      *
127      * @param imsRadioTech the radio access technology. Valid values are defined as
128      * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
129      */
onRegistered(@msRegistrationTech int imsRadioTech)130     public final void onRegistered(@ImsRegistrationTech int imsRadioTech) {
131         updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERED);
132         mCallbacks.broadcast((c) -> {
133             try {
134                 c.onRegistered(imsRadioTech);
135             } catch (RemoteException e) {
136                 Log.w(LOG_TAG, e + " " + "onRegistrationConnected() - Skipping " +
137                         "callback.");
138             }
139         });
140     }
141 
142     /**
143      * Notify the framework that the device is trying to connect the IMS network.
144      *
145      * @param imsRadioTech the radio access technology. Valid values are defined as
146      * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
147      */
onRegistering(@msRegistrationTech int imsRadioTech)148     public final void onRegistering(@ImsRegistrationTech int imsRadioTech) {
149         updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERING);
150         mCallbacks.broadcast((c) -> {
151             try {
152                 c.onRegistering(imsRadioTech);
153             } catch (RemoteException e) {
154                 Log.w(LOG_TAG, e + " " + "onRegistrationProcessing() - Skipping " +
155                         "callback.");
156             }
157         });
158     }
159 
160     /**
161      * Notify the framework that the device is disconnected from the IMS network.
162      * <p>
163      * Note: Prior to calling {@link #onDeregistered(ImsReasonInfo)}, you should ensure that any
164      * changes to {@link android.telephony.ims.feature.ImsFeature} capability availability is sent
165      * to the framework.  For example,
166      * {@link android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}
167      * and
168      * {@link android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}
169      * may be set to unavailable to ensure the framework knows these services are no longer
170      * available due to de-registration.  If you do not report capability changes impacted by
171      * de-registration, the framework will not know which features are no longer available as a
172      * result.
173      *
174      * @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
175      */
onDeregistered(ImsReasonInfo info)176     public final void onDeregistered(ImsReasonInfo info) {
177         updateToDisconnectedState(info);
178         mCallbacks.broadcast((c) -> {
179             try {
180                 c.onDeregistered(info);
181             } catch (RemoteException e) {
182                 Log.w(LOG_TAG, e + " " + "onRegistrationDisconnected() - Skipping " +
183                         "callback.");
184             }
185         });
186     }
187 
188     /**
189      * Notify the framework that the handover from the current radio technology to the technology
190      * defined in {@code imsRadioTech} has failed.
191      * @param imsRadioTech The technology that has failed to be changed. Valid values are
192      * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
193      * @param info The {@link ImsReasonInfo} for the failure to change technology.
194      */
onTechnologyChangeFailed(@msRegistrationTech int imsRadioTech, ImsReasonInfo info)195     public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech,
196             ImsReasonInfo info) {
197         mCallbacks.broadcast((c) -> {
198             try {
199                 c.onTechnologyChangeFailed(imsRadioTech, info);
200             } catch (RemoteException e) {
201                 Log.w(LOG_TAG, e + " " + "onRegistrationChangeFailed() - Skipping " +
202                         "callback.");
203             }
204         });
205     }
206 
207     /**
208      * The this device's subscriber associated {@link Uri}s have changed, which are used to filter
209      * out this device's {@link Uri}s during conference calling.
210      * @param uris
211      */
onSubscriberAssociatedUriChanged(Uri[] uris)212     public final void onSubscriberAssociatedUriChanged(Uri[] uris) {
213         mCallbacks.broadcast((c) -> {
214             try {
215                 c.onSubscriberAssociatedUriChanged(uris);
216             } catch (RemoteException e) {
217                 Log.w(LOG_TAG, e + " " + "onSubscriberAssociatedUriChanged() - Skipping " +
218                         "callback.");
219             }
220         });
221     }
222 
updateToState(@msRegistrationTech int connType, int newState)223     private void updateToState(@ImsRegistrationTech int connType, int newState) {
224         synchronized (mLock) {
225             mConnectionType = connType;
226             mRegistrationState = newState;
227             mLastDisconnectCause = null;
228         }
229     }
230 
updateToDisconnectedState(ImsReasonInfo info)231     private void updateToDisconnectedState(ImsReasonInfo info) {
232         synchronized (mLock) {
233             updateToState(REGISTRATION_TECH_NONE, REGISTRATION_STATE_NOT_REGISTERED);
234             if (info != null) {
235                 mLastDisconnectCause = info;
236             } else {
237                 Log.w(LOG_TAG, "updateToDisconnectedState: no ImsReasonInfo provided.");
238                 mLastDisconnectCause = new ImsReasonInfo();
239             }
240         }
241     }
242 
243     /**
244      * @return the current registration connection type. Valid values are
245      * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}
246      * @hide
247      */
248     @VisibleForTesting
getConnectionType()249     public final @ImsRegistrationTech int getConnectionType() {
250         synchronized (mLock) {
251             return mConnectionType;
252         }
253     }
254 
255     /**
256      * @param c the newly registered callback that will be updated with the current registration
257      *         state.
258      */
updateNewCallbackWithState(IImsRegistrationCallback c)259     private void updateNewCallbackWithState(IImsRegistrationCallback c) throws RemoteException {
260         int state;
261         ImsReasonInfo disconnectInfo;
262         synchronized (mLock) {
263             state = mRegistrationState;
264             disconnectInfo = mLastDisconnectCause;
265         }
266         switch (state) {
267             case REGISTRATION_STATE_NOT_REGISTERED: {
268                 c.onDeregistered(disconnectInfo);
269                 break;
270             }
271             case REGISTRATION_STATE_REGISTERING: {
272                 c.onRegistering(getConnectionType());
273                 break;
274             }
275             case REGISTRATION_STATE_REGISTERED: {
276                 c.onRegistered(getConnectionType());
277                 break;
278             }
279             case REGISTRATION_STATE_UNKNOWN: {
280                 // Do not callback if the state has not been updated yet by the ImsService.
281                 break;
282             }
283         }
284     }
285 }
286