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 291 @Override disconnect(String callId, Session.Info info)292 public void disconnect(String callId, Session.Info info) throws RemoteException { } 293 294 @Override silence(String callId, Session.Info info)295 public void silence(String callId, Session.Info info) throws RemoteException { } 296 297 @Override hold(String callId, Session.Info info)298 public void hold(String callId, Session.Info info) throws RemoteException { } 299 300 @Override unhold(String callId, Session.Info info)301 public void unhold(String callId, Session.Info info) throws RemoteException { } 302 303 @Override onCallAudioStateChanged(String activeCallId, CallAudioState audioState, Session.Info info)304 public void onCallAudioStateChanged(String activeCallId, CallAudioState audioState, 305 Session.Info info) 306 throws RemoteException { } 307 308 @Override playDtmfTone(String callId, char digit, Session.Info info)309 public void playDtmfTone(String callId, char digit, 310 Session.Info info) throws RemoteException { } 311 312 @Override stopDtmfTone(String callId, Session.Info info)313 public void stopDtmfTone(String callId, Session.Info info) throws RemoteException { } 314 315 @Override conference(String conferenceCallId, String callId, Session.Info info)316 public void conference(String conferenceCallId, String callId, 317 Session.Info info) throws RemoteException { 318 mConnectionServiceDelegateAdapter.conference(conferenceCallId, callId, info); 319 } 320 321 @Override splitFromConference(String callId, Session.Info info)322 public void splitFromConference(String callId, Session.Info info) throws RemoteException { } 323 324 @Override mergeConference(String conferenceCallId, Session.Info info)325 public void mergeConference(String conferenceCallId, 326 Session.Info info) throws RemoteException { } 327 328 @Override swapConference(String conferenceCallId, Session.Info info)329 public void swapConference(String conferenceCallId, 330 Session.Info info) throws RemoteException { } 331 332 @Override onPostDialContinue(String callId, boolean proceed, Session.Info info)333 public void onPostDialContinue(String callId, boolean proceed, 334 Session.Info info) throws RemoteException { } 335 336 @Override pullExternalCall(String callId, Session.Info info)337 public void pullExternalCall(String callId, Session.Info info) throws RemoteException { } 338 339 @Override sendCallEvent(String callId, String event, Bundle extras, Session.Info info)340 public void sendCallEvent(String callId, String event, Bundle extras, 341 Session.Info info) throws RemoteException 342 {} 343 onExtrasChanged(String callId, Bundle extras, Session.Info info)344 public void onExtrasChanged(String callId, Bundle extras, 345 Session.Info info) throws RemoteException { 346 mConnectionServiceDelegateAdapter.onExtrasChanged(callId, extras, info); 347 } 348 349 @Override startRtt(String callId, ParcelFileDescriptor fromInCall, ParcelFileDescriptor toInCall, Session.Info sessionInfo)350 public void startRtt(String callId, ParcelFileDescriptor fromInCall, 351 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException { 352 353 } 354 355 @Override stopRtt(String callId, Session.Info sessionInfo)356 public void stopRtt(String callId, Session.Info sessionInfo) throws RemoteException { 357 358 } 359 360 @Override respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall, ParcelFileDescriptor toInCall, Session.Info sessionInfo)361 public void respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall, 362 ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException { 363 364 } 365 366 @Override connectionServiceFocusLost(Session.Info sessionInfo)367 public void connectionServiceFocusLost(Session.Info sessionInfo) throws RemoteException { 368 } 369 370 @Override connectionServiceFocusGained(Session.Info sessionInfo)371 public void connectionServiceFocusGained(Session.Info sessionInfo) throws RemoteException { 372 } 373 374 @Override asBinder()375 public IBinder asBinder() { 376 return this; 377 } 378 379 @Override queryLocalInterface(String descriptor)380 public IInterface queryLocalInterface(String descriptor) { 381 return this; 382 } 383 384 @Override handoverFailed(String callId, ConnectionRequest request, int error, Session.Info sessionInfo)385 public void handoverFailed(String callId, ConnectionRequest request, 386 int error, Session.Info sessionInfo) {} 387 388 @Override handoverComplete(String callId, Session.Info sessionInfo)389 public void handoverComplete(String callId, Session.Info sessionInfo) {} 390 } 391 392 FakeConnectionServiceDelegate mConnectionServiceDelegate; 393 private IConnectionService mConnectionServiceDelegateAdapter; 394 395 FakeConnectionService mConnectionService = new FakeConnectionService(); 396 private IConnectionService.Stub mConnectionServiceSpy = Mockito.spy(mConnectionService); 397 398 public class ConnectionInfo { 399 PhoneAccountHandle connectionManagerPhoneAccount; 400 String id; 401 boolean ringing; 402 ConnectionRequest request; 403 boolean isIncoming; 404 boolean isUnknown; 405 int state; 406 int addressPresentation; 407 int capabilities; 408 int properties; 409 int supportedAudioRoutes; 410 StatusHints statusHints; 411 DisconnectCause disconnectCause; 412 String conferenceId; 413 String callerDisplayName; 414 int callerDisplayNamePresentation; 415 final List<String> conferenceableConnectionIds = new ArrayList<>(); 416 IVideoProvider videoProvider; 417 Connection.VideoProvider videoProviderImpl; 418 MockVideoProvider mockVideoProvider; 419 int videoState; 420 boolean isVoipAudioMode; 421 Bundle extras; 422 boolean isConferenceCreated; 423 } 424 425 public class ConferenceInfo { 426 PhoneAccountHandle phoneAccount; 427 int state; 428 int capabilities; 429 int properties; 430 final List<String> connectionIds = new ArrayList<>(); 431 IVideoProvider videoProvider; 432 int videoState; 433 long connectTimeMillis; 434 long connectElapsedTimeMillis; 435 StatusHints statusHints; 436 Bundle extras; 437 } 438 439 public String mLatestConnectionId; 440 public Connection mLatestConnection; 441 public Conference mLatestConference; 442 public final Set<IConnectionServiceAdapter> mConnectionServiceAdapters = new HashSet<>(); 443 public final Map<String, ConnectionInfo> mConnectionById = new HashMap<>(); 444 public final Map<String, ConferenceInfo> mConferenceById = new HashMap<>(); 445 public final List<ComponentName> mRemoteConnectionServiceNames = new ArrayList<>(); 446 public final List<IBinder> mRemoteConnectionServices = new ArrayList<>(); 447 ConnectionServiceFixture(Context context)448 public ConnectionServiceFixture(Context context) throws Exception { 449 mConnectionServiceDelegate = new FakeConnectionServiceDelegate(context); 450 mConnectionServiceDelegateAdapter = IConnectionService.Stub.asInterface( 451 mConnectionServiceDelegate.onBind(null)); 452 } 453 454 @Override getTestDouble()455 public IConnectionService getTestDouble() { 456 return mConnectionServiceSpy; 457 } 458 sendHandleCreateConnectionComplete(String id)459 public void sendHandleCreateConnectionComplete(String id) throws Exception { 460 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 461 a.handleCreateConnectionComplete( 462 id, 463 mConnectionById.get(id).request, 464 parcelable(mConnectionById.get(id)), null /*Session.Info*/); 465 } 466 } 467 sendSetActive(String id)468 public void sendSetActive(String id) throws Exception { 469 mConnectionById.get(id).state = Connection.STATE_ACTIVE; 470 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 471 a.setActive(id, null /*Session.Info*/); 472 } 473 } 474 sendSetRinging(String id)475 public void sendSetRinging(String id) throws Exception { 476 mConnectionById.get(id).state = Connection.STATE_RINGING; 477 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 478 a.setRinging(id, null /*Session.Info*/); 479 } 480 } 481 sendSetDialing(String id)482 public void sendSetDialing(String id) throws Exception { 483 mConnectionById.get(id).state = Connection.STATE_DIALING; 484 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 485 a.setDialing(id, null /*Session.Info*/); 486 } 487 } 488 sendSetDisconnected(String id, int disconnectCause)489 public void sendSetDisconnected(String id, int disconnectCause) throws Exception { 490 mConnectionById.get(id).state = Connection.STATE_DISCONNECTED; 491 mConnectionById.get(id).disconnectCause = new DisconnectCause(disconnectCause); 492 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 493 a.setDisconnected(id, mConnectionById.get(id).disconnectCause, null /*Session.Info*/); 494 } 495 } 496 sendSetOnHold(String id)497 public void sendSetOnHold(String id) throws Exception { 498 mConnectionById.get(id).state = Connection.STATE_HOLDING; 499 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 500 a.setOnHold(id, null /*Session.Info*/); 501 } 502 } 503 sendSetRingbackRequested(String id)504 public void sendSetRingbackRequested(String id) throws Exception { 505 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 506 a.setRingbackRequested(id, mConnectionById.get(id).ringing, null /*Session.Info*/); 507 } 508 } 509 sendSetConnectionCapabilities(String id)510 public void sendSetConnectionCapabilities(String id) throws Exception { 511 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 512 a.setConnectionCapabilities(id, mConnectionById.get(id).capabilities, 513 null /*Session.Info*/); 514 } 515 } 516 sendSetConnectionProperties(String id)517 public void sendSetConnectionProperties(String id) throws Exception { 518 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 519 a.setConnectionProperties(id, mConnectionById.get(id).properties, null /*Session.Info*/); 520 } 521 } sendSetIsConferenced(String id)522 public void sendSetIsConferenced(String id) throws Exception { 523 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 524 a.setIsConferenced(id, mConnectionById.get(id).conferenceId, null /*Session.Info*/); 525 } 526 } 527 sendAddConferenceCall(String id)528 public void sendAddConferenceCall(String id) throws Exception { 529 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 530 a.addConferenceCall(id, parcelable(mConferenceById.get(id)), null /*Session.Info*/); 531 } 532 } 533 sendRemoveCall(String id)534 public void sendRemoveCall(String id) throws Exception { 535 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 536 a.removeCall(id, null /*Session.Info*/); 537 } 538 } 539 sendOnPostDialWait(String id, String remaining)540 public void sendOnPostDialWait(String id, String remaining) throws Exception { 541 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 542 a.onPostDialWait(id, remaining, null /*Session.Info*/); 543 } 544 } 545 sendOnPostDialChar(String id, char nextChar)546 public void sendOnPostDialChar(String id, char nextChar) throws Exception { 547 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 548 a.onPostDialChar(id, nextChar, null /*Session.Info*/); 549 } 550 } 551 sendQueryRemoteConnectionServices()552 public void sendQueryRemoteConnectionServices() throws Exception { 553 mRemoteConnectionServices.clear(); 554 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 555 a.queryRemoteConnectionServices(new RemoteServiceCallback.Stub() { 556 @Override 557 public void onError() throws RemoteException { 558 throw new RuntimeException(); 559 } 560 561 @Override 562 public void onResult( 563 List<ComponentName> names, 564 List<IBinder> services) 565 throws RemoteException { 566 TestCase.assertEquals(names.size(), services.size()); 567 mRemoteConnectionServiceNames.addAll(names); 568 mRemoteConnectionServices.addAll(services); 569 } 570 571 @Override 572 public IBinder asBinder() { 573 return this; 574 } 575 }, null /*Session.Info*/); 576 } 577 } 578 sendSetVideoProvider(String id)579 public void sendSetVideoProvider(String id) throws Exception { 580 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 581 a.setVideoProvider(id, mConnectionById.get(id).videoProvider, null /*Session.Info*/); 582 } 583 } 584 sendSetVideoState(String id)585 public void sendSetVideoState(String id) throws Exception { 586 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 587 a.setVideoState(id, mConnectionById.get(id).videoState, null /*Session.Info*/); 588 } 589 } 590 sendSetIsVoipAudioMode(String id)591 public void sendSetIsVoipAudioMode(String id) throws Exception { 592 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 593 a.setIsVoipAudioMode(id, mConnectionById.get(id).isVoipAudioMode, 594 null /*Session.Info*/); 595 } 596 } 597 sendSetStatusHints(String id)598 public void sendSetStatusHints(String id) throws Exception { 599 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 600 a.setStatusHints(id, mConnectionById.get(id).statusHints, null /*Session.Info*/); 601 } 602 } 603 sendSetAddress(String id)604 public void sendSetAddress(String id) throws Exception { 605 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 606 a.setAddress( 607 id, 608 mConnectionById.get(id).request.getAddress(), 609 mConnectionById.get(id).addressPresentation, null /*Session.Info*/); 610 } 611 } 612 sendSetCallerDisplayName(String id)613 public void sendSetCallerDisplayName(String id) throws Exception { 614 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 615 a.setCallerDisplayName( 616 id, 617 mConnectionById.get(id).callerDisplayName, 618 mConnectionById.get(id).callerDisplayNamePresentation, null /*Session.Info*/); 619 } 620 } 621 sendSetConferenceableConnections(String id)622 public void sendSetConferenceableConnections(String id) throws Exception { 623 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 624 a.setConferenceableConnections(id, mConnectionById.get(id).conferenceableConnectionIds, 625 null /*Session.Info*/); 626 } 627 } 628 sendAddExistingConnection(String id)629 public void sendAddExistingConnection(String id) throws Exception { 630 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 631 a.addExistingConnection(id, parcelable(mConnectionById.get(id)), null /*Session.Info*/); 632 } 633 } 634 sendConnectionEvent(String id, String event, Bundle extras)635 public void sendConnectionEvent(String id, String event, Bundle extras) throws Exception { 636 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 637 a.onConnectionEvent(id, event, extras, null /*Session.Info*/); 638 } 639 } 640 sendSetConferenceMergeFailed(String id)641 public void sendSetConferenceMergeFailed(String id) throws Exception { 642 for (IConnectionServiceAdapter a : mConnectionServiceAdapters) { 643 a.setConferenceMergeFailed(id, null /*Session.Info*/); 644 } 645 } 646 647 /** 648 * Waits until the {@link Connection#onExtrasChanged(Bundle)} API has been called on a 649 * {@link Connection} or {@link Conference}. 650 */ waitForExtras()651 public void waitForExtras() { 652 try { 653 mExtrasLock.await(TelecomSystemTest.TEST_TIMEOUT, TimeUnit.MILLISECONDS); 654 } catch (InterruptedException ie) { 655 } 656 mExtrasLock = new CountDownLatch(1); 657 } 658 parcelable(ConferenceInfo c)659 private ParcelableConference parcelable(ConferenceInfo c) { 660 return new ParcelableConference( 661 c.phoneAccount, 662 c.state, 663 c.capabilities, 664 c.properties, 665 c.connectionIds, 666 c.videoProvider, 667 c.videoState, 668 c.connectTimeMillis, 669 c.connectElapsedTimeMillis, 670 c.statusHints, 671 c.extras); 672 } 673 parcelable(ConnectionInfo c)674 private ParcelableConnection parcelable(ConnectionInfo c) { 675 return new ParcelableConnection( 676 c.request.getAccountHandle(), 677 c.state, 678 c.capabilities, 679 c.properties, 680 c.supportedAudioRoutes, 681 c.request.getAddress(), 682 c.addressPresentation, 683 c.callerDisplayName, 684 c.callerDisplayNamePresentation, 685 c.videoProvider, 686 c.videoState, 687 false, /* ringback requested */ 688 false, /* voip audio mode */ 689 0, /* Connect Time for conf call on this connection */ 690 0, /* Connect Real Time comes from conference call */ 691 c.statusHints, 692 c.disconnectCause, 693 c.conferenceableConnectionIds, 694 c.extras); 695 } 696 } 697