• 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.os.Binder;
20 import android.os.IBinder;
21 import android.os.RemoteException;
22 import android.telephony.ims.DelegateRegistrationState;
23 import android.telephony.ims.DelegateRequest;
24 import android.telephony.ims.FeatureTagState;
25 import android.telephony.ims.SipDelegateConfiguration;
26 import android.telephony.ims.SipDelegateImsConfiguration;
27 import android.telephony.ims.SipDelegateManager;
28 import android.telephony.ims.aidl.IImsRegistration;
29 import android.telephony.ims.aidl.ISipDelegate;
30 import android.telephony.ims.aidl.ISipDelegateMessageCallback;
31 import android.telephony.ims.aidl.ISipDelegateStateCallback;
32 import android.telephony.ims.aidl.ISipTransport;
33 import android.telephony.ims.stub.SipDelegate;
34 import android.util.LocalLog;
35 import android.util.Log;
36 
37 import java.io.PrintWriter;
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.NoSuchElementException;
41 import java.util.Set;
42 import java.util.concurrent.Executor;
43 import java.util.function.BiConsumer;
44 import java.util.function.Consumer;
45 
46 /**
47  * Container for the active connection to the {@link SipDelegate} active on the ImsService.
48  * <p>
49  * New instances of this class will be created and destroyed new {@link SipDelegate}s are created
50  * and destroyed by the {@link SipDelegateController}.
51  */
52 public class SipDelegateBinderConnection implements DelegateBinderStateManager,
53         IBinder.DeathRecipient {
54     private static final String LOG_TAG = "BinderConn";
55 
56     protected final int mSubId;
57     protected final Set<FeatureTagState> mDeniedTags;
58     protected final Executor mExecutor;
59     protected final List<StateCallback> mStateCallbacks;
60 
61     private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
62 
63     // Callback interface from ImsService to this Connection. State Events will be forwarded to IMS
64     // application through DelegateStateTracker.
65     private final ISipDelegateStateCallback mSipDelegateStateCallback =
66             new ISipDelegateStateCallback.Stub() {
67                 @Override
68                 public void onCreated(ISipDelegate delegate,
69                         List<FeatureTagState> deniedFeatureTags) {
70                     long token = Binder.clearCallingIdentity();
71                     try {
72                         mExecutor.execute(() ->
73                                 notifySipDelegateCreated(delegate, deniedFeatureTags));
74                     } finally {
75                         Binder.restoreCallingIdentity(token);
76                     }
77                 }
78 
79                 @Override
80                 public void onFeatureTagRegistrationChanged(
81                         DelegateRegistrationState registrationState) {
82                     long token = Binder.clearCallingIdentity();
83                     try {
84                         mExecutor.execute(() -> {
85                             logi("onFeatureTagRegistrationChanged:" + registrationState);
86                             for (StateCallback c : mStateCallbacks) {
87                                 c.onRegistrationStateChanged(registrationState);
88                             }
89                         });
90                     } finally {
91                         Binder.restoreCallingIdentity(token);
92                     }
93                 }
94 
95                 @Override
96                 public void onImsConfigurationChanged(
97                         SipDelegateImsConfiguration registeredSipConfig) {
98                     long token = Binder.clearCallingIdentity();
99                     try {
100                         mExecutor.execute(() -> {
101                             logi("onImsConfigurationChanged: version="
102                                     + registeredSipConfig.getVersion());
103                             for (StateCallback c : mStateCallbacks) {
104                                 c.onImsConfigurationChanged(registeredSipConfig);
105                             }
106                         });
107                     } finally {
108                         Binder.restoreCallingIdentity(token);
109                     }
110                 }
111 
112                 @Override
113                 public void onConfigurationChanged(
114                         SipDelegateConfiguration registeredSipConfig) {
115                     long token = Binder.clearCallingIdentity();
116                     try {
117                         mExecutor.execute(() -> {
118                             logi("onConfigurationChanged");
119                             for (StateCallback c : mStateCallbacks) {
120                                 c.onConfigurationChanged(registeredSipConfig);
121                             }
122                         });
123                     } finally {
124                         Binder.restoreCallingIdentity(token);
125                     }
126                 }
127 
128                 @Override
129                 public void onDestroyed(int reason) {
130                     long token = Binder.clearCallingIdentity();
131                     try {
132                         mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
133                     } finally {
134                         Binder.restoreCallingIdentity(token);
135                     }
136                 }
137             };
138 
139     private final ISipTransport mSipTransport;
140     private final IImsRegistration mImsRegistration;
141     private final DelegateRequest mRequestedConfig;
142 
143     private ISipDelegate mDelegateBinder;
144     private BiConsumer<ISipDelegate, Set<FeatureTagState>> mPendingCreatedConsumer;
145     private Consumer<Integer> mPendingDestroyedConsumer;
146 
147     /**
148      * Create a new Connection object to manage the creation and destruction of a
149      * {@link SipDelegate}.
150      * @param subId The subid that this SipDelegate is being created for.
151      * @param sipTransport The SipTransport implementation that will be used to manage SipDelegates.
152      * @param registrationImpl The ImsRegistration implementation that will be used to manage
153      *                         registration changes in relation to the SipDelegates.
154      * @param requestedConfig The DelegateRequest to be sent to the ImsService.
155      * @param transportDeniedTags The feature tags that have already been denied by the
156      *                            SipTransportController and should not be requested.
157      * @param executor The Executor that all binder calls from the remote process will be executed
158      *                on.
159      * @param stateCallbacks A list of callbacks that will each be called when the state of the
160      *                       SipDelegate changes. This will be called on the supplied executor.
161      */
SipDelegateBinderConnection(int subId, ISipTransport sipTransport, IImsRegistration registrationImpl, DelegateRequest requestedConfig, Set<FeatureTagState> transportDeniedTags, Executor executor, List<StateCallback> stateCallbacks)162     public SipDelegateBinderConnection(int subId, ISipTransport sipTransport,
163             IImsRegistration registrationImpl, DelegateRequest requestedConfig,
164             Set<FeatureTagState> transportDeniedTags, Executor executor,
165             List<StateCallback> stateCallbacks) {
166         mSubId = subId;
167         mSipTransport = sipTransport;
168         mImsRegistration = registrationImpl;
169         mRequestedConfig = requestedConfig;
170         mDeniedTags = transportDeniedTags;
171         mExecutor = executor;
172         mStateCallbacks = stateCallbacks;
173     }
174 
175     @Override
create(ISipDelegateMessageCallback cb, BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer)176     public boolean create(ISipDelegateMessageCallback cb,
177             BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer) {
178         try {
179             mSipTransport.createSipDelegate(mSubId, mRequestedConfig, mSipDelegateStateCallback,
180                     cb);
181             mSipTransport.asBinder().linkToDeath(this, 0);
182         } catch (RemoteException e) {
183             logw("create called on unreachable SipTransport:" + e);
184             return false;
185         }
186         mPendingCreatedConsumer = createdConsumer;
187         return true;
188     }
189 
190     @Override
destroy(int reason, Consumer<Integer> destroyedConsumer)191     public void destroy(int reason, Consumer<Integer> destroyedConsumer) {
192         mPendingDestroyedConsumer = destroyedConsumer;
193         try {
194             if (mDelegateBinder != null) {
195                 mSipTransport.destroySipDelegate(mDelegateBinder, reason);
196             } else {
197                 mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
198             }
199             mStateCallbacks.clear();
200         } catch (RemoteException e) {
201             logw("destroy called on unreachable SipTransport:" + e);
202             mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
203         }
204         try {
205             mSipTransport.asBinder().unlinkToDeath(this, 0);
206         } catch (NoSuchElementException e) {
207             logw("unlinkToDeath called on already unlinked binder" + e);
208         }
209     }
210 
211     @Override
triggerFullNetworkRegistration(int sipCode, String sipReason)212     public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
213         try {
214             mImsRegistration.triggerFullNetworkRegistration(sipCode, sipReason);
215         } catch (RemoteException e) {
216             logw("triggerFullNetworkRegistration called on unreachable ImsRegistration:" + e);
217         }
218     }
219 
notifySipDelegateCreated(ISipDelegate delegate, List<FeatureTagState> deniedFeatureTags)220     private void notifySipDelegateCreated(ISipDelegate delegate,
221             List<FeatureTagState> deniedFeatureTags) {
222         logi("Delegate Created: " + delegate + ", deniedTags:" + deniedFeatureTags);
223         if (delegate == null) {
224             logw("Invalid null delegate returned!");
225         }
226         mDelegateBinder = delegate;
227         // Add denied feature tags from SipDelegate to the ones denied by the transport
228         if (deniedFeatureTags != null) {
229             mDeniedTags.addAll(deniedFeatureTags);
230         }
231         if (mPendingCreatedConsumer == null) return;
232         mPendingCreatedConsumer.accept(delegate, mDeniedTags);
233         mPendingCreatedConsumer = null;
234     }
235 
notifySipDelegateDestroyed(int reason)236     private void notifySipDelegateDestroyed(int reason) {
237         logi("Delegate Destroyed, reason: " + reason);
238         mDelegateBinder = null;
239         if (mPendingDestroyedConsumer == null) return;
240         mPendingDestroyedConsumer.accept(reason);
241         mPendingDestroyedConsumer = null;
242     }
243 
244     /** Dump state about this binder connection that should be included in the dumpsys. */
dump(PrintWriter printWriter)245     public void dump(PrintWriter printWriter) {
246         mLocalLog.dump(printWriter);
247     }
248 
logi(String log)249     protected final void logi(String log) {
250         Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
251         mLocalLog.log("[I] " + log);
252     }
253 
logw(String log)254     protected final void logw(String log) {
255         Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
256         mLocalLog.log("[W] " + log);
257     }
258 
259     @Override
binderDied()260     public void binderDied() {
261         mExecutor.execute(() -> {
262             logw("binderDied!");
263             // Unblock any pending create/destroy operations.
264             // SipTransportController will handle the overall destruction/teardown.
265             notifySipDelegateCreated(null, Collections.emptyList());
266             notifySipDelegateDestroyed(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
267         });
268     }
269 }
270