• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 com.android.services.telephony.rcs;
18 
19 import android.app.compat.CompatChanges;
20 import android.compat.annotation.ChangeId;
21 import android.compat.annotation.EnabledAfter;
22 import android.os.Build;
23 import android.os.RemoteException;
24 import android.telephony.ims.DelegateRegistrationState;
25 import android.telephony.ims.FeatureTagState;
26 import android.telephony.ims.SipDelegateConfiguration;
27 import android.telephony.ims.SipDelegateImsConfiguration;
28 import android.telephony.ims.aidl.ISipDelegate;
29 import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
30 import android.telephony.ims.stub.DelegateConnectionStateCallback;
31 import android.util.ArraySet;
32 import android.util.LocalLog;
33 import android.util.Log;
34 
35 import com.android.internal.annotations.VisibleForTesting;
36 import com.android.internal.telephony.metrics.RcsStats;
37 
38 import java.io.PrintWriter;
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Set;
42 
43 /**
44  * Manages the events sent back to the remote IMS application using the AIDL backing for the
45  * {@link DelegateConnectionStateCallback} interface.
46  */
47 public class DelegateStateTracker implements DelegateBinderStateManager.StateCallback {
48     private static final String LOG_TAG = "DelegateST";
49 
50     private final int mSubId;
51     private final int mUid;
52     private final ISipDelegateConnectionStateCallback mAppStateCallback;
53     private final ISipDelegate mLocalDelegateImpl;
54 
55     private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
56 
57     private final RcsStats mRcsStats;
58 
59     private List<FeatureTagState> mDelegateDeniedTags;
60     private DelegateRegistrationState mLastRegState;
61     private boolean mCreatedCalled = false;
62     private int mRegistrationStateOverride = -1;
63     private CompatChangesFactory mCompatChangesFactory;
64     private Set<String> mDelegateSupportedTags;
65 
66     /**
67      * Interface for checking compatibility of apps
68      */
69     public interface CompatChangesFactory {
70         /**
71          *  @param changeId The ID of the compatibility change.
72          *  @param uid      The UID of the app.
73          *  @return {@code true} if the change is enabled for the current app.
74          */
isChangeEnabled(long changeId, int uid)75         boolean isChangeEnabled(long changeId, int uid);
76     }
77 
78     /**
79      * For apps targeting Android T and above, support the REGISTERING state on APIs, such as
80      * {@code DelegateRegistrationState#addRegisteringFeatureTags} and
81      * {@code DelegateRegistrationState#getRegisteringFeatureTags}
82      * @hide
83      */
84     @ChangeId
85     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
86     @VisibleForTesting
87     public static final long SUPPORT_REGISTERING_DELEGATE_STATE = 205194548;
88 
89     /**
90      * For apps targeting Android T and above, support the DEREGISTERING_REASON_LOSING_PDN state
91      * on APIs, such as {@code DelegateRegistrationState#addDeregisteringFeatureTag} and
92      * {@code DelegateRegistrationState#getDeregisteringFeatureTags}
93      * @hide
94      */
95     @ChangeId
96     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
97     @VisibleForTesting
98     public static final long SUPPORT_DEREGISTERING_LOSING_PDN_STATE = 201522903;
99 
DelegateStateTracker(int subId, int uid, ISipDelegateConnectionStateCallback appStateCallback, ISipDelegate localDelegateImpl, RcsStats rcsStats)100     public DelegateStateTracker(int subId, int uid,
101             ISipDelegateConnectionStateCallback appStateCallback,
102             ISipDelegate localDelegateImpl, RcsStats rcsStats) {
103         mSubId = subId;
104         mUid = uid;
105         mAppStateCallback = appStateCallback;
106         mLocalDelegateImpl = localDelegateImpl;
107         mRcsStats = rcsStats;
108         setCompatChangesFactory((changeId, uid1) -> CompatChanges.isChangeEnabled(changeId, uid1));
109     }
110 
111     @VisibleForTesting
setCompatChangesFactory(CompatChangesFactory factory)112     protected void setCompatChangesFactory(CompatChangesFactory factory) {
113         mCompatChangesFactory = factory;
114     }
115 
116     /**
117      * Notify this state tracker that a new internal SipDelegate has been connected.
118      *
119      * Registration and state updates will be send via the
120      * {@link SipDelegateBinderConnection.StateCallback} callback implemented by this class as they
121      * arrive.
122      * @param supportedTags the tags supported by the SipTransportController and ImsService creating
123      *                      the SipDelegate. These tags will be used as a key for SipDelegate
124      *                      metrics.
125      * @param deniedTags The tags denied by the SipTransportController and ImsService creating the
126      *         SipDelegate. These tags will need to be notified back to the IMS application.
127      */
sipDelegateConnected(Set<String> supportedTags, Set<FeatureTagState> deniedTags)128     public void sipDelegateConnected(Set<String> supportedTags, Set<FeatureTagState> deniedTags) {
129         logi("SipDelegate connected with denied tags:" + deniedTags);
130         // From the IMS application perspective, we only call onCreated/onDestroyed once and
131         // provide the local implementation of ISipDelegate, which doesn't change, even though
132         // SipDelegates may be changing underneath.
133         if (!mCreatedCalled) {
134             mCreatedCalled = true;
135             notifySipDelegateCreated();
136             mDelegateSupportedTags = supportedTags;
137             mRcsStats.createSipDelegateStats(mSubId, mDelegateSupportedTags);
138         }
139         mRegistrationStateOverride = -1;
140         mDelegateDeniedTags = new ArrayList<>(deniedTags);
141     }
142 
143     /**
144      * The underlying SipDelegate is changing due to a state change in the SipDelegateController.
145      *
146      * This will trigger an override of the IMS application's registration state. All feature tags
147      * in the REGISTERED state will be overridden to move to the deregistering state specified until
148      * a new SipDelegate was successfully created and {@link #sipDelegateConnected(Set, Set)} was
149      * called or it was destroyed and {@link #sipDelegateDestroyed(int)} was called.
150      * @param deregisteringReason The new deregistering reason that all feature tags in the
151      *         registered state should now report.
152      */
sipDelegateChanging(int deregisteringReason)153     public void sipDelegateChanging(int deregisteringReason) {
154         logi("SipDelegate Changing");
155         mRegistrationStateOverride = deregisteringReason;
156         if (mLastRegState == null) {
157             logw("sipDelegateChanging: invalid state, onRegistrationStateChanged never called.");
158             mLastRegState = new DelegateRegistrationState.Builder().build();
159         }
160         onRegistrationStateChanged(mLastRegState);
161     }
162 
163     /**
164      * The underlying SipDelegate has been destroyed.
165      *
166      * This should only be called when the entire {@link SipDelegateController} is going down
167      * because the application has requested that the SipDelegate be destroyed.
168      *
169      * This can also be called in error conditions where the IMS application or ImsService has
170      * crashed.
171      * @param reason The reason that will be sent to the IMS application for why the SipDelegate
172      *         is being destroyed.
173      */
sipDelegateDestroyed(int reason)174     public void sipDelegateDestroyed(int reason) {
175         logi("SipDelegate destroyed:" + reason);
176         mRegistrationStateOverride = -1;
177         try {
178             mAppStateCallback.onDestroyed(reason);
179             mRcsStats.onSipDelegateStats(mSubId, mDelegateSupportedTags, reason);
180         } catch (RemoteException e) {
181             logw("sipDelegateDestroyed: IMS application is dead: " + e);
182         }
183     }
184 
185     /**
186      * The underlying SipDelegate has reported that its registration state has changed.
187      * @param registrationState The RegistrationState reported by the SipDelegate to be sent to the
188      *         IMS application.
189      */
190     @Override
onRegistrationStateChanged(DelegateRegistrationState registrationState)191     public void onRegistrationStateChanged(DelegateRegistrationState registrationState) {
192         if (!mCompatChangesFactory.isChangeEnabled(SUPPORT_DEREGISTERING_LOSING_PDN_STATE, mUid)) {
193             registrationState = overrideDeregisteringStateForCompatibility(registrationState);
194         }
195         if (!mCompatChangesFactory.isChangeEnabled(SUPPORT_REGISTERING_DELEGATE_STATE, mUid)) {
196             registrationState = overrideRegistrationForCompatibility(registrationState);
197         }
198 
199         if (mRegistrationStateOverride > DelegateRegistrationState.DEREGISTERED_REASON_UNKNOWN) {
200             logi("onRegistrationStateChanged: overriding registered state to "
201                     + mRegistrationStateOverride);
202             registrationState = overrideRegistrationForDelegateChange(mRegistrationStateOverride,
203                     registrationState);
204         }
205         if (registrationState.equals(mLastRegState)) {
206             logi("onRegistrationStateChanged: skipping notification, state is the same.");
207             return;
208         }
209         mLastRegState = registrationState;
210         logi("onRegistrationStateChanged: sending reg state " + registrationState);
211         try {
212             mAppStateCallback.onFeatureTagStatusChanged(registrationState, mDelegateDeniedTags);
213             Set<String> registeredFeatureTags = registrationState.getRegisteredFeatureTags();
214             mRcsStats.onSipTransportFeatureTagStats(mSubId,
215                     new ArraySet<FeatureTagState>(mDelegateDeniedTags),
216                     registrationState.getDeregisteredFeatureTags(),
217                     registeredFeatureTags);
218         } catch (RemoteException e) {
219             logw("onRegistrationStateChanged: IMS application is dead: " + e);
220         }
221     }
222 
223     /**
224      * THe underlying SipDelegate has reported that the IMS configuration has changed.
225      * @param config The config to be sent to the IMS application.
226      */
227     @Override
onImsConfigurationChanged(SipDelegateImsConfiguration config)228     public void onImsConfigurationChanged(SipDelegateImsConfiguration config) {
229         logi("onImsConfigurationChanged: Sending new IMS configuration.");
230         try {
231             mAppStateCallback.onImsConfigurationChanged(config);
232         } catch (RemoteException e) {
233             logw("onImsConfigurationChanged: IMS application is dead: " + e);
234         }
235     }
236 
237     /**
238      * THe underlying SipDelegate has reported that the IMS configuration has changed.
239      * @param config The config to be sent to the IMS application.
240      */
241     @Override
onConfigurationChanged(SipDelegateConfiguration config)242     public void onConfigurationChanged(SipDelegateConfiguration config) {
243         logi("onImsConfigurationChanged: Sending new IMS configuration.");
244         try {
245             mAppStateCallback.onConfigurationChanged(config);
246         } catch (RemoteException e) {
247             logw("onImsConfigurationChanged: IMS application is dead: " + e);
248         }
249     }
250 
251     /** Write state about this tracker into the PrintWriter to be included in the dumpsys */
dump(PrintWriter printWriter)252     public void dump(PrintWriter printWriter) {
253         printWriter.println("Last reg state: " + mLastRegState);
254         printWriter.println("Denied tags: " + mDelegateDeniedTags);
255         printWriter.println();
256         printWriter.println("Most recent logs: ");
257         mLocalLog.dump(printWriter);
258     }
259 
overrideRegistrationForDelegateChange( int registerOverrideReason, DelegateRegistrationState state)260     private DelegateRegistrationState overrideRegistrationForDelegateChange(
261             int registerOverrideReason, DelegateRegistrationState state) {
262         Set<String> registeredFeatures = state.getRegisteredFeatureTags();
263         Set<String> registeringFeatures = state.getRegisteringFeatureTags();
264         DelegateRegistrationState.Builder overriddenState = new DelegateRegistrationState.Builder();
265         // keep other deregistering/deregistered tags the same.
266         for (FeatureTagState dereging : state.getDeregisteringFeatureTags()) {
267             overriddenState.addDeregisteringFeatureTag(dereging.getFeatureTag(),
268                     dereging.getState());
269         }
270         for (FeatureTagState dereged : state.getDeregisteredFeatureTags()) {
271             overriddenState.addDeregisteredFeatureTag(dereged.getFeatureTag(),
272                     dereged.getState());
273         }
274         // Override REGISTERING/REGISTERED
275         for (String ft : registeringFeatures) {
276             overriddenState.addDeregisteringFeatureTag(ft, registerOverrideReason);
277         }
278         for (String ft : registeredFeatures) {
279             overriddenState.addDeregisteringFeatureTag(ft, registerOverrideReason);
280         }
281         return overriddenState.build();
282     }
283 
overrideRegistrationForCompatibility( DelegateRegistrationState state)284     private DelegateRegistrationState overrideRegistrationForCompatibility(
285             DelegateRegistrationState state) {
286         Set<String> registeredFeatures = state.getRegisteredFeatureTags();
287         Set<String> registeringFeatures = state.getRegisteringFeatureTags();
288         DelegateRegistrationState.Builder overriddenState = new DelegateRegistrationState.Builder();
289         // keep other registered/deregistering/deregistered tags the same.
290         for (FeatureTagState dereging : state.getDeregisteringFeatureTags()) {
291             overriddenState.addDeregisteringFeatureTag(dereging.getFeatureTag(),
292                     dereging.getState());
293         }
294         for (FeatureTagState dereged : state.getDeregisteredFeatureTags()) {
295             overriddenState.addDeregisteredFeatureTag(dereged.getFeatureTag(),
296                     dereged.getState());
297         }
298         overriddenState.addRegisteredFeatureTags(registeredFeatures);
299 
300         // move the REGISTERING state to the DEREGISTERED state.
301         for (String tag : registeringFeatures) {
302             overriddenState.addDeregisteredFeatureTag(tag,
303                     DelegateRegistrationState.DEREGISTERED_REASON_NOT_REGISTERED);
304         }
305 
306         return overriddenState.build();
307     }
308 
309     /**
310      * @param state The RegistrationState reported by the SipDelegate to be sent to the
311      *              IMS application .
312      * @return DEREGISTERING_REASON_PDN_CHANGE instead of DEREGISTERING_REASON_LOSING_PDN
313      * if the SUPPORT_DEREGISTERING_LOSING_PDN_STATE compat key is not enabled for the application
314      * consuming the registration change events.
315      */
overrideDeregisteringStateForCompatibility( DelegateRegistrationState state)316     private DelegateRegistrationState overrideDeregisteringStateForCompatibility(
317             DelegateRegistrationState state) {
318         Set<String> registeredFeatures = state.getRegisteredFeatureTags();
319         Set<String> registeringFeatures = state.getRegisteringFeatureTags();
320         DelegateRegistrationState.Builder overriddenState = new DelegateRegistrationState.Builder();
321 
322         // keep other registered/registering/deregistered tags the same.
323         for (FeatureTagState dereged : state.getDeregisteredFeatureTags()) {
324             overriddenState.addDeregisteredFeatureTag(dereged.getFeatureTag(),
325                     dereged.getState());
326         }
327         overriddenState.addRegisteredFeatureTags(registeredFeatures);
328         overriddenState.addRegisteringFeatureTags(registeringFeatures);
329 
330         // change DEREGISTERING_REASON_LOSING_PDN to DEREGISTERING_REASON_PDN_CHANGE
331         for (FeatureTagState dereging : state.getDeregisteringFeatureTags()) {
332             overriddenState.addDeregisteringFeatureTag(dereging.getFeatureTag(),
333                     getDeregisteringReasonForCompatibility(dereging.getState()));
334         }
335 
336         return overriddenState.build();
337     }
338 
getDeregisteringReasonForCompatibility(int reason)339     private int getDeregisteringReasonForCompatibility(int reason) {
340         if (reason == DelegateRegistrationState.DEREGISTERING_REASON_LOSING_PDN) {
341             reason = DelegateRegistrationState.DEREGISTERING_REASON_PDN_CHANGE;
342         }
343         return reason;
344     }
345 
notifySipDelegateCreated()346     private void notifySipDelegateCreated() {
347         try {
348             mAppStateCallback.onCreated(mLocalDelegateImpl);
349         } catch (RemoteException e) {
350             logw("notifySipDelegateCreated: IMS application is dead: " + e);
351         }
352     }
353 
logi(String log)354     private void logi(String log) {
355         Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
356         mLocalLog.log("[I] " + log);
357     }
logw(String log)358     private void logw(String log) {
359         Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
360         mLocalLog.log("[W] " + log);
361     }
362 }
363