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