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 com.android.server.telecom.tests; 18 19 import com.android.internal.telecom.IConnectionService; 20 import com.android.internal.telecom.IConnectionServiceAdapter; 21 import com.android.internal.telecom.IVideoProvider; 22 import com.android.internal.telecom.RemoteServiceCallback; 23 24 import junit.framework.TestCase; 25 26 import org.mockito.Mockito; 27 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.net.Uri; 31 import android.os.Bundle; 32 import android.os.IBinder; 33 import android.os.IInterface; 34 import android.os.ParcelFileDescriptor; 35 import android.os.RemoteException; 36 import android.telecom.CallAudioState; 37 import android.telecom.Conference; 38 import android.telecom.Connection; 39 import android.telecom.ConnectionRequest; 40 import android.telecom.ConnectionService; 41 import android.telecom.DisconnectCause; 42 import android.telecom.Log; 43 import android.telecom.Logging.Session; 44 import android.telecom.ParcelableConference; 45 import android.telecom.ParcelableConnection; 46 import android.telecom.PhoneAccountHandle; 47 import android.telecom.StatusHints; 48 import android.telecom.TelecomManager; 49 50 import com.google.android.collect.Lists; 51 52 import java.lang.Override; 53 import java.util.ArrayList; 54 import java.util.HashMap; 55 import java.util.HashSet; 56 import java.util.List; 57 import java.util.Map; 58 import java.util.Set; 59 import java.util.concurrent.CountDownLatch; 60 import java.util.concurrent.TimeUnit; 61 62 /** 63 * Controls a test {@link IConnectionService} as would be provided by a source of connectivity 64 * to the Telecom framework. 65 */ 66 public class ConnectionServiceFixture implements TestFixture<IConnectionService> { 67 static int INVALID_VIDEO_STATE = -1; 68 public CountDownLatch mExtrasLock = new CountDownLatch(1); 69 static int NOT_SPECIFIED = 0; 70 71 /** 72 * Implementation of ConnectionService that performs no-ops for tasks normally meant for 73 * Telephony and reports success back to Telecom 74 */ 75 public class FakeConnectionServiceDelegate extends ConnectionService { 76 int mVideoState = INVALID_VIDEO_STATE; 77 int mCapabilities = NOT_SPECIFIED; 78 int mProperties = NOT_SPECIFIED; 79 FakeConnectionServiceDelegate(Context base)80 public FakeConnectionServiceDelegate(Context base) { 81 attachBaseContext(base); 82 } 83 84 @Override onCreateUnknownConnection( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)85 public Connection onCreateUnknownConnection( 86 PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) { 87 mLatestConnection = new FakeConnection(request.getVideoState(), request.getAddress()); 88 return mLatestConnection; 89 } 90 91 @Override onCreateIncomingConnection( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)92 public Connection onCreateIncomingConnection( 93 PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) { 94 FakeConnection fakeConnection = new FakeConnection( 95 mVideoState == INVALID_VIDEO_STATE ? request.getVideoState() : mVideoState, 96 request.getAddress()); 97 mLatestConnection = fakeConnection; 98 if (mCapabilities != NOT_SPECIFIED) { 99 fakeConnection.setConnectionCapabilities(mCapabilities); 100 } 101 if (mProperties != NOT_SPECIFIED) { 102 fakeConnection.setConnectionProperties(mProperties); 103 } 104 105 return fakeConnection; 106 } 107 108 @Override onCreateOutgoingConnection( PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)109 public Connection onCreateOutgoingConnection( 110 PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) { 111 FakeConnection fakeConnection = new FakeConnection(request.getVideoState(), 112 request.getAddress()); 113 mLatestConnection = fakeConnection; 114 if (mCapabilities != NOT_SPECIFIED) { 115 fakeConnection.setConnectionCapabilities(mCapabilities); 116 } 117 if (mProperties != NOT_SPECIFIED) { 118 fakeConnection.setConnectionProperties(mProperties); 119 } 120 return fakeConnection; 121 } 122 123 @Override onCreateConnectionComplete(Connection connection)124 public void onCreateConnectionComplete(Connection connection) { 125 } 126 127 @Override onConference(Connection cxn1, Connection cxn2)128 public void onConference(Connection cxn1, Connection cxn2) { 129 if (((FakeConnection) cxn1).getIsConferenceCreated()) { 130 // Usually, this is implemented by something in Telephony, which does a bunch of 131 // radio work to conference the two connections together. Here we just short-cut 132 // that and declare them conferenced. 133 Conference fakeConference = new FakeConference(); 134 fakeConference.addConnection(cxn1); 135 fakeConference.addConnection(cxn2); 136 mLatestConference = fakeConference; 137 addConference(fakeConference); 138 } else { 139 try { 140 sendSetConferenceMergeFailed(cxn1.getTelecomCallId()); 141 } catch (Exception e) { 142 Log.w(this, "Exception on sendSetConferenceMergeFailed: " + e.getMessage()); 143 } 144 } 145 } 146 } 147 148 public class FakeConnection extends Connection { 149 // Set to false if you wish the Conference merge to fail. 150 boolean mIsConferenceCreated = true; 151 FakeConnection(int videoState, Uri address)152 public FakeConnection(int videoState, Uri address) { 153 super(); 154 int capabilities = getConnectionCapabilities(); 155 capabilities |= CAPABILITY_MUTE; 156 capabilities |= CAPABILITY_SUPPORT_HOLD; 157 capabilities |= CAPABILITY_HOLD; 158 setVideoState(videoState); 159 setConnectionCapabilities(capabilities); 160 setDialing(); 161 setAddress(address, TelecomManager.PRESENTATION_ALLOWED); 162 } 163 164 @Override onExtrasChanged(Bundle extras)165 public void onExtrasChanged(Bundle extras) { 166 mExtrasLock.countDown(); 167 } 168 getIsConferenceCreated()169 public boolean getIsConferenceCreated() { 170 return mIsConferenceCreated; 171 } 172 setIsConferenceCreated(boolean isConferenceCreated)173 public void setIsConferenceCreated(boolean isConferenceCreated) { 174 mIsConferenceCreated = isConferenceCreated; 175 } 176 } 177 178 public class FakeConference extends Conference { FakeConference()179 public FakeConference() { 180 super(null); 181 setConnectionCapabilities( 182 Connection.CAPABILITY_SUPPORT_HOLD 183 | Connection.CAPABILITY_HOLD 184 | Connection.CAPABILITY_MUTE 185 | Connection.CAPABILITY_MANAGE_CONFERENCE); 186 } 187 188 @Override onMerge(Connection connection)189 public void onMerge(Connection connection) { 190 // Do nothing besides inform the connection that it was merged into this conference. 191 connection.setConference(this); 192 } 193 194 @Override onExtrasChanged(Bundle extras)195 public void onExtrasChanged(Bundle extras) { 196 Log.w(this, "FakeConference onExtrasChanged"); 197 mExtrasLock.countDown(); 198 } 199 } 200 201 public class FakeConnectionService extends IConnectionService.Stub { 202 List<String> rejectedCallIds = Lists.newArrayList(); 203 204 @Override addConnectionServiceAdapter(IConnectionServiceAdapter adapter, Session.Info info)205 public void addConnectionServiceAdapter(IConnectionServiceAdapter adapter, 206 Session.Info info) throws RemoteException { 207 if (!mConnectionServiceAdapters.add(adapter)) { 208 throw new RuntimeException("Adapter already added: " + adapter); 209 } 210 mConnectionServiceDelegateAdapter.addConnectionServiceAdapter(adapter, 211 null /*Session.Info*/); 212 } 213 214 @Override removeConnectionServiceAdapter(IConnectionServiceAdapter adapter, Session.Info info)215 public void removeConnectionServiceAdapter(IConnectionServiceAdapter adapter, 216 Session.Info info) throws RemoteException { 217 if (!mConnectionServiceAdapters.remove(adapter)) { 218 throw new RuntimeException("Adapter never added: " + adapter); 219 } 220 mConnectionServiceDelegateAdapter.removeConnectionServiceAdapter(adapter, 221 null /*Session.Info*/); 222 } 223 224 @Override createConnection(PhoneAccountHandle connectionManagerPhoneAccount, String id, ConnectionRequest request, boolean isIncoming, boolean isUnknown, Session.Info info)225 public void createConnection(PhoneAccountHandle connectionManagerPhoneAccount, 226 String id, ConnectionRequest request, boolean isIncoming, boolean isUnknown, 227 Session.Info info) throws RemoteException { 228 Log.i(ConnectionServiceFixture.this, "createConnection --> " + id); 229 230 if (mConnectionById.containsKey(id)) { 231 throw new RuntimeException("Connection already exists: " + id); 232 } 233 mLatestConnectionId = id; 234 ConnectionInfo c = new ConnectionInfo(); 235 c.connectionManagerPhoneAccount = connectionManagerPhoneAccount; 236 c.id = id; 237 c.request = request; 238 c.isIncoming = isIncoming; 239 c.isUnknown = isUnknown; 240 c.capabilities |= Connection.CAPABILITY_HOLD | Connection.CAPABILITY_SUPPORT_HOLD; 241 c.videoState = request.getVideoState(); 242 c.mockVideoProvider = new MockVideoProvider(); 243 c.videoProvider = c.mockVideoProvider.getInterface(); 244 c.isConferenceCreated = true; 245 mConnectionById.put(id, c); 246 mConnectionServiceDelegateAdapter.createConnection(connectionManagerPhoneAccount, 247 id, request, isIncoming, isUnknown, null /*Session.Info*/); 248 } 249 250 @Override createConnectionComplete(String id, Session.Info info)251 public void createConnectionComplete(String id, Session.Info info) throws RemoteException { 252 mConnectionServiceDelegateAdapter.createConnectionComplete(id, null /*Session.Info*/); 253 } 254 255 @Override createConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, String callId, ConnectionRequest request, boolean isIncoming, Session.Info sessionInfo)256 public void createConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, 257 String callId, ConnectionRequest request, boolean isIncoming, 258 Session.Info sessionInfo) throws RemoteException { 259 Log.i(ConnectionServiceFixture.this, "createConnectionFailed --> " + callId); 260 261 if (mConnectionById.containsKey(callId)) { 262 throw new RuntimeException("Connection already exists: " + callId); 263 } 264 265 // TODO(3p-calls): Implement this. 266 } 267 268 @Override abort(String callId, Session.Info info)269 public void abort(String callId, Session.Info info) throws RemoteException { } 270 271 @Override answerVideo(String callId, int videoState, Session.Info info)272 public void answerVideo(String callId, int videoState, 273 Session.Info info) throws RemoteException { } 274 275 @Override answer(String callId, Session.Info info)276 public void answer(String callId, Session.Info info) throws RemoteException { } 277 278 @Override deflect(String callId, Uri address, Session.Info info)279 public void deflect(String callId, Uri address, Session.Info info) 280 throws RemoteException { } 281 282 @Override reject(String callId, Session.Info info)283 public void reject(String callId, Session.Info info) throws RemoteException { 284 rejectedCallIds.add(callId); 285 } 286 287 @Override rejectWithMessage(String callId, String message, Session.Info info)288 public void rejectWithMessage(String callId, String message, 289 Session.Info info) throws RemoteException { 290 rejectedCallIds.add(callId); 291 } 292 293 @Override disconnect(String callId, Session.Info info)294 public void disconnect(String callId, Session.Info info) throws RemoteException { } 295 296 @Override silence(String callId, Session.Info info)297 public void silence(String callId, Session.Info info) throws RemoteException { } 298 299 @Override hold(String callId, Session.Info info)300 public void hold(String callId, Session.Info info) throws RemoteException { } 301 302 @Override unhold(String callId, Session.Info info)303 public void unhold(String callId, Session.Info info) throws RemoteException { } 304 305 @Override onCallAudioStateChanged(String activeCallId, CallAudioState audioState, Session.Info info)306 public void onCallAudioStateChanged(String activeCallId, CallAudioState audioState, 307 Session.Info info) 308 throws RemoteException { } 309 310 @Override playDtmfTone(String callId, char digit, Session.Info info)311 public void playDtmfTone(String callId, char digit, 312 Session.Info info) throws RemoteException { } 313 314 @Override stopDtmfTone(String callId, Session.Info info)315 public void stopDtmfTone(String callId, Session.Info info) throws RemoteException { } 316 317 @Override conference(String conferenceCallId, String callId, Session.Info info)318 public void conference(String conferenceCallId, String callId, 319 Session.Info info) throws RemoteException { 320 mConnectionServiceDelegateAdapter.conference(conferenceCallId, callId, info); 321 } 322 323 @Override splitFromConference(String callId, Session.Info info)324 public void splitFromConference(String callId, Session.Info info) throws RemoteException { } 325 326 @Override mergeConference(String conferenceCallId, Session.Info info)327 public void mergeConference(String conferenceCallId, 328 Session.Info info) throws RemoteException { } 329 330 @Override swapConference(String conferenceCallId, Session.Info info)331 public void swapConference(String conferenceCallId, 332 Session.Info info) throws RemoteException { } 333 334 @Override onPostDialContinue(String callId, boolean proceed, Session.Info info)335 public void onPostDialContinue(String callId, boolean proceed, 336 Session.Info info) throws RemoteException { } 337 338 @Override pullExternalCall(String callId, Session.Info info)339 public void pullExternalCall(String callId, Session.Info info) throws RemoteException { } 340 341 @Override sendCallEvent(String callId, String event, Bundle extras, Session.Info info)342 public void sendCallEvent(String callId, String event, Bundle extras, 343 Session.Info info) throws RemoteException 344 {} 345 onExtrasChanged(String callId, Bundle extras, Session.Info info)346 public void onExtrasChanged(String callId, Bundle extras, 347 Session.Info info) throws RemoteException { 348 mConnectionServiceDelegateAdapter.onExtrasChanged(callId, extras, info); 349 } 350 351 @Override startRtt(String callId, ParcelFileDescriptor fromInCall, ParcelFileDescriptor toInCall, Session.Info sessionInfo)352 public void startRtt(String callId, ParcelFileDescriptor fromInCall, 353 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException { 354 355 } 356 357 @Override stopRtt(String callId, Session.Info sessionInfo)358 public void stopRtt(String callId, Session.Info sessionInfo) throws RemoteException { 359 360 } 361 362 @Override respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall, ParcelFileDescriptor toInCall, Session.Info sessionInfo)363 public void respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall, 364 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException { 365 366 } 367 368 @Override connectionServiceFocusLost(Session.Info sessionInfo)369 public void connectionServiceFocusLost(Session.Info sessionInfo) throws RemoteException { 370 } 371 372 @Override connectionServiceFocusGained(Session.Info sessionInfo)373 public void connectionServiceFocusGained(Session.Info sessionInfo) throws RemoteException { 374 } 375 376 @Override asBinder()377 public IBinder asBinder() { 378 return this; 379 } 380 381 @Override queryLocalInterface(String descriptor)382 public IInterface queryLocalInterface(String descriptor) { 383 return this; 384 } 385 386 @Override handoverFailed(String callId, ConnectionRequest request, int error, Session.Info sessionInfo)387 public void handoverFailed(String callId, ConnectionRequest request, 388 int error, Session.Info sessionInfo) {} 389 390 @Override handoverComplete(String callId, Session.Info sessionInfo)391 public void handoverComplete(String callId, Session.Info sessionInfo) {} 392 } 393 394 FakeConnectionServiceDelegate mConnectionServiceDelegate; 395 private IConnectionService mConnectionServiceDelegateAdapter; 396 397 FakeConnectionService mConnectionService = new FakeConnectionService(); 398 private IConnectionService.Stub mConnectionServiceSpy = Mockito.spy(mConnectionService); 399 400 public class ConnectionInfo { 401 PhoneAccountHandle connectionManagerPhoneAccount; 402 String id; 403 boolean ringing; 404 ConnectionRequest request; 405 boolean isIncoming; 406 boolean isUnknown; 407 int state; 408 int addressPresentation; 409 int capabilities; 410 int properties; 411 int supportedAudioRoutes; 412 StatusHints statusHints; 413 DisconnectCause disconnectCause; 414 String conferenceId; 415 String callerDisplayName; 416 int callerDisplayNamePresentation; 417 final List<String> conferenceableConnectionIds = new ArrayList<>(); 418 IVideoProvider videoProvider; 419 Connection.VideoProvider videoProviderImpl; 420 MockVideoProvider mockVideoProvider; 421 int videoState; 422 boolean isVoipAudioMode; 423 Bundle extras; 424 boolean isConferenceCreated; 425 } 426 427 public class ConferenceInfo { 428 PhoneAccountHandle phoneAccount; 429 int state; 430 int capabilities; 431 int properties; 432 final List<String> connectionIds = new ArrayList<>(); 433 IVideoProvider videoProvider; 434 int videoState; 435 long connectTimeMillis; 436 long connectElapsedTimeMillis; 437 StatusHints statusHints; 438 Bundle extras; 439 } 440 441 public String mLatestConnectionId; 442 public Connection mLatestConnection; 443 public Conference mLatestConference; 444 public final Set<IConnectionServiceAdapter> mConnectionServiceAdapters = new HashSet<>(); 445 public final Map<String, ConnectionInfo> mConnectionById = new HashMap<>(); 446 public final Map<String, ConferenceInfo> mConferenceById = new HashMap<>(); 447 public final List<ComponentName> mRemoteConnectionServiceNames = new ArrayList<>(); 448 public final List<IBinder> mRemoteConnectionServices = new ArrayList<>(); 449 ConnectionServiceFixture(Context context)450 public ConnectionServiceFixture(Context context) throws Exception { 451 mConnectionServiceDelegate = new FakeConnectionServiceDelegate(context); 452 mConnectionServiceDelegateAdapter = IConnectionService.Stub.asInterface( 453 mConnectionServiceDelegate.onBind(null)); 454 } 455 456 @Override getTestDouble()457 public IConnectionService getTestDouble() { 458 return mConnectionServiceSpy; 459 } 460 sendHandleCreateConnectionComplete(String id)461 public void sendHandleCreateConnectionComplete(String id) throws Exception { 462 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 463 a.handleCreateConnectionComplete( 464 id, 465 mConnectionById.get(id).request, 466 parcelable(mConnectionById.get(id)), null /*Session.Info*/); 467 } 468 } 469 sendSetActive(String id)470 public void sendSetActive(String id) throws Exception { 471 mConnectionById.get(id).state = Connection.STATE_ACTIVE; 472 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 473 a.setActive(id, null /*Session.Info*/); 474 } 475 } 476 sendSetRinging(String id)477 public void sendSetRinging(String id) throws Exception { 478 mConnectionById.get(id).state = Connection.STATE_RINGING; 479 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 480 a.setRinging(id, null /*Session.Info*/); 481 } 482 } 483 sendSetDialing(String id)484 public void sendSetDialing(String id) throws Exception { 485 mConnectionById.get(id).state = Connection.STATE_DIALING; 486 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 487 a.setDialing(id, null /*Session.Info*/); 488 } 489 } 490 sendSetDisconnected(String id, int disconnectCause)491 public void sendSetDisconnected(String id, int disconnectCause) throws Exception { 492 mConnectionById.get(id).state = Connection.STATE_DISCONNECTED; 493 mConnectionById.get(id).disconnectCause = new DisconnectCause(disconnectCause); 494 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 495 a.setDisconnected(id, mConnectionById.get(id).disconnectCause, null /*Session.Info*/); 496 } 497 } 498 sendSetOnHold(String id)499 public void sendSetOnHold(String id) throws Exception { 500 mConnectionById.get(id).state = Connection.STATE_HOLDING; 501 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 502 a.setOnHold(id, null /*Session.Info*/); 503 } 504 } 505 sendSetRingbackRequested(String id)506 public void sendSetRingbackRequested(String id) throws Exception { 507 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 508 a.setRingbackRequested(id, mConnectionById.get(id).ringing, null /*Session.Info*/); 509 } 510 } 511 sendSetConnectionCapabilities(String id)512 public void sendSetConnectionCapabilities(String id) throws Exception { 513 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 514 a.setConnectionCapabilities(id, mConnectionById.get(id).capabilities, 515 null /*Session.Info*/); 516 } 517 } 518 sendSetConnectionProperties(String id)519 public void sendSetConnectionProperties(String id) throws Exception { 520 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 521 a.setConnectionProperties(id, mConnectionById.get(id).properties, null /*Session.Info*/); 522 } 523 } sendSetIsConferenced(String id)524 public void sendSetIsConferenced(String id) throws Exception { 525 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 526 a.setIsConferenced(id, mConnectionById.get(id).conferenceId, null /*Session.Info*/); 527 } 528 } 529 sendAddConferenceCall(String id)530 public void sendAddConferenceCall(String id) throws Exception { 531 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 532 a.addConferenceCall(id, parcelable(mConferenceById.get(id)), null /*Session.Info*/); 533 } 534 } 535 sendRemoveCall(String id)536 public void sendRemoveCall(String id) throws Exception { 537 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 538 a.removeCall(id, null /*Session.Info*/); 539 } 540 } 541 sendOnPostDialWait(String id, String remaining)542 public void sendOnPostDialWait(String id, String remaining) throws Exception { 543 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 544 a.onPostDialWait(id, remaining, null /*Session.Info*/); 545 } 546 } 547 sendOnPostDialChar(String id, char nextChar)548 public void sendOnPostDialChar(String id, char nextChar) throws Exception { 549 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 550 a.onPostDialChar(id, nextChar, null /*Session.Info*/); 551 } 552 } 553 sendQueryRemoteConnectionServices()554 public void sendQueryRemoteConnectionServices() throws Exception { 555 mRemoteConnectionServices.clear(); 556 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 557 a.queryRemoteConnectionServices(new RemoteServiceCallback.Stub() { 558 @Override 559 public void onError() throws RemoteException { 560 throw new RuntimeException(); 561 } 562 563 @Override 564 public void onResult( 565 List<ComponentName> names, 566 List<IBinder> services) 567 throws RemoteException { 568 TestCase.assertEquals(names.size(), services.size()); 569 mRemoteConnectionServiceNames.addAll(names); 570 mRemoteConnectionServices.addAll(services); 571 } 572 573 @Override 574 public IBinder asBinder() { 575 return this; 576 } 577 }, "" /* callingPackage */, null /*Session.Info*/); 578 } 579 } 580 sendSetVideoProvider(String id)581 public void sendSetVideoProvider(String id) throws Exception { 582 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 583 a.setVideoProvider(id, mConnectionById.get(id).videoProvider, null /*Session.Info*/); 584 } 585 } 586 sendSetVideoState(String id)587 public void sendSetVideoState(String id) throws Exception { 588 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 589 a.setVideoState(id, mConnectionById.get(id).videoState, null /*Session.Info*/); 590 } 591 } 592 sendSetIsVoipAudioMode(String id)593 public void sendSetIsVoipAudioMode(String id) throws Exception { 594 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 595 a.setIsVoipAudioMode(id, mConnectionById.get(id).isVoipAudioMode, 596 null /*Session.Info*/); 597 } 598 } 599 sendSetStatusHints(String id)600 public void sendSetStatusHints(String id) throws Exception { 601 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 602 a.setStatusHints(id, mConnectionById.get(id).statusHints, null /*Session.Info*/); 603 } 604 } 605 sendSetAddress(String id)606 public void sendSetAddress(String id) throws Exception { 607 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 608 a.setAddress( 609 id, 610 mConnectionById.get(id).request.getAddress(), 611 mConnectionById.get(id).addressPresentation, null /*Session.Info*/); 612 } 613 } 614 sendSetCallerDisplayName(String id)615 public void sendSetCallerDisplayName(String id) throws Exception { 616 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 617 a.setCallerDisplayName( 618 id, 619 mConnectionById.get(id).callerDisplayName, 620 mConnectionById.get(id).callerDisplayNamePresentation, null /*Session.Info*/); 621 } 622 } 623 sendSetConferenceableConnections(String id)624 public void sendSetConferenceableConnections(String id) throws Exception { 625 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 626 a.setConferenceableConnections(id, mConnectionById.get(id).conferenceableConnectionIds, 627 null /*Session.Info*/); 628 } 629 } 630 sendAddExistingConnection(String id)631 public void sendAddExistingConnection(String id) throws Exception { 632 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 633 a.addExistingConnection(id, parcelable(mConnectionById.get(id)), null /*Session.Info*/); 634 } 635 } 636 sendConnectionEvent(String id, String event, Bundle extras)637 public void sendConnectionEvent(String id, String event, Bundle extras) throws Exception { 638 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 639 a.onConnectionEvent(id, event, extras, null /*Session.Info*/); 640 } 641 } 642 sendSetConferenceMergeFailed(String id)643 public void sendSetConferenceMergeFailed(String id) throws Exception { 644 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 645 a.setConferenceMergeFailed(id, null /*Session.Info*/); 646 } 647 } 648 649 /** 650 * Waits until the {@link Connection#onExtrasChanged(Bundle)} API has been called on a 651 * {@link Connection} or {@link Conference}. 652 */ waitForExtras()653 public void waitForExtras() { 654 try { 655 mExtrasLock.await(TelecomSystemTest.TEST_TIMEOUT, TimeUnit.MILLISECONDS); 656 } catch (InterruptedException ie) { 657 } 658 mExtrasLock = new CountDownLatch(1); 659 } 660 parcelable(ConferenceInfo c)661 private ParcelableConference parcelable(ConferenceInfo c) { 662 return new ParcelableConference( 663 c.phoneAccount, 664 c.state, 665 c.capabilities, 666 c.properties, 667 c.connectionIds, 668 c.videoProvider, 669 c.videoState, 670 c.connectTimeMillis, 671 c.connectElapsedTimeMillis, 672 c.statusHints, 673 c.extras, 674 null, 675 0, 676 null, 677 0); 678 } 679 parcelable(ConnectionInfo c)680 private ParcelableConnection parcelable(ConnectionInfo c) { 681 return new ParcelableConnection( 682 c.request.getAccountHandle(), 683 c.state, 684 c.capabilities, 685 c.properties, 686 c.supportedAudioRoutes, 687 c.request.getAddress(), 688 c.addressPresentation, 689 c.callerDisplayName, 690 c.callerDisplayNamePresentation, 691 c.videoProvider, 692 c.videoState, 693 false, /* ringback requested */ 694 false, /* voip audio mode */ 695 0, /* Connect Time for conf call on this connection */ 696 0, /* Connect Real Time comes from conference call */ 697 c.statusHints, 698 c.disconnectCause, 699 c.conferenceableConnectionIds, 700 c.extras); 701 } 702 } 703