BasicCallTests.java revision ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734f
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 com.android.internal.util.IndentingPrintWriter;
20import com.android.server.telecom.Analytics;
21import com.android.server.telecom.Log;
22
23import android.content.Context;
24import android.media.AudioManager;
25import android.os.Process;
26import android.telecom.Call;
27import android.telecom.CallAudioState;
28import android.telecom.Connection;
29import android.telecom.DisconnectCause;
30import android.telecom.ParcelableCall;
31import android.telecom.ParcelableCallAnalytics;
32import android.telecom.TelecomManager;
33import android.telecom.VideoProfile;
34
35import com.android.internal.telecom.IInCallAdapter;
36
37import java.io.StringWriter;
38import java.util.List;
39import java.util.Map;
40import java.util.concurrent.BrokenBarrierException;
41import java.util.concurrent.CountDownLatch;
42import java.util.concurrent.CyclicBarrier;
43
44import static org.mockito.Matchers.any;
45import static org.mockito.Matchers.anyInt;
46import static org.mockito.Matchers.eq;
47import static org.mockito.Mockito.timeout;
48import static org.mockito.Mockito.verify;
49
50/**
51 * Performs various basic call tests in Telecom.
52 */
53public class BasicCallTests extends TelecomSystemTest {
54    public void testSingleOutgoingCallLocalDisconnect() throws Exception {
55        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
56                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
57
58        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
59        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
60        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
61
62        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
63        assertEquals(Call.STATE_DISCONNECTED,
64                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
65        assertEquals(Call.STATE_DISCONNECTED,
66                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
67    }
68
69    public void testSingleOutgoingCallRemoteDisconnect() throws Exception {
70        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
71                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
72
73        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
74        assertEquals(Call.STATE_DISCONNECTED,
75                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
76        assertEquals(Call.STATE_DISCONNECTED,
77                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
78    }
79
80    /**
81     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
82     * audio-only call.
83     *
84     * @throws Exception
85     */
86    public void testTelecomManagerAcceptRingingCall() throws Exception {
87        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
88                mConnectionServiceFixtureA);
89
90        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
91        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
92
93        // Use TelecomManager API to answer the ringing call.
94        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
95                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
96        telecomManager.acceptRingingCall();
97
98        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
99                .answer(ids.mCallId);
100        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
101
102        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
103    }
104
105    /**
106     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
107     * video call, which should be answered as video.
108     *
109     * @throws Exception
110     */
111    public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
112        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
113                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
114
115        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
116        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
117
118        // Use TelecomManager API to answer the ringing call; the default expected behavior is to
119        // answer using whatever video state the ringing call requests.
120        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
121                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
122        telecomManager.acceptRingingCall();
123
124        // Answer video API should be called
125        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
126                .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
127        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
128
129        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
130    }
131
132    /**
133     * Tests the {@link TelecomManager#acceptRingingCall(int)} API.  Tests answering a video call
134     * as an audio call.
135     *
136     * @throws Exception
137     */
138    public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
139        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
140                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
141
142        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
143        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
144
145        // Use TelecomManager API to answer the ringing call.
146        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
147                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
148        telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY);
149
150        // The generic answer method on the ConnectionService is used to answer audio-only calls.
151        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
152                .answer(eq(ids.mCallId));
153        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
154
155        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
156    }
157
158    /**
159     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
160     * video call, where an attempt is made to answer with an invalid video state.
161     *
162     * @throws Exception
163     */
164    public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
165        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
166                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
167
168        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
169        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
170
171        // Use TelecomManager API to answer the ringing call; the default expected behavior is to
172        // answer using whatever video state the ringing call requests.
173        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
174                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
175        telecomManager.acceptRingingCall(999 /* invalid videostate */);
176
177        // Answer video API should be called
178        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
179                .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
180        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
181        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
182    }
183
184    public void testSingleIncomingCallLocalDisconnect() throws Exception {
185        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
186                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
187        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
188        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
189        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
190
191        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
192        assertEquals(Call.STATE_DISCONNECTED,
193                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
194        assertEquals(Call.STATE_DISCONNECTED,
195                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
196    }
197
198    public void testSingleIncomingCallRemoteDisconnect() throws Exception {
199        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
200                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
201
202        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
203        assertEquals(Call.STATE_DISCONNECTED,
204                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
205        assertEquals(Call.STATE_DISCONNECTED,
206                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
207    }
208
209    public void do_testDeadlockOnOutgoingCall() throws Exception {
210        final IdPair ids = startOutgoingPhoneCall("650-555-1212",
211                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
212                Process.myUserHandle());
213        rapidFire(
214                new Runnable() {
215                    @Override
216                    public void run() {
217                        while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) {
218                            mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply();
219                        }
220                    }
221                },
222                new Runnable() {
223                    @Override
224                    public void run() {
225                        try {
226                            mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
227                        } catch (Exception e) {
228                            Log.e(this, e, "");
229                        }
230                    }
231                });
232    }
233
234    public void testDeadlockOnOutgoingCall() throws Exception {
235        for (int i = 0; i < 100; i++) {
236            BasicCallTests test = new BasicCallTests();
237            test.setContext(getContext());
238            test.setTestContext(getTestContext());
239            test.setName(getName());
240            test.setUp();
241            test.do_testDeadlockOnOutgoingCall();
242            test.tearDown();
243        }
244    }
245
246    public void testIncomingThenOutgoingCalls() throws Exception {
247        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
248        IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
249                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
250        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
251                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
252
253        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
254        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
255    }
256
257    public void testOutgoingThenIncomingCalls() throws Exception {
258        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
259        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
260                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
261        IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
262                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
263        verify(mConnectionServiceFixtureA.getTestDouble())
264                .hold(outgoing.mConnectionId);
265        mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
266                Connection.STATE_HOLDING;
267        mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId);
268        assertEquals(Call.STATE_HOLDING,
269                mInCallServiceFixtureX.getCall(outgoing.mCallId).getState());
270        assertEquals(Call.STATE_HOLDING,
271                mInCallServiceFixtureY.getCall(outgoing.mCallId).getState());
272
273        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
274        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
275    }
276
277    public void testAudioManagerOperations() throws Exception {
278        AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble()
279                .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
280
281        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
282                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
283
284        verify(audioManager, timeout(TEST_TIMEOUT)).requestAudioFocusForCall(anyInt(), anyInt());
285        verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
286                .setMode(AudioManager.MODE_IN_CALL);
287
288        mInCallServiceFixtureX.mInCallAdapter.mute(true);
289        verify(mAudioService, timeout(TEST_TIMEOUT))
290                .setMicrophoneMute(eq(true), any(String.class), any(Integer.class));
291        mInCallServiceFixtureX.mInCallAdapter.mute(false);
292        verify(mAudioService, timeout(TEST_TIMEOUT))
293                .setMicrophoneMute(eq(false), any(String.class), any(Integer.class));
294
295        mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
296        verify(audioManager, timeout(TEST_TIMEOUT))
297                .setSpeakerphoneOn(true);
298        mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE);
299        verify(audioManager, timeout(TEST_TIMEOUT))
300                .setSpeakerphoneOn(false);
301
302        mConnectionServiceFixtureA.
303                sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE);
304
305        verify(audioManager, timeout(TEST_TIMEOUT))
306                .abandonAudioFocusForCall();
307        verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
308                .setMode(AudioManager.MODE_NORMAL);
309    }
310
311    private void rapidFire(Runnable... tasks) {
312        final CyclicBarrier barrier = new CyclicBarrier(tasks.length);
313        final CountDownLatch latch = new CountDownLatch(tasks.length);
314        for (int i = 0; i < tasks.length; i++) {
315            final Runnable task = tasks[i];
316            new Thread(new Runnable() {
317                @Override
318                public void run() {
319                    try {
320                        barrier.await();
321                        task.run();
322                    } catch (InterruptedException | BrokenBarrierException e){
323                        Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
324                    } finally {
325                        latch.countDown();
326                    }
327                }
328            }).start();
329        }
330        try {
331            latch.await();
332        } catch (InterruptedException e) {
333            Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
334        }
335    }
336
337    public void testBasicConferenceCall() throws Exception {
338        makeConferenceCall();
339    }
340
341    public void testAddCallToConference1() throws Exception {
342        ParcelableCall conferenceCall = makeConferenceCall();
343        IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
344                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
345        // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
346        mInCallServiceFixtureX.getInCallAdapter().conference(
347                conferenceCall.getId(), callId3.mCallId);
348        Thread.sleep(200);
349
350        ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
351        ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
352        assertEquals(conferenceCall.getId(), call3.getParentCallId());
353        assertEquals(3, updatedConference.getChildCallIds().size());
354        assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
355    }
356
357    public void testAddCallToConference2() throws Exception {
358        ParcelableCall conferenceCall = makeConferenceCall();
359        IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
360                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
361        mInCallServiceFixtureX.getInCallAdapter()
362                .conference(callId3.mCallId, conferenceCall.getId());
363        Thread.sleep(200);
364
365        ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
366        ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
367        assertEquals(conferenceCall.getId(), call3.getParentCallId());
368        assertEquals(3, updatedConference.getChildCallIds().size());
369        assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
370    }
371
372    private ParcelableCall makeConferenceCall() throws Exception {
373        IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212",
374                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
375
376        IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213",
377                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
378
379        IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
380        inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
381        // Wait for wacky non-deterministic behavior
382        Thread.sleep(200);
383        ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId);
384        ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId);
385        // Check that the two calls end up with a parent in the end
386        assertNotNull(call1.getParentCallId());
387        assertNotNull(call2.getParentCallId());
388        assertEquals(call1.getParentCallId(), call2.getParentCallId());
389
390        // Check to make sure that the parent call made it to the in-call service
391        String parentCallId = call1.getParentCallId();
392        ParcelableCall conferenceCall = mInCallServiceFixtureX.getCall(parentCallId);
393        assertEquals(2, conferenceCall.getChildCallIds().size());
394        assertTrue(conferenceCall.getChildCallIds().contains(callId1.mCallId));
395        assertTrue(conferenceCall.getChildCallIds().contains(callId2.mCallId));
396        return conferenceCall;
397    }
398
399    public void testAnalyticsSingleCall() throws Exception {
400        IdPair testCall = startAndMakeActiveIncomingCall(
401                "650-555-1212",
402                mPhoneAccountA0.getAccountHandle(),
403                mConnectionServiceFixtureA);
404        Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
405
406        assertTrue(analyticsMap.containsKey(testCall.mCallId));
407
408        Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId);
409        assertTrue(callAnalytics.startTime > 0);
410        assertEquals(0, callAnalytics.endTime);
411        assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection);
412        assertFalse(callAnalytics.isInterrupted);
413        assertNull(callAnalytics.callTerminationReason);
414        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
415                callAnalytics.connectionService);
416
417        mConnectionServiceFixtureA.
418                sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
419
420        analyticsMap = Analytics.cloneData();
421        callAnalytics = analyticsMap.get(testCall.mCallId);
422        assertTrue(callAnalytics.endTime > 0);
423        assertNotNull(callAnalytics.callTerminationReason);
424        assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode());
425
426        StringWriter sr = new StringWriter();
427        IndentingPrintWriter ip = new IndentingPrintWriter(sr, "    ");
428        Analytics.dump(ip);
429        String dumpResult = sr.toString();
430        String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall",
431                "isInterrupted", "callTechnologies", "callTerminationReason", "connectionService"};
432        for (String field : expectedFields) {
433            assertTrue(dumpResult.contains(field));
434        }
435    }
436
437    public void testAnalyticsDumping() throws Exception {
438        Analytics.reset();
439        IdPair testCall = startAndMakeActiveIncomingCall(
440                "650-555-1212",
441                mPhoneAccountA0.getAccountHandle(),
442                mConnectionServiceFixtureA);
443
444        mConnectionServiceFixtureA.
445                sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
446        Analytics.CallInfoImpl expectedAnalytics = Analytics.cloneData().get(testCall.mCallId);
447
448        TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE);
449        List<ParcelableCallAnalytics> analyticsList = tm.dumpAnalytics();
450
451        assertEquals(1, analyticsList.size());
452        ParcelableCallAnalytics pCA = analyticsList.get(0);
453
454        assertTrue(Math.abs(expectedAnalytics.startTime - pCA.getStartTimeMillis()) <
455                ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
456        assertEquals(0, pCA.getStartTimeMillis() % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES);
457        assertTrue(Math.abs((expectedAnalytics.endTime - expectedAnalytics.startTime) -
458                pCA.getCallDurationMillis()) < ParcelableCallAnalytics.MILLIS_IN_1_SECOND);
459        assertEquals(0, pCA.getCallDurationMillis() % ParcelableCallAnalytics.MILLIS_IN_1_SECOND);
460
461        assertEquals(expectedAnalytics.callDirection, pCA.getCallType());
462        assertEquals(expectedAnalytics.isAdditionalCall, pCA.isAdditionalCall());
463        assertEquals(expectedAnalytics.isInterrupted, pCA.isInterrupted());
464        assertEquals(expectedAnalytics.callTechnologies, pCA.getCallTechnologies());
465        assertEquals(expectedAnalytics.callTerminationReason.getCode(),
466                pCA.getCallTerminationCode());
467        assertEquals(expectedAnalytics.connectionService, pCA.getConnectionService());
468    }
469
470    public void testAnalyticsTwoCalls() throws Exception {
471        IdPair testCall1 = startAndMakeActiveIncomingCall(
472                "650-555-1212",
473                mPhoneAccountA0.getAccountHandle(),
474                mConnectionServiceFixtureA);
475        IdPair testCall2 = startAndMakeActiveOutgoingCall(
476                "650-555-1213",
477                mPhoneAccountA0.getAccountHandle(),
478                mConnectionServiceFixtureA);
479
480        Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
481        assertTrue(analyticsMap.containsKey(testCall1.mCallId));
482        assertTrue(analyticsMap.containsKey(testCall2.mCallId));
483
484        Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId);
485        Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId);
486        assertTrue(callAnalytics1.startTime > 0);
487        assertTrue(callAnalytics2.startTime > 0);
488        assertEquals(0, callAnalytics1.endTime);
489        assertEquals(0, callAnalytics2.endTime);
490
491        assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection);
492        assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection);
493
494        assertTrue(callAnalytics1.isInterrupted);
495        assertTrue(callAnalytics2.isAdditionalCall);
496
497        assertNull(callAnalytics1.callTerminationReason);
498        assertNull(callAnalytics2.callTerminationReason);
499
500        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
501                callAnalytics1.connectionService);
502        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
503                callAnalytics1.connectionService);
504
505        mConnectionServiceFixtureA.
506                sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE);
507        mConnectionServiceFixtureA.
508                sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR);
509
510        analyticsMap = Analytics.cloneData();
511        callAnalytics1 = analyticsMap.get(testCall1.mCallId);
512        callAnalytics2 = analyticsMap.get(testCall2.mCallId);
513        assertTrue(callAnalytics1.endTime > 0);
514        assertTrue(callAnalytics2.endTime > 0);
515        assertNotNull(callAnalytics1.callTerminationReason);
516        assertNotNull(callAnalytics2.callTerminationReason);
517        assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode());
518        assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode());
519    }
520}
521