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