• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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