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