TelecomSystemTest.java revision 1b5490ac8643a5969adaba6f68d872acd251d666
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
17package com.android.server.telecom.tests;
18
19import static org.mockito.Matchers.any;
20import static org.mockito.Matchers.anyBoolean;
21import static org.mockito.Matchers.anyInt;
22import static org.mockito.Matchers.anyString;
23import static org.mockito.Matchers.eq;
24import static org.mockito.Mockito.mock;
25import static org.mockito.Mockito.reset;
26import static org.mockito.Mockito.timeout;
27import static org.mockito.Mockito.verify;
28import static org.mockito.Mockito.when;
29
30import android.content.BroadcastReceiver;
31import android.content.ComponentName;
32import android.content.Context;
33import android.content.Intent;
34import android.net.Uri;
35import android.os.Bundle;
36import android.os.Handler;
37import android.os.UserHandle;
38import android.telecom.Call;
39import android.telecom.ConnectionRequest;
40import android.telecom.DisconnectCause;
41import android.telecom.ParcelableCall;
42import android.telecom.PhoneAccount;
43import android.telecom.PhoneAccountHandle;
44import android.telecom.TelecomManager;
45import android.telephony.TelephonyManager;
46
47import com.android.internal.telecom.IInCallAdapter;
48import com.android.server.telecom.CallsManager;
49import com.android.server.telecom.HeadsetMediaButton;
50import com.android.server.telecom.HeadsetMediaButtonFactory;
51import com.android.server.telecom.InCallWakeLockController;
52import com.android.server.telecom.InCallWakeLockControllerFactory;
53import com.android.server.telecom.Log;
54import com.android.server.telecom.MissedCallNotifier;
55import com.android.server.telecom.ProximitySensorManager;
56import com.android.server.telecom.ProximitySensorManagerFactory;
57import com.android.server.telecom.TelecomSystem;
58
59import org.mockito.ArgumentCaptor;
60import org.mockito.Mock;
61
62import java.util.concurrent.BrokenBarrierException;
63import java.util.concurrent.CountDownLatch;
64import java.util.concurrent.CyclicBarrier;
65
66public class TelecomSystemTest extends TelecomTestCase {
67
68    static final int TEST_TIMEOUT = 1000;  // milliseconds
69
70    @Mock MissedCallNotifier mMissedCallNotifier;
71    @Mock HeadsetMediaButton mHeadsetMediaButton;
72    @Mock ProximitySensorManager mProximitySensorManager;
73    @Mock InCallWakeLockController mInCallWakeLockController;
74
75    final ComponentName mInCallServiceComponentNameX =
76            new ComponentName(
77                    "incall-service-package-X",
78                    "incall-service-class-X");
79    final ComponentName mInCallServiceComponentNameY =
80            new ComponentName(
81                    "incall-service-package-Y",
82                    "incall-service-class-Y");
83
84    InCallServiceFixture mInCallServiceFixtureX;
85    InCallServiceFixture mInCallServiceFixtureY;
86
87    final ComponentName mConnectionServiceComponentNameA =
88            new ComponentName(
89                    "connection-service-package-A",
90                    "connection-service-class-A");
91    final ComponentName mConnectionServiceComponentNameB =
92            new ComponentName(
93                    "connection-service-package-B",
94                    "connection-service-class-B");
95
96    final PhoneAccount mPhoneAccountA0 =
97            PhoneAccount.builder(
98                    new PhoneAccountHandle(
99                            mConnectionServiceComponentNameA,
100                            "id A 0"),
101                    "Phone account service A ID 0")
102                    .addSupportedUriScheme("tel")
103                    .setCapabilities(
104                            PhoneAccount.CAPABILITY_CALL_PROVIDER |
105                            PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
106                    .build();
107    final PhoneAccount mPhoneAccountA1 =
108            PhoneAccount.builder(
109                    new PhoneAccountHandle(
110                            mConnectionServiceComponentNameA,
111                            "id A 1"),
112                    "Phone account service A ID 1")
113                    .addSupportedUriScheme("tel")
114                    .setCapabilities(
115                            PhoneAccount.CAPABILITY_CALL_PROVIDER |
116                            PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
117                    .build();
118    final PhoneAccount mPhoneAccountB0 =
119            PhoneAccount.builder(
120                    new PhoneAccountHandle(
121                            mConnectionServiceComponentNameB,
122                            "id B 0"),
123                    "Phone account service B ID 0")
124                    .addSupportedUriScheme("tel")
125                    .setCapabilities(
126                            PhoneAccount.CAPABILITY_CALL_PROVIDER |
127                            PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
128                    .build();
129
130    ConnectionServiceFixture mConnectionServiceFixtureA;
131    ConnectionServiceFixture mConnectionServiceFixtureB;
132
133    CallerInfoAsyncQueryFactoryFixture mCallerInfoAsyncQueryFactoryFixture;
134
135    TelecomSystem mTelecomSystem;
136
137    class IdPair {
138        final String mConnectionId;
139        final String mCallId;
140
141        public IdPair(String connectionId, String callId) {
142            this.mConnectionId = connectionId;
143            this.mCallId = callId;
144        }
145    }
146
147    @Override
148    public void setUp() throws Exception {
149        super.setUp();
150
151        // First set up information about the In-Call services in the mock Context, since
152        // Telecom will search for these as soon as it is instantiated
153        setupInCallServices();
154
155        // Next, create the TelecomSystem, our system under test
156        setupTelecomSystem();
157
158        // Finally, register the ConnectionServices with the PhoneAccountRegistrar of the
159        // now-running TelecomSystem
160        setupConnectionServices();
161    }
162
163    @Override
164    public void tearDown() throws Exception {
165        mTelecomSystem = null;
166        super.tearDown();
167    }
168
169    private void setupTelecomSystem() throws Exception {
170        HeadsetMediaButtonFactory headsetMediaButtonFactory =
171                mock(HeadsetMediaButtonFactory.class);
172        ProximitySensorManagerFactory proximitySensorManagerFactory =
173                mock(ProximitySensorManagerFactory.class);
174        InCallWakeLockControllerFactory inCallWakeLockControllerFactory =
175                mock(InCallWakeLockControllerFactory.class);
176
177        mCallerInfoAsyncQueryFactoryFixture = new CallerInfoAsyncQueryFactoryFixture();
178
179        when(headsetMediaButtonFactory.create(
180                any(Context.class),
181                any(CallsManager.class),
182                any(TelecomSystem.SyncRoot.class)))
183                .thenReturn(mHeadsetMediaButton);
184        when(proximitySensorManagerFactory.create(
185                any(Context.class),
186                any(CallsManager.class)))
187                .thenReturn(mProximitySensorManager);
188        when(inCallWakeLockControllerFactory.create(
189                any(Context.class),
190                any(CallsManager.class)))
191                .thenReturn(mInCallWakeLockController);
192
193        mTelecomSystem = new TelecomSystem(
194                mComponentContextFixture.getTestDouble(),
195                mMissedCallNotifier,
196                mCallerInfoAsyncQueryFactoryFixture.getTestDouble(),
197                headsetMediaButtonFactory,
198                proximitySensorManagerFactory,
199                inCallWakeLockControllerFactory);
200
201        verify(headsetMediaButtonFactory).create(
202                eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
203                any(CallsManager.class),
204                any(TelecomSystem.SyncRoot.class));
205        verify(proximitySensorManagerFactory).create(
206                eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
207                any(CallsManager.class));
208        verify(inCallWakeLockControllerFactory).create(
209                eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
210                any(CallsManager.class));
211    }
212
213    private void setupConnectionServices() throws Exception {
214        mConnectionServiceFixtureA = new ConnectionServiceFixture();
215        mConnectionServiceFixtureB = new ConnectionServiceFixture();
216
217        mComponentContextFixture.addConnectionService(
218                mConnectionServiceComponentNameA,
219                mConnectionServiceFixtureA.getTestDouble());
220        mComponentContextFixture.addConnectionService(
221                mConnectionServiceComponentNameB,
222                mConnectionServiceFixtureB.getTestDouble());
223
224        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0);
225        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA1);
226        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountB0);
227
228        mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount(
229                mPhoneAccountA0.getAccountHandle());
230    }
231
232    private void setupInCallServices() throws Exception {
233        mComponentContextFixture.putResource(
234                com.android.server.telecom.R.string.ui_default_package,
235                mInCallServiceComponentNameX.getPackageName());
236        mComponentContextFixture.putResource(
237                com.android.server.telecom.R.string.incall_default_class,
238                mInCallServiceComponentNameX.getClassName());
239
240        mInCallServiceFixtureX = new InCallServiceFixture();
241        mInCallServiceFixtureY = new InCallServiceFixture();
242
243        mComponentContextFixture.addInCallService(
244                mInCallServiceComponentNameX,
245                mInCallServiceFixtureX.getTestDouble());
246        mComponentContextFixture.addInCallService(
247                mInCallServiceComponentNameY,
248                mInCallServiceFixtureY.getTestDouble());
249    }
250
251    private IdPair startOutgoingPhoneCall(
252            String number,
253            PhoneAccountHandle phoneAccountHandle,
254            ConnectionServiceFixture connectionServiceFixture) throws Exception {
255        reset(
256                connectionServiceFixture.getTestDouble(),
257                mInCallServiceFixtureX.getTestDouble(),
258                mInCallServiceFixtureY.getTestDouble());
259
260        assertEquals(
261                mInCallServiceFixtureX.mCallById.size(),
262                mInCallServiceFixtureY.mCallById.size());
263        assertEquals(
264                (mInCallServiceFixtureX.mInCallAdapter != null),
265                (mInCallServiceFixtureY.mInCallAdapter != null));
266
267        int startingNumConnections = connectionServiceFixture.mConnectionById.size();
268        int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
269        boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
270
271        Intent actionCallIntent = new Intent();
272        actionCallIntent.setData(Uri.parse("tel:" + number));
273        actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
274        actionCallIntent.setAction(Intent.ACTION_CALL);
275        if (phoneAccountHandle != null) {
276            actionCallIntent.putExtra(
277                    TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
278                    phoneAccountHandle);
279        }
280
281        mTelecomSystem.getCallIntentProcessor().processIntent(actionCallIntent);
282
283        if (!hasInCallAdapter) {
284            verify(mInCallServiceFixtureX.getTestDouble())
285                    .setInCallAdapter(
286                            any(IInCallAdapter.class));
287            verify(mInCallServiceFixtureY.getTestDouble())
288                    .setInCallAdapter(
289                            any(IInCallAdapter.class));
290        }
291
292        ArgumentCaptor<Intent> newOutgoingCallIntent =
293                ArgumentCaptor.forClass(Intent.class);
294        ArgumentCaptor<BroadcastReceiver> newOutgoingCallReceiver =
295                ArgumentCaptor.forClass(BroadcastReceiver.class);
296
297        verify(mComponentContextFixture.getTestDouble().getApplicationContext())
298                .sendOrderedBroadcastAsUser(
299                        newOutgoingCallIntent.capture(),
300                        any(UserHandle.class),
301                        anyString(),
302                        anyInt(),
303                        newOutgoingCallReceiver.capture(),
304                        any(Handler.class),
305                        anyInt(),
306                        anyString(),
307                        any(Bundle.class));
308
309        assertNotNull(mInCallServiceFixtureX.mInCallAdapter);
310        assertNotNull(mInCallServiceFixtureY.mInCallAdapter);
311
312        // Pass on the new outgoing call Intent
313        // Set a dummy PendingResult so the BroadcastReceiver agrees to accept onReceive()
314        newOutgoingCallReceiver.getValue().setPendingResult(
315                new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0));
316        newOutgoingCallReceiver.getValue().setResultData(
317                newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER));
318        newOutgoingCallReceiver.getValue().onReceive(
319                mComponentContextFixture.getTestDouble(),
320                newOutgoingCallIntent.getValue());
321
322        assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
323
324        verify(connectionServiceFixture.getTestDouble()).createConnection(
325                eq(phoneAccountHandle),
326                anyString(),
327                any(ConnectionRequest.class),
328                anyBoolean(),
329                anyBoolean());
330
331        connectionServiceFixture.sendHandleCreateConnectionComplete(
332                connectionServiceFixture.mLatestConnectionId);
333
334        assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
335        assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
336
337        assertEquals(
338                mInCallServiceFixtureX.mLatestCallId,
339                mInCallServiceFixtureY.mLatestCallId);
340
341        return new IdPair(
342                connectionServiceFixture.mLatestConnectionId,
343                mInCallServiceFixtureX.mLatestCallId);
344    }
345
346    private IdPair startIncomingPhoneCall(
347            String number,
348            PhoneAccountHandle phoneAccountHandle,
349            ConnectionServiceFixture connectionServiceFixture) throws Exception {
350        reset(
351                connectionServiceFixture.getTestDouble(),
352                mInCallServiceFixtureX.getTestDouble(),
353                mInCallServiceFixtureY.getTestDouble());
354
355        assertEquals(
356                mInCallServiceFixtureX.mCallById.size(),
357                mInCallServiceFixtureY.mCallById.size());
358        assertEquals(
359                (mInCallServiceFixtureX.mInCallAdapter != null),
360                (mInCallServiceFixtureY.mInCallAdapter != null));
361
362        int startingNumConnections = connectionServiceFixture.mConnectionById.size();
363        int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
364        boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
365
366        Bundle extras = new Bundle();
367        extras.putParcelable(
368                TelephonyManager.EXTRA_INCOMING_NUMBER,
369                Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null));
370        mTelecomSystem.getTelecomServiceImpl().getBinder()
371                .addNewIncomingCall(phoneAccountHandle, extras);
372
373        verify(connectionServiceFixture.getTestDouble()).createConnection(
374                any(PhoneAccountHandle.class),
375                anyString(),
376                any(ConnectionRequest.class),
377                eq(true),
378                eq(false));
379
380        connectionServiceFixture.sendHandleCreateConnectionComplete(
381                connectionServiceFixture.mLatestConnectionId);
382        connectionServiceFixture.sendSetRinging(
383                connectionServiceFixture.mLatestConnectionId);
384
385        // For the case of incoming calls, Telecom connecting the InCall services and adding the
386        // Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call
387        // is added, future interactions as triggered by the ConnectionService, through the various
388        // test fixtures, will be synchronous.
389
390        if (!hasInCallAdapter) {
391            verify(
392                    mInCallServiceFixtureX.getTestDouble(),
393                    timeout(TEST_TIMEOUT))
394                    .setInCallAdapter(
395                            any(IInCallAdapter.class));
396            verify(
397                    mInCallServiceFixtureY.getTestDouble(),
398                    timeout(TEST_TIMEOUT))
399                    .setInCallAdapter(
400                            any(IInCallAdapter.class));
401        }
402
403        // Give the InCallService time to respond
404        pause();
405
406        assertNotNull(mInCallServiceFixtureX.mInCallAdapter);
407        assertNotNull(mInCallServiceFixtureY.mInCallAdapter);
408
409        verify(
410                mInCallServiceFixtureX.getTestDouble(),
411                timeout(TEST_TIMEOUT))
412                .addCall(
413                        any(ParcelableCall.class));
414        verify(
415                mInCallServiceFixtureY.getTestDouble(),
416                timeout(TEST_TIMEOUT))
417                .addCall(
418                        any(ParcelableCall.class));
419
420        // Give the InCallService time to respond
421        pause();
422
423        assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
424        assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
425        assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
426
427        assertEquals(
428                mInCallServiceFixtureX.mLatestCallId,
429                mInCallServiceFixtureY.mLatestCallId);
430
431        return new IdPair(
432                connectionServiceFixture.mLatestConnectionId,
433                mInCallServiceFixtureX.mLatestCallId);
434    }
435
436    private void rapidFire(Runnable... tasks) {
437        final CyclicBarrier barrier = new CyclicBarrier(tasks.length);
438        final CountDownLatch latch = new CountDownLatch(tasks.length);
439        for (int i = 0; i < tasks.length; i++) {
440            final Runnable task = tasks[i];
441            new Thread(new Runnable() {
442                @Override
443                public void run() {
444                    try {
445                        barrier.await();
446                        task.run();
447                    } catch (InterruptedException | BrokenBarrierException e){
448                        Log.e(TelecomSystemTest.this, e, "Unexpectedly interrupted");
449                    } finally {
450                        latch.countDown();
451                    }
452                }
453            }).start();
454        }
455        try {
456            latch.await();
457        } catch (InterruptedException e) {
458            Log.e(TelecomSystemTest.this, e, "Unexpectedly interrupted");
459        }
460    }
461
462    // A simple outgoing call, verifying that the appropriate connection service is contacted,
463    // the proper lifecycle is followed, and both In-Call Services are updated correctly.
464    private IdPair startAndMakeActiveOutgoingCall(
465            String number,
466            PhoneAccountHandle phoneAccountHandle,
467            ConnectionServiceFixture connectionServiceFixture) throws Exception {
468        IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture);
469
470        connectionServiceFixture.sendSetDialing(ids.mConnectionId);
471
472        assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
473        assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
474
475        connectionServiceFixture.sendSetActive(ids.mConnectionId);
476        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
477        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
478
479        return ids;
480    }
481
482    public void testSingleOutgoingCallLocalDisconnect() throws Exception {
483        IdPair ids = startAndMakeActiveOutgoingCall(
484                "650-555-1212",
485                mPhoneAccountA0.getAccountHandle(),
486                mConnectionServiceFixtureA);
487
488        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
489        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
490        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
491
492        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
493        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
494        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
495    }
496
497    public void testSingleOutgoingCallRemoteDisconnect() throws Exception {
498        IdPair ids = startAndMakeActiveOutgoingCall(
499                "650-555-1212",
500                mPhoneAccountA0.getAccountHandle(),
501                mConnectionServiceFixtureA);
502
503        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
504        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
505        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
506    }
507
508    // A simple incoming call, similar in scope to the previous test
509    private IdPair startAndMakeActiveIncomingCall(
510            String number,
511            PhoneAccountHandle phoneAccountHandle,
512            ConnectionServiceFixture connectionServiceFixture) throws Exception {
513        IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture);
514
515        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
516        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
517
518        connectionServiceFixture.sendSetActive(ids.mConnectionId);
519        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
520        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
521
522        return ids;
523    }
524
525    public void testSingleIncomingCallLocalDisconnect() throws Exception {
526        IdPair ids = startAndMakeActiveIncomingCall(
527                "650-555-1212",
528                mPhoneAccountA0.getAccountHandle(),
529                mConnectionServiceFixtureA);
530
531        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
532        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
533        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
534
535        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
536        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
537        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
538    }
539
540    public void testSingleIncomingCallRemoteDisconnect() throws Exception {
541        IdPair ids = startAndMakeActiveIncomingCall(
542                "650-555-1212",
543                mPhoneAccountA0.getAccountHandle(),
544                mConnectionServiceFixtureA);
545
546        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
547        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
548        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
549    }
550
551    public void do_testDeadlockOnOutgoingCall() throws Exception {
552        final IdPair ids = startOutgoingPhoneCall(
553                "650-555-1212",
554                mPhoneAccountA0.getAccountHandle(),
555                mConnectionServiceFixtureA);
556        rapidFire(
557                new Runnable() {
558                    @Override
559                    public void run() {
560                        while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) {
561                            mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply();
562                        }
563                    }
564                },
565                new Runnable() {
566                    @Override
567                    public void run() {
568                        try {
569                            mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
570                        } catch (Exception e) {
571                            Log.e(this, e, "");
572                        }
573                    }
574                });
575    }
576
577    public void testDeadlockOnOutgoingCall() throws Exception {
578        for (int i = 0; i < 100; i++) {
579            TelecomSystemTest test = new TelecomSystemTest();
580            test.setContext(getContext());
581            test.setTestContext(getTestContext());
582            test.setName(getName());
583            test.setUp();
584            test.do_testDeadlockOnOutgoingCall();
585            test.tearDown();
586        }
587    }
588
589    public void testIncomingThenOutgoingCalls() throws Exception {
590        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
591        IdPair incoming = startAndMakeActiveIncomingCall(
592                "650-555-2323",
593                mPhoneAccountA0.getAccountHandle(),
594                mConnectionServiceFixtureA);
595        IdPair outgoing = startAndMakeActiveOutgoingCall(
596                "650-555-1212",
597                mPhoneAccountA0.getAccountHandle(),
598                mConnectionServiceFixtureA);
599    }
600
601    public void testOutgoingThenIncomingCalls() throws Exception {
602        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
603        IdPair outgoing = startAndMakeActiveOutgoingCall(
604                "650-555-1212",
605                mPhoneAccountA0.getAccountHandle(),
606                mConnectionServiceFixtureA);
607        IdPair incoming = startAndMakeActiveIncomingCall(
608                "650-555-2323",
609                mPhoneAccountA0.getAccountHandle(),
610                mConnectionServiceFixtureA);
611    }
612
613    protected static void pause() {
614        try {
615            Thread.sleep(TEST_TIMEOUT);
616        } catch (InterruptedException e) {
617            fail(e.toString());
618        }
619    }
620}
621