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 android.telephony.ims.aidl;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Binder;
22 import android.os.RemoteException;
23 import android.telephony.ims.DelegateMessageCallback;
24 import android.telephony.ims.DelegateRegistrationState;
25 import android.telephony.ims.DelegateStateCallback;
26 import android.telephony.ims.FeatureTagState;
27 import android.telephony.ims.SipDelegateConfiguration;
28 import android.telephony.ims.SipDelegateImsConfiguration;
29 import android.telephony.ims.SipDelegateManager;
30 import android.telephony.ims.SipMessage;
31 import android.telephony.ims.stub.SipDelegate;
32 
33 import java.util.ArrayList;
34 import java.util.Set;
35 import java.util.concurrent.Executor;
36 
37 /**
38  * Implementation of callbacks by wrapping the internal AIDL from telephony. Also implements
39  * ISipDelegate internally when {@link DelegateStateCallback#onCreated(SipDelegate, Set)} is called
40  * in order to trampoline events back to telephony.
41  * @hide
42  */
43 public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMessageCallback {
44     private static final String LOG_TAG = "SipDelegateAW";
45 
46     private final ISipDelegate.Stub mDelegateBinder = new ISipDelegate.Stub() {
47         @Override
48         public void sendMessage(SipMessage sipMessage, long configVersion) {
49             SipDelegate d = mDelegate;
50             final long token = Binder.clearCallingIdentity();
51             try {
52                 mExecutor.execute(() -> d.sendMessage(sipMessage, configVersion));
53             } finally {
54                 Binder.restoreCallingIdentity(token);
55             }
56         }
57 
58         @Override
59         public void notifyMessageReceived(String viaTransactionId)  {
60             SipDelegate d = mDelegate;
61             final long token = Binder.clearCallingIdentity();
62             try {
63                 mExecutor.execute(() -> d.notifyMessageReceived(viaTransactionId));
64             } finally {
65                 Binder.restoreCallingIdentity(token);
66             }
67 
68         }
69 
70         @Override
71         public void notifyMessageReceiveError(String viaTransactionId, int reason) {
72             SipDelegate d = mDelegate;
73             final long token = Binder.clearCallingIdentity();
74             try {
75                 mExecutor.execute(() -> d.notifyMessageReceiveError(viaTransactionId, reason));
76             } finally {
77                 Binder.restoreCallingIdentity(token);
78             }
79 
80         }
81 
82         @Override
83         public void cleanupSession(String callId)  {
84             SipDelegate d = mDelegate;
85             final long token = Binder.clearCallingIdentity();
86             try {
87                 mExecutor.execute(() -> d.cleanupSession(callId));
88             } finally {
89                 Binder.restoreCallingIdentity(token);
90             }
91         }
92     };
93 
94     private final ISipDelegateMessageCallback mMessageBinder;
95     private final ISipDelegateStateCallback mStateBinder;
96     private final Executor mExecutor;
97 
98     private volatile SipDelegate mDelegate;
99 
SipDelegateAidlWrapper(Executor executor, ISipDelegateStateCallback stateBinder, ISipDelegateMessageCallback messageBinder)100     public SipDelegateAidlWrapper(Executor executor, ISipDelegateStateCallback stateBinder,
101             ISipDelegateMessageCallback messageBinder) {
102         mExecutor = executor;
103         mStateBinder = stateBinder;
104         mMessageBinder = messageBinder;
105     }
106 
107     @Override
onMessageReceived(SipMessage message)108     public void onMessageReceived(SipMessage message) {
109         try {
110             mMessageBinder.onMessageReceived(message);
111         } catch (RemoteException e) {
112             // BinderDied will be called on SipTransport instance to trigger destruction. Notify
113             // failure message failure locally for now.
114             SipDelegate d = mDelegate;
115             if (d != null) {
116                 notifyLocalMessageFailedToBeReceived(message,
117                         SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
118             }
119         }
120     }
121 
122     @Override
onMessageSent(String viaTransactionId)123     public void onMessageSent(String viaTransactionId) {
124         try {
125             mMessageBinder.onMessageSent(viaTransactionId);
126         } catch (RemoteException e) {
127             // BinderDied will trigger destroySipDelegate, so just ignore this locally.
128         }
129     }
130 
131     @Override
onMessageSendFailure(String viaTransactionId, int reason)132     public void onMessageSendFailure(String viaTransactionId, int reason) {
133         try {
134             mMessageBinder.onMessageSendFailure(viaTransactionId, reason);
135         } catch (RemoteException e) {
136             // BinderDied will trigger destroySipDelegate, so just ignore this locally.
137         }
138     }
139 
140     @Override
onCreated(@onNull SipDelegate delegate, @Nullable Set<FeatureTagState> deniedTags)141     public void onCreated(@NonNull SipDelegate delegate,
142             @Nullable Set<FeatureTagState> deniedTags) {
143         mDelegate = delegate;
144         try {
145             mStateBinder.onCreated(mDelegateBinder, new ArrayList<>(deniedTags));
146         } catch (RemoteException e) {
147             // BinderDied will trigger destroySipDelegate, so just ignore this locally.
148         }
149     }
150 
151     @Override
onFeatureTagRegistrationChanged(DelegateRegistrationState registrationState)152     public void onFeatureTagRegistrationChanged(DelegateRegistrationState registrationState) {
153         try {
154             mStateBinder.onFeatureTagRegistrationChanged(registrationState);
155         } catch (RemoteException e) {
156             // BinderDied will trigger destroySipDelegate, so just ignore this locally.
157         }
158     }
159 
160     @Override
onImsConfigurationChanged(@onNull SipDelegateImsConfiguration config)161     public void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration config) {
162         try {
163             mStateBinder.onImsConfigurationChanged(config);
164         } catch (RemoteException e) {
165             // BinderDied will trigger destroySipDelegate, so just ignore this locally.
166         }
167     }
168 
169     @Override
onConfigurationChanged(@onNull SipDelegateConfiguration config)170     public void onConfigurationChanged(@NonNull SipDelegateConfiguration config) {
171         try {
172             mStateBinder.onConfigurationChanged(config);
173         } catch (RemoteException e) {
174             // BinderDied will trigger destroySipDelegate, so just ignore this locally.
175         }
176     }
177 
178     @Override
onDestroyed(int reasonCode)179     public void onDestroyed(int reasonCode) {
180         mDelegate = null;
181         try {
182             mStateBinder.onDestroyed(reasonCode);
183         } catch (RemoteException e) {
184             // Do not worry about this if the remote side is already dead.
185         }
186     }
187 
getDelegate()188     public SipDelegate getDelegate()  {
189         return mDelegate;
190     }
191 
getDelegateBinder()192     public ISipDelegate getDelegateBinder() {
193         return mDelegateBinder;
194     }
195 
getStateCallbackBinder()196     public ISipDelegateStateCallback getStateCallbackBinder() {
197         return mStateBinder;
198     }
199 
notifyLocalMessageFailedToBeReceived(SipMessage m, int reason)200     private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) {
201         String transactionId = m.getViaBranchParameter();
202         SipDelegate d = mDelegate;
203         if (d != null) {
204             mExecutor.execute(() -> d.notifyMessageReceiveError(transactionId, reason));
205         }
206     }
207 }
208