1 /*
2  * Copyright (C) 2015 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.telecom.cts;
18 
19 import static android.telecom.CallAudioState.*;
20 
21 import android.net.Uri;
22 import android.os.Bundle;
23 import android.telecom.CallAudioState;
24 import android.telecom.CallScreeningService;
25 import android.telecom.Connection;
26 import android.telecom.DisconnectCause;
27 import android.telecom.PhoneAccountHandle;
28 import android.telecom.RemoteConnection;
29 import android.telecom.VideoProfile;
30 import android.telecom.cts.TestUtils.InvokeCounter;
31 import android.util.SparseArray;
32 
33 import java.util.List;
34 
35 /**
36  * {@link Connection} subclass that immediately performs any state changes that are a result of
37  * callbacks sent from Telecom.
38  */
39 public class MockConnection extends Connection {
40     public static final int ON_POST_DIAL_WAIT = 1;
41     public static final int ON_CALL_EVENT = 2;
42     public static final int ON_PULL_EXTERNAL_CALL = 3;
43     public static final int ON_EXTRAS_CHANGED = 4;
44     public static final int ON_START_RTT = 5;
45     public static final int ON_RTT_REQUEST_RESPONSE = 6;
46     public static final int ON_STOP_RTT = 7;
47     public static final int ON_DEFLECT = 8;
48     public static final int ON_SILENCE = 9;
49     public static final int ON_ADD_CONFERENCE_PARTICIPANTS = 10;
50     public static final int ON_CALL_FILTERING_COMPLETED = 11;
51     public static final int ON_ANSWER_CALLED = 12;
52     public static final int ON_ANSWER_VIDEO_CALLED = 13;
53 
54     private CallAudioState mCallAudioState =
55             new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, ROUTE_EARPIECE | ROUTE_SPEAKER);
56     private int mState = STATE_NEW;
57     public int videoState = VideoProfile.STATE_AUDIO_ONLY;
58     private String mDtmfString = "";
59     private MockVideoProvider mMockVideoProvider;
60     private PhoneAccountHandle mPhoneAccountHandle;
61     private RemoteConnection mRemoteConnection = null;
62     private RttTextStream mRttTextStream;
63     private boolean mAutoDestroy = true;
64 
65     private SparseArray<InvokeCounter> mInvokeCounterMap = new SparseArray<>(13);
66 
67     @Override
onAnswer()68     public void onAnswer() {
69         super.onAnswer();
70         if (mInvokeCounterMap.get(ON_ANSWER_CALLED) != null) {
71             mInvokeCounterMap.get(ON_ANSWER_CALLED).invoke();
72         }
73     }
74 
75     @Override
onAnswer(int videoState)76     public void onAnswer(int videoState) {
77         super.onAnswer(videoState);
78         this.videoState = videoState;
79         setActive();
80         if (mRemoteConnection != null) {
81             mRemoteConnection.answer();
82         }
83         if (mInvokeCounterMap.get(ON_ANSWER_VIDEO_CALLED) != null) {
84             mInvokeCounterMap.get(ON_ANSWER_VIDEO_CALLED).invoke(videoState);
85         }
86     }
87 
88     @Override
onReject()89     public void onReject() {
90         super.onReject();
91         setDisconnected(new DisconnectCause(DisconnectCause.REJECTED));
92         if (mRemoteConnection != null) {
93             mRemoteConnection.reject();
94         }
95         if (mAutoDestroy) destroy();
96     }
97 
98     @Override
onReject(int rejectReason)99     public void onReject(int rejectReason) {
100         super.onReject(rejectReason);
101         setDisconnected(new DisconnectCause(DisconnectCause.REJECTED,
102                 Integer.toString(rejectReason)));
103         if (mAutoDestroy) destroy();
104     }
105 
106     @Override
onReject(String reason)107     public void onReject(String reason) {
108         super.onReject();
109         setDisconnected(new DisconnectCause(DisconnectCause.REJECTED, reason));
110         if (mRemoteConnection != null) {
111             mRemoteConnection.reject();
112         }
113         if (mAutoDestroy) destroy();
114     }
115 
116     @Override
onHold()117     public void onHold() {
118         super.onHold();
119         setOnHold();
120         if (mRemoteConnection != null) {
121             mRemoteConnection.hold();
122         }
123     }
124 
125     @Override
onUnhold()126     public void onUnhold() {
127         super.onUnhold();
128         setActive();
129         if (mRemoteConnection != null) {
130             mRemoteConnection.unhold();
131         }
132     }
133 
134     @Override
onDisconnect()135     public void onDisconnect() {
136         super.onDisconnect();
137         setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
138         if (mRemoteConnection != null) {
139             mRemoteConnection.disconnect();
140         }
141         if (mAutoDestroy) destroy();
142     }
143 
144     @Override
onAbort()145     public void onAbort() {
146         super.onAbort();
147         setDisconnected(new DisconnectCause(DisconnectCause.UNKNOWN));
148         if (mRemoteConnection != null) {
149             mRemoteConnection.abort();
150         }
151         if (mAutoDestroy) destroy();
152     }
153 
154     @Override
onPlayDtmfTone(char c)155     public void onPlayDtmfTone(char c) {
156         super.onPlayDtmfTone(c);
157         mDtmfString += c;
158         if (mRemoteConnection != null) {
159             mRemoteConnection.playDtmfTone(c);
160         }
161     }
162 
163     @Override
onStopDtmfTone()164     public void onStopDtmfTone() {
165         super.onStopDtmfTone();
166         mDtmfString += ".";
167         if (mRemoteConnection != null) {
168             mRemoteConnection.stopDtmfTone();
169         }
170     }
171 
172     @Override
onCallAudioStateChanged(CallAudioState state)173     public void onCallAudioStateChanged(CallAudioState state) {
174         super.onCallAudioStateChanged(state);
175         mCallAudioState = state;
176         if (mRemoteConnection != null) {
177             mRemoteConnection.setCallAudioState(state);
178         }
179     }
180 
181     @Override
onStateChanged(int state)182     public void onStateChanged(int state) {
183         super.onStateChanged(state);
184         mState = state;
185     }
186 
187     @Override
onPostDialContinue(boolean proceed)188     public void onPostDialContinue(boolean proceed) {
189         super.onPostDialContinue(proceed);
190         if (mInvokeCounterMap.get(ON_POST_DIAL_WAIT) != null) {
191             mInvokeCounterMap.get(ON_POST_DIAL_WAIT).invoke(proceed);
192         }
193     }
194 
195     @Override
onCallEvent(String event, Bundle extras)196     public void onCallEvent(String event, Bundle extras) {
197         super.onCallEvent(event, extras);
198         if (mInvokeCounterMap.get(ON_CALL_EVENT) != null) {
199             mInvokeCounterMap.get(ON_CALL_EVENT).invoke(event, extras);
200         }
201     }
202 
203     @Override
onPullExternalCall()204     public void onPullExternalCall() {
205         super.onPullExternalCall();
206         if (mInvokeCounterMap.get(ON_PULL_EXTERNAL_CALL) != null) {
207             mInvokeCounterMap.get(ON_PULL_EXTERNAL_CALL).invoke();
208         }
209     }
210 
211     @Override
onAddConferenceParticipants(List<Uri> participants)212     public void onAddConferenceParticipants(List<Uri> participants) {
213         super.onAddConferenceParticipants(participants);
214         if (mInvokeCounterMap.get(ON_ADD_CONFERENCE_PARTICIPANTS) != null) {
215             mInvokeCounterMap.get(ON_ADD_CONFERENCE_PARTICIPANTS).invoke(participants);
216         }
217     }
218 
219     @Override
onExtrasChanged(Bundle extras)220     public void onExtrasChanged(Bundle extras) {
221         super.onExtrasChanged(extras);
222         if (mInvokeCounterMap.get(ON_EXTRAS_CHANGED) != null) {
223             mInvokeCounterMap.get(ON_EXTRAS_CHANGED).invoke(extras);
224         }
225     }
226 
227     @Override
onStartRtt(RttTextStream rttTextStream)228     public void onStartRtt(RttTextStream rttTextStream) {
229         super.onStartRtt(rttTextStream);
230         if (mInvokeCounterMap.get(ON_START_RTT) != null) {
231             mInvokeCounterMap.get(ON_START_RTT).invoke(rttTextStream);
232         }
233     }
234 
235     @Override
handleRttUpgradeResponse(RttTextStream rttTextStream)236     public void handleRttUpgradeResponse(RttTextStream rttTextStream) {
237         super.handleRttUpgradeResponse(rttTextStream);
238         if (rttTextStream != null) {
239             setRttTextStream(rttTextStream);
240             setConnectionProperties(getConnectionProperties() | PROPERTY_IS_RTT);
241         }
242 
243         if (mInvokeCounterMap.get(ON_RTT_REQUEST_RESPONSE) != null) {
244             mInvokeCounterMap.get(ON_RTT_REQUEST_RESPONSE).invoke(rttTextStream);
245         }
246     }
247 
248     @Override
onStopRtt()249     public void onStopRtt() {
250         super.onStopRtt();
251 
252         if (mInvokeCounterMap.get(ON_STOP_RTT) != null) {
253             mInvokeCounterMap.get(ON_STOP_RTT).invoke();
254         }
255     }
256 
257     @Override
onDeflect(Uri address)258     public void onDeflect(Uri address) {
259         if (mInvokeCounterMap.get(ON_DEFLECT) != null) {
260             mInvokeCounterMap.get(ON_DEFLECT).invoke(address);
261         }
262     }
263 
264     @Override
onSilence()265     public void onSilence() {
266         super.onSilence();
267 
268         if (mInvokeCounterMap.get(ON_SILENCE) != null) {
269             mInvokeCounterMap.get(ON_SILENCE).invoke();
270         }
271     }
272 
273     @Override
onCallFilteringCompleted( Connection.CallFilteringCompletionInfo callFilteringCompletionInfo)274     public void onCallFilteringCompleted(
275             Connection.CallFilteringCompletionInfo callFilteringCompletionInfo) {
276         getInvokeCounter(ON_CALL_FILTERING_COMPLETED).invoke(callFilteringCompletionInfo);
277 
278         if (mRemoteConnection != null) {
279             mRemoteConnection.onCallFilteringCompleted(callFilteringCompletionInfo);
280         }
281     }
282 
283     /**
284      * Do not destroy after setting disconnected for cases that need finer state control. If
285      * disabled the caller will need to call destroy manually.
286      */
disableAutoDestroy()287     public void disableAutoDestroy() {
288         mAutoDestroy = false;
289     }
290 
getCurrentState()291     public int getCurrentState()  {
292         return mState;
293     }
294 
getCurrentCallAudioState()295     public CallAudioState getCurrentCallAudioState() {
296         return mCallAudioState;
297     }
298 
getDtmfString()299     public String getDtmfString() {
300         return mDtmfString;
301     }
302 
getInvokeCounter(int counterIndex)303     public InvokeCounter getInvokeCounter(int counterIndex) {
304         if (mInvokeCounterMap.get(counterIndex) == null) {
305             mInvokeCounterMap.put(counterIndex,
306                     new InvokeCounter(getCounterLabel(counterIndex)));
307         }
308         return mInvokeCounterMap.get(counterIndex);
309     }
310 
311     /**
312      * Creates a mock video provider for this connection.
313      */
createMockVideoProvider()314     public void createMockVideoProvider() {
315         final MockVideoProvider mockVideoProvider = new MockVideoProvider(this);
316         mMockVideoProvider = mockVideoProvider;
317         setVideoProvider(mockVideoProvider);
318     }
319 
sendMockVideoQuality(int videoQuality)320     public void sendMockVideoQuality(int videoQuality) {
321         if (mMockVideoProvider == null) {
322             return;
323         }
324         mMockVideoProvider.sendMockVideoQuality(videoQuality);
325     }
326 
sendMockCallSessionEvent(int event)327     public void sendMockCallSessionEvent(int event) {
328         if (mMockVideoProvider == null) {
329             return;
330         }
331         mMockVideoProvider.sendMockCallSessionEvent(event);
332     }
333 
sendMockPeerWidth(int width)334     public void sendMockPeerWidth(int width) {
335         if (mMockVideoProvider == null) {
336             return;
337         }
338         mMockVideoProvider.sendMockPeerWidth(width);
339     }
340 
sendMockSessionModifyRequest(VideoProfile request)341     public void sendMockSessionModifyRequest(VideoProfile request) {
342         if (mMockVideoProvider == null) {
343             return;
344         }
345         mMockVideoProvider.sendMockSessionModifyRequest(request);
346     }
347 
getMockVideoProvider()348     public MockVideoProvider getMockVideoProvider() {
349         return mMockVideoProvider;
350     }
351 
setMockPhoneAccountHandle(PhoneAccountHandle handle)352     public void setMockPhoneAccountHandle(PhoneAccountHandle handle)  {
353         mPhoneAccountHandle = handle;
354     }
355 
getMockPhoneAccountHandle()356     public PhoneAccountHandle getMockPhoneAccountHandle()  {
357         return mPhoneAccountHandle;
358     }
359 
setRemoteConnection(RemoteConnection remoteConnection)360     public void setRemoteConnection(RemoteConnection remoteConnection)  {
361         mRemoteConnection = remoteConnection;
362     }
363 
getRemoteConnection()364     public RemoteConnection getRemoteConnection()  {
365         return mRemoteConnection;
366     }
367 
setRttTextStream(RttTextStream rttTextStream)368     public void setRttTextStream(RttTextStream rttTextStream) {
369         mRttTextStream = rttTextStream;
370     }
371 
getRttTextStream()372     public RttTextStream getRttTextStream() {
373         return mRttTextStream;
374     }
375 
getCounterLabel(int counterIndex)376     private static String getCounterLabel(int counterIndex) {
377         switch (counterIndex) {
378             case ON_POST_DIAL_WAIT:
379                 return "onPostDialWait";
380             case ON_CALL_EVENT:
381                 return "onCallEvent";
382             case ON_PULL_EXTERNAL_CALL:
383                 return "onPullExternalCall";
384             case ON_EXTRAS_CHANGED:
385                 return "onExtrasChanged";
386             case ON_START_RTT:
387                 return "onStartRtt";
388             case ON_RTT_REQUEST_RESPONSE:
389                 return "onRttRequestResponse";
390             case ON_STOP_RTT:
391                 return "onStopRtt";
392             case ON_DEFLECT:
393                 return "onDeflect";
394             case ON_SILENCE:
395                 return "onSilence";
396             case ON_ADD_CONFERENCE_PARTICIPANTS:
397                 return "onAddConferenceParticipants";
398             default:
399                 return "Callback";
400         }
401     }
402 }
403