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