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