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