1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.telecom.cts;
18 
19 import static android.telecom.cts.TestUtils.*;
20 
21 import android.os.Bundle;
22 import android.os.Handler;
23 import android.os.HandlerThread;
24 import android.telecom.Call;
25 import android.telecom.Connection;
26 import android.telecom.ConnectionRequest;
27 import android.telecom.DisconnectCause;
28 import android.telecom.PhoneAccountHandle;
29 import android.telecom.RemoteConference;
30 import android.telecom.RemoteConnection;
31 import android.telecom.TelecomManager;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 /**
37  * Extended suite of tests that use {@link CtsConnectionService} and {@link MockInCallService} to
38  * verify the functionality of Remote Conferences.
39  * We make 2 connections on the {@link CtsConnectionService} & we create 2 connections on the
40  * {@link CtsRemoteConnectionService} via the {@link RemoteConnection} object. We store this
41  * corresponding RemoteConnection object on the connections to plumb the modifications on
42  * the connections in {@link CtsConnectionService} to the connections on
43  * {@link CtsRemoteConnectionService}. Then we create a remote conference on the
44  * {@link CtsRemoteConnectionService} and control it via the {@link RemoteConference}
45  * object. The onConference method on the managerConnectionService will initiate a remote conference
46  * creation on the remoteConnectionService and once that is completed, we create a local conference
47  * on the managerConnectionService.
48  */
49 public class RemoteConferenceTest extends BaseRemoteTelecomTest {
50 
51     public static final int CONF_CAPABILITIES = Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE |
52             Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE | Connection.CAPABILITY_HOLD |
53             Connection.CAPABILITY_MERGE_CONFERENCE | Connection.CAPABILITY_SWAP_CONFERENCE;
54 
55     MockConnection mConnection1, mConnection2;
56     MockConnection mRemoteConnection1, mRemoteConnection2;
57     Call mCall1, mCall2;
58     MockConference mConference, mRemoteConference;
59     RemoteConference mRemoteConferenceObject;
60 
61     @Override
setUp()62     protected void setUp() throws Exception {
63         super.setUp();
64         if (mShouldTestTelecom) {
65             addRemoteConferenceCall();
66             verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
67         }
68     }
69 
testRemoteConferenceCreate()70     public void testRemoteConferenceCreate() {
71         if (!mShouldTestTelecom) {
72             return;
73         }
74         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
75         assertCallState(confCall, Call.STATE_ACTIVE);
76 
77         if (mCall1.getParent() != confCall || mCall2.getParent() != confCall) {
78             fail("The 2 participating calls should contain the conference call as its parent");
79         }
80         if (!(confCall.getChildren().contains(mCall1) && confCall.getChildren().contains(mCall2))) {
81             fail("The conference call should contain the 2 participating calls as its children");
82         }
83 
84         assertConnectionState(mConnection1, Connection.STATE_ACTIVE);
85         assertConnectionState(mConnection2, Connection.STATE_ACTIVE);
86         assertConnectionState(mRemoteConnection1, Connection.STATE_ACTIVE);
87         assertConnectionState(mRemoteConnection2, Connection.STATE_ACTIVE);
88         assertConferenceState(mConference, Connection.STATE_ACTIVE);
89         assertConferenceState(mRemoteConference, Connection.STATE_ACTIVE);
90         assertRemoteConferenceState(mRemoteConferenceObject, Connection.STATE_ACTIVE);
91     }
92 
testRemoteConferenceSplit()93     public void testRemoteConferenceSplit() {
94         if (!mShouldTestTelecom) {
95             return;
96         }
97         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
98         assertCallState(confCall, Call.STATE_ACTIVE);
99 
100         if (!(mCall1.getParent() == confCall) && (confCall.getChildren().contains(mCall1))) {
101             fail("Call 1 not conferenced");
102         }
103         assertTrue(mConference.getConnections().contains(mConnection1));
104         assertTrue(mRemoteConference.getConnections().contains(mRemoteConnection1));
105 
106         splitFromConferenceCall(mCall1);
107 
108         if ((mCall1.getParent() == confCall) || (confCall.getChildren().contains(mCall1))) {
109             fail("Call 1 should not be still conferenced");
110         }
111         assertFalse(mConference.getConnections().contains(mConnection1));
112         assertFalse(mRemoteConference.getConnections().contains(mRemoteConnection1));
113     }
114 
testRemoteConferenceHoldAndUnhold()115     public void testRemoteConferenceHoldAndUnhold() {
116         if (!mShouldTestTelecom) {
117             return;
118         }
119         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
120         assertCallState(confCall, Call.STATE_ACTIVE);
121 
122         confCall.hold();
123         assertCallState(confCall, Call.STATE_HOLDING);
124         assertCallState(mCall1, Call.STATE_HOLDING);
125         assertCallState(mCall2, Call.STATE_HOLDING);
126         assertConnectionState(mConnection1, Connection.STATE_HOLDING);
127         assertConnectionState(mConnection2, Connection.STATE_HOLDING);
128         assertConnectionState(mRemoteConnection1, Connection.STATE_HOLDING);
129         assertConnectionState(mRemoteConnection2, Connection.STATE_HOLDING);
130         assertConferenceState(mConference, Connection.STATE_HOLDING);
131         assertConferenceState(mRemoteConference, Connection.STATE_HOLDING);
132         assertRemoteConferenceState(mRemoteConferenceObject, Connection.STATE_HOLDING);
133 
134         confCall.unhold();
135         assertCallState(confCall, Call.STATE_ACTIVE);
136         assertCallState(mCall1, Call.STATE_ACTIVE);
137         assertCallState(mCall2, Call.STATE_ACTIVE);
138         assertConnectionState(mConnection1, Connection.STATE_ACTIVE);
139         assertConnectionState(mConnection2, Connection.STATE_ACTIVE);
140         assertConnectionState(mRemoteConnection1, Connection.STATE_ACTIVE);
141         assertConnectionState(mRemoteConnection2, Connection.STATE_ACTIVE);
142         assertConferenceState(mConference, Connection.STATE_ACTIVE);
143         assertConferenceState(mRemoteConference, Connection.STATE_ACTIVE);
144         assertRemoteConferenceState(mRemoteConferenceObject, Connection.STATE_ACTIVE);
145     }
146 
testRemoteConferenceMergeAndSwap()147     public void testRemoteConferenceMergeAndSwap() {
148         if (!mShouldTestTelecom) {
149             return;
150         }
151         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
152         assertCallState(confCall, Call.STATE_ACTIVE);
153 
154         confCall.mergeConference();
155         assertCallDisplayName(mCall1, TestUtils.MERGE_CALLER_NAME);
156         assertCallDisplayName(mCall2, TestUtils.MERGE_CALLER_NAME);
157         assertConnectionCallDisplayName(mConnection1,
158                 TestUtils.MERGE_CALLER_NAME);
159         assertConnectionCallDisplayName(mConnection2,
160                 TestUtils.MERGE_CALLER_NAME);
161         assertConnectionCallDisplayName(mRemoteConnection1,
162                 TestUtils.MERGE_CALLER_NAME);
163         assertConnectionCallDisplayName(mRemoteConnection2,
164                 TestUtils.MERGE_CALLER_NAME);
165 
166         confCall.swapConference();
167         assertCallDisplayName(mCall1, TestUtils.SWAP_CALLER_NAME);
168         assertCallDisplayName(mCall2, TestUtils.SWAP_CALLER_NAME);
169         assertConnectionCallDisplayName(mConnection1,
170                 TestUtils.SWAP_CALLER_NAME);
171         assertConnectionCallDisplayName(mConnection2,
172                 TestUtils.SWAP_CALLER_NAME);
173         assertConnectionCallDisplayName(mRemoteConnection1,
174                 TestUtils.SWAP_CALLER_NAME);
175         assertConnectionCallDisplayName(mRemoteConnection2,
176                 TestUtils.SWAP_CALLER_NAME);
177     }
178 
testRemoteConferenceDTMFTone()179     public void testRemoteConferenceDTMFTone() {
180         if (!mShouldTestTelecom) {
181             return;
182         }
183         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
184         assertCallState(confCall, Call.STATE_ACTIVE);
185 
186         assertTrue(mConference.getDtmfString().isEmpty());
187         assertTrue(mRemoteConference.getDtmfString().isEmpty());
188         confCall.playDtmfTone('1');
189         assertDtmfString(mConference, "1");
190         assertDtmfString(mRemoteConference, "1");
191         confCall.stopDtmfTone();
192         assertDtmfString(mConference, "1.");
193         assertDtmfString(mRemoteConference, "1.");
194         confCall.playDtmfTone('3');
195         assertDtmfString(mConference, "1.3");
196         assertDtmfString(mRemoteConference, "1.3");
197         confCall.stopDtmfTone();
198         assertDtmfString(mConference, "1.3.");
199         assertDtmfString(mRemoteConference, "1.3.");
200     }
201 
testRemoteConferenceCallbacks_StateChange()202     public void testRemoteConferenceCallbacks_StateChange() {
203         if (!mShouldTestTelecom) {
204             return;
205         }
206         Handler handler = setupRemoteConferenceCallbacksTest();
207 
208         final InvokeCounter callbackInvoker =
209                 new InvokeCounter("testRemoteConferenceCallbacks_StateChange");
210         RemoteConference.Callback callback;
211 
212         callback = new RemoteConference.Callback() {
213             @Override
214             public void onStateChanged(RemoteConference conference, int oldState, int newState) {
215                 super.onStateChanged(conference, oldState, newState);
216                 callbackInvoker.invoke(conference, oldState, newState);
217             }
218         };
219         mRemoteConferenceObject.registerCallback(callback, handler);
220         mRemoteConference.setOnHold();
221         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
222         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
223         assertEquals(Connection.STATE_ACTIVE, callbackInvoker.getArgs(0)[1]);
224         assertEquals(Connection.STATE_HOLDING, callbackInvoker.getArgs(0)[2]);
225         mRemoteConferenceObject.unregisterCallback(callback);
226     }
227 
testRemoteConferenceCallbacks_Disconnect()228     public void testRemoteConferenceCallbacks_Disconnect() {
229         if (!mShouldTestTelecom) {
230             return;
231         }
232         Handler handler = setupRemoteConferenceCallbacksTest();
233 
234         final InvokeCounter callbackInvoker =
235                 new InvokeCounter("testRemoteConferenceCallbacks_Disconnect");
236         RemoteConference.Callback callback;
237 
238         callback = new RemoteConference.Callback() {
239             @Override
240             public void onDisconnected(RemoteConference conference,
241                                        DisconnectCause disconnectCause) {
242                 super.onDisconnected(conference, disconnectCause);
243                 callbackInvoker.invoke(conference, disconnectCause);
244             }
245         };
246         mRemoteConferenceObject.registerCallback(callback, handler);
247         DisconnectCause cause = new DisconnectCause(DisconnectCause.LOCAL);
248         mRemoteConference.setDisconnected(cause);
249         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
250         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
251         assertEquals(cause, callbackInvoker.getArgs(0)[1]);
252         mRemoteConferenceObject.unregisterCallback(callback);
253     }
254 
testRemoteConferenceCallbacks_ConnectionAdd()255     public void testRemoteConferenceCallbacks_ConnectionAdd() {
256         if (!mShouldTestTelecom) {
257             return;
258         }
259         Handler handler = setupRemoteConferenceCallbacksTest();
260 
261         final InvokeCounter callbackInvoker =
262                 new InvokeCounter("testRemoteConferenceCallbacks_ConnectionAdd");
263         RemoteConference.Callback callback;
264 
265         callback = new RemoteConference.Callback() {
266             @Override
267             public void onConnectionAdded(RemoteConference conference,
268                                           RemoteConnection connection) {
269                 super.onConnectionAdded(conference, connection);
270                 callbackInvoker.invoke(conference, connection);
271             }
272         };
273         mRemoteConferenceObject.registerCallback(callback, handler);
274         placeAndVerifyCall();
275         RemoteConnection newRemoteConnectionObject =
276                 verifyConnectionForOutgoingCall(1).getRemoteConnection();
277         MockConnection newConnection = verifyConnectionForOutgoingCallOnRemoteCS(2);
278         mRemoteConference.addConnection(newConnection);
279         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
280         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
281         // No "equals" method in RemoteConnection
282         //assertEquals(newRemoteConnectionObject, callbackInvoker.getArgs(0)[1]);
283         mRemoteConferenceObject.unregisterCallback(callback);
284     }
285 
testRemoteConferenceCallbacks_ConnectionRemove()286     public void testRemoteConferenceCallbacks_ConnectionRemove() {
287         if (!mShouldTestTelecom) {
288             return;
289         }
290         Handler handler = setupRemoteConferenceCallbacksTest();
291 
292         final InvokeCounter callbackInvoker =
293                 new InvokeCounter("testRemoteConferenceCallbacks_ConnectionRemove");
294         RemoteConference.Callback callback;
295 
296         callback = new RemoteConference.Callback() {
297             @Override
298             public void onConnectionRemoved(RemoteConference conference,
299                                             RemoteConnection connection) {
300                 super.onConnectionRemoved(conference, connection);
301                 callbackInvoker.invoke(conference, connection);
302             }
303         };
304         mRemoteConferenceObject.registerCallback(callback, handler);
305         placeAndVerifyCall();
306         RemoteConnection newRemoteConnectionObject =
307                 verifyConnectionForOutgoingCall(1).getRemoteConnection();
308         MockConnection newConnection = verifyConnectionForOutgoingCallOnRemoteCS(2);
309         mRemoteConference.addConnection(newConnection);
310         mRemoteConference.removeConnection(newConnection);
311         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
312         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
313         //assertEquals(newRemoteConnectionObject, callbackInvoker.getArgs(0)[1]);
314         // No "equals" method in RemoteConnection
315         mRemoteConferenceObject.unregisterCallback(callback);
316     }
317 
testRemoteConferenceCallbacks_ConnectionCapabilities()318     public void testRemoteConferenceCallbacks_ConnectionCapabilities() {
319         if (!mShouldTestTelecom) {
320             return;
321         }
322         Handler handler = setupRemoteConferenceCallbacksTest();
323 
324         final InvokeCounter callbackInvoker =
325                 new InvokeCounter("testRemoteConferenceCallbacks_ConnectionCapabilities");
326         RemoteConference.Callback callback;
327 
328         callback = new RemoteConference.Callback() {
329             @Override
330             public void onConnectionCapabilitiesChanged(
331                     RemoteConference conference,
332                     int connectionCapabilities) {
333                 super.onConnectionCapabilitiesChanged(conference, connectionCapabilities);
334                 callbackInvoker.invoke(conference, connectionCapabilities);
335             }
336         };
337         mRemoteConferenceObject.registerCallback(callback, handler);
338         int capabilities = mRemoteConference.getConnectionCapabilities() | Connection.CAPABILITY_MUTE;
339         mRemoteConference.setConnectionCapabilities(capabilities);
340         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
341         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
342         assertEquals(capabilities, callbackInvoker.getArgs(0)[1]);
343         mRemoteConferenceObject.unregisterCallback(callback);
344     }
345 
testRemoteConferenceCallbacks_ConferenceableConnections()346     public void testRemoteConferenceCallbacks_ConferenceableConnections() {
347         if (!mShouldTestTelecom) {
348             return;
349         }
350         Handler handler = setupRemoteConferenceCallbacksTest();
351 
352         final InvokeCounter callbackInvoker =
353                 new InvokeCounter("testRemoteConferenceCallbacks_ConferenceableConnections");
354         RemoteConference.Callback callback;
355 
356         callback = new RemoteConference.Callback() {
357             @Override
358             public void onConferenceableConnectionsChanged(
359                     RemoteConference conference,
360                     List<RemoteConnection> conferenceableConnections) {
361                 super.onConferenceableConnectionsChanged(conference, conferenceableConnections);
362                 callbackInvoker.invoke(conference, conferenceableConnections);
363             }
364         };
365         mRemoteConferenceObject.registerCallback(callback, handler);
366         placeAndVerifyCall();
367         RemoteConnection newRemoteConnectionObject =
368             verifyConnectionForOutgoingCall(1).getRemoteConnection();
369         MockConnection newConnection = verifyConnectionForOutgoingCallOnRemoteCS(1);
370         ArrayList<Connection> confList = new ArrayList<>();
371         confList.add(newConnection);
372         mRemoteConference.setConferenceableConnections(confList);
373         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
374         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
375         // No "equals" method in RemoteConnection
376         //assertTrue(((List<RemoteConnection>)callbackInvoker.getArgs(0)[1]).contains(
377                 //newRemoteConnectionObject));
378         mRemoteConferenceObject.unregisterCallback(callback);
379     }
380 
testRemoteConferenceCallbacks_Destroy()381     public void testRemoteConferenceCallbacks_Destroy() {
382         if (!mShouldTestTelecom) {
383             return;
384         }
385         Handler handler = setupRemoteConferenceCallbacksTest();
386 
387         final InvokeCounter callbackInvoker =
388                 new InvokeCounter("testRemoteConferenceCallbacks_Destroy");
389         RemoteConference.Callback callback;
390 
391         callback = new RemoteConference.Callback() {
392             @Override
393             public void onDestroyed(RemoteConference conference) {
394                 super.onDestroyed(conference);
395                 callbackInvoker.invoke(conference);
396             }
397         };
398         mRemoteConferenceObject.registerCallback(callback, handler);
399         mRemoteConference.destroy();
400         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
401         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
402         mRemoteConferenceObject.unregisterCallback(callback);
403     }
404 
405 
testRemoteConferenceCallbacks_Extras()406     public void testRemoteConferenceCallbacks_Extras() {
407         if (!mShouldTestTelecom) {
408             return;
409         }
410         Handler handler = setupRemoteConferenceCallbacksTest();
411 
412         final InvokeCounter callbackInvoker =
413                 new InvokeCounter("testRemoteConferenceCallbacks_Extras");
414         RemoteConference.Callback callback;
415 
416         callback = new RemoteConference.Callback() {
417             @Override
418             public void onExtrasChanged(RemoteConference conference, Bundle extras) {
419                 super.onExtrasChanged(conference, extras);
420                 callbackInvoker.invoke(conference, extras);
421             }
422         };
423         mRemoteConferenceObject.registerCallback(callback, handler);
424         Bundle extras = new Bundle();
425         extras.putString(TelecomManager.EXTRA_CALL_DISCONNECT_MESSAGE, "Test");
426         mRemoteConference.setExtras(extras);
427         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
428         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
429         assertTrue(areBundlesEqual(extras, (Bundle) callbackInvoker.getArgs(0)[1]));
430         mRemoteConferenceObject.unregisterCallback(callback);
431     }
432 
verifyRemoteConferenceObject(RemoteConference remoteConferenceObject, MockConference remoteConference, MockConference conference)433     private void verifyRemoteConferenceObject(RemoteConference remoteConferenceObject,
434             MockConference remoteConference, MockConference conference) {
435         assertEquals(remoteConference.getConnectionCapabilities(),
436                 remoteConferenceObject.getConnectionCapabilities());
437         assertTrue(remoteConferenceObject.getConferenceableConnections().isEmpty());
438         List<RemoteConnection> remoteConnections = new ArrayList<>();
439         for (Connection c: conference.getConnections()) {
440             remoteConnections.add(((MockConnection)c).getRemoteConnection());
441         }
442         assertEquals(remoteConnections, remoteConferenceObject.getConnections());
443         assertEquals(remoteConference.getDisconnectCause(), remoteConferenceObject.getDisconnectCause());
444         assertEquals(remoteConference.getExtras(), remoteConferenceObject.getExtras());
445     }
446 
addRemoteConnectionOutgoingCalls()447     private void addRemoteConnectionOutgoingCalls() {
448         try {
449             MockConnectionService managerConnectionService = new MockConnectionService() {
450                 @Override
451                 public Connection onCreateOutgoingConnection(
452                         PhoneAccountHandle connectionManagerPhoneAccount,
453                         ConnectionRequest request) {
454                     MockConnection connection = (MockConnection)super.onCreateOutgoingConnection(
455                             connectionManagerPhoneAccount, request);
456                     ConnectionRequest remoteRequest = new ConnectionRequest(
457                             TEST_REMOTE_PHONE_ACCOUNT_HANDLE,
458                             request.getAddress(),
459                             request.getExtras());
460                     RemoteConnection remoteConnection =
461                             CtsConnectionService.createRemoteOutgoingConnectionToTelecom(
462                                     TEST_REMOTE_PHONE_ACCOUNT_HANDLE, remoteRequest);
463                     connection.setRemoteConnection(remoteConnection);
464                     // Modify the connection object created with local values.
465                     int capabilities = connection.getConnectionCapabilities();
466                     connection.setConnectionCapabilities(capabilities | CONF_CAPABILITIES);
467                     return connection;
468                 }
469                 @Override
470                 public void onConference(Connection connection1, Connection connection2) {
471                     /**
472                      * Fetch the corresponding remoteConnection objects and instantiate a remote
473                      * conference creation on the remoteConnectionService instead of this
474                      * managerConnectionService.
475                      */
476                     RemoteConnection remoteConnection1 =
477                             ((MockConnection)connection1).getRemoteConnection();
478                     RemoteConnection remoteConnection2 =
479                             ((MockConnection)connection2).getRemoteConnection();
480                     if (remoteConnection1.getConference() == null &&
481                             remoteConnection2.getConference() == null) {
482                         conferenceRemoteConnections(remoteConnection1, remoteConnection2);
483                     }
484 
485                     if (connection1.getState() == Connection.STATE_HOLDING){
486                         connection1.setActive();
487                     }
488                     if(connection2.getState() == Connection.STATE_HOLDING){
489                         connection2.setActive();
490                     }
491                 }
492                 @Override
493                 public void onRemoteConferenceAdded(RemoteConference remoteConference) {
494                     /**
495                      * Now that the remote conference has been created,
496                      * let's create a local conference on this ConnectionService.
497                      */
498                     MockConference conference = new MockConference(mConnection1, mConnection2);
499                     conference.setRemoteConference(remoteConference);
500                     CtsConnectionService.addConferenceToTelecom(conference);
501                     conferences.add(conference);
502                     lock.release();
503                 }
504             };
505             /**
506              * We want the conference to be instantiated on the remoteConnectionService registered
507              * with telecom.
508              */
509             MockConnectionService remoteConnectionService= new MockConnectionService() {
510                 @Override
511                 public Connection onCreateOutgoingConnection(
512                         PhoneAccountHandle connectionManagerPhoneAccount,
513                         ConnectionRequest request) {
514                     Connection connection = super.onCreateOutgoingConnection(
515                             connectionManagerPhoneAccount,
516                             request);
517                     // Modify the connection object created with local values.
518                     int capabilities = connection.getConnectionCapabilities();
519                     connection.setConnectionCapabilities(capabilities | CONF_CAPABILITIES);
520                     return connection;
521                 }
522                 @Override
523                 public void onConference(Connection connection1, Connection connection2) {
524                     // Make sure that these connections are already not conferenced.
525                     if (connection1.getConference() == null &&
526                             connection2.getConference() == null) {
527                         MockConference conference = new MockConference(
528                                 (MockConnection)connection1, (MockConnection)connection2);
529                         CtsRemoteConnectionService.addConferenceToTelecom(conference);
530                         conferences.add(conference);
531 
532                         if (connection1.getState() == Connection.STATE_HOLDING){
533                             connection1.setActive();
534                         }
535                         if(connection2.getState() == Connection.STATE_HOLDING){
536                             connection2.setActive();
537                         }
538 
539                         lock.release();
540                     }
541                 }
542             };
543             setupConnectionServices(managerConnectionService, remoteConnectionService,
544                     FLAG_REGISTER | FLAG_ENABLE);
545         } catch(Exception e) {
546             fail("Error in setting up the connection services");
547         }
548 
549         placeAndVerifyCall();
550         mConnection1 = verifyConnectionForOutgoingCall(0);
551         mRemoteConnection1 = verifyConnectionForOutgoingCallOnRemoteCS(0);
552         mCall1 = mInCallCallbacks.getService().getLastCall();
553         assertCallState(mCall1, Call.STATE_DIALING);
554         mConnection1.setActive();
555         mRemoteConnection1.setActive();
556         assertCallState(mCall1, Call.STATE_ACTIVE);
557 
558         placeAndVerifyCall();
559         mConnection2 = verifyConnectionForOutgoingCall(1);
560         mRemoteConnection2 = verifyConnectionForOutgoingCallOnRemoteCS(1);
561         mCall2 = mInCallCallbacks.getService().getLastCall();
562         assertCallState(mCall2, Call.STATE_DIALING);
563         mConnection2.setActive();
564         mRemoteConnection2.setActive();
565         assertCallState(mCall2, Call.STATE_ACTIVE);
566 
567         setAndVerifyConferenceablesForOutgoingConnection(0);
568         setAndVerifyConferenceablesForOutgoingConnection(1);
569         setAndVerifyConferenceablesForOutgoingConnectionOnRemoteCS(0);
570         setAndVerifyConferenceablesForOutgoingConnectionOnRemoteCS(1);
571     }
572 
addRemoteConferenceCall()573     private void addRemoteConferenceCall() {
574         addRemoteConnectionOutgoingCalls();
575         /**
576          * We've 2 connections on the local connectionService which have 2 corresponding
577          * connections on the remoteConnectionService controlled via 2 RemoteConnection objects
578          * on the connectionService. We now create a conference on the local two connections
579          * which triggers a creation of conference on the remoteConnectionService via the
580          * RemoteConference object.
581          */
582 
583         addConferenceCall(mCall1, mCall2);
584         mConference = verifyConferenceForOutgoingCall();
585         mRemoteConference = verifyConferenceForOutgoingCallOnRemoteCS();
586         mRemoteConferenceObject = mConference.getRemoteConference();
587         mRemoteConnection1 = (MockConnection)mRemoteConference.getConnections().get(0);
588         mRemoteConnection2 = (MockConnection)mRemoteConference.getConnections().get(1);
589     }
590 
setupRemoteConferenceCallbacksTest()591     private Handler setupRemoteConferenceCallbacksTest() {
592         final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
593         assertCallState(confCall, Call.STATE_ACTIVE);
594 
595         // Create a looper thread for the callbacks.
596         HandlerThread workerThread = new HandlerThread("CallbackThread");
597         workerThread.start();
598         Handler handler = new Handler(workerThread.getLooper());
599         return handler;
600     }
601 }
602