GsmCdmaCallTrackerTest.java revision e97fb0b4ff012fe960c36d7cb09311550c7d4055
1/*
2 * Copyright (C) 2016 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 */
16package com.android.internal.telephony;
17
18import android.os.HandlerThread;
19import android.telephony.DisconnectCause;
20import android.telephony.PhoneNumberUtils;
21import android.telephony.ServiceState;
22import android.test.suitebuilder.annotation.MediumTest;
23import android.test.suitebuilder.annotation.SmallTest;
24
25import android.os.Message;
26import org.junit.After;
27import org.junit.Assert;
28import org.junit.Before;
29import org.junit.Test;
30import org.mockito.Mock;
31import org.mockito.ArgumentCaptor;
32import android.os.Handler;
33
34import static org.junit.Assert.assertNotNull;
35import static org.mockito.Mockito.doReturn;
36import static org.junit.Assert.assertEquals;
37import static org.mockito.Mockito.*;
38import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
39
40
41public class GsmCdmaCallTrackerTest extends TelephonyTest {
42    private static final int VOICE_CALL_STARTED_EVENT = 0;
43    private static final int VOICE_CALL_ENDED_EVENT = 1;
44    private String mDialString = PhoneNumberUtils.stripSeparators("+17005554141");
45    /* Handler class initiated at the HandlerThread */
46    private GsmCdmaCallTracker mCTUT;
47    @Mock
48    GsmCdmaCall mCall;
49    @Mock
50    private Handler mHandler;
51
52    private class GsmCdmaCTHandlerThread extends HandlerThread {
53
54        private GsmCdmaCTHandlerThread(String name) {
55            super(name);
56        }
57        @Override
58        public void onLooperPrepared() {
59            mCTUT = new GsmCdmaCallTracker(mPhone);
60            setReady(true);
61        }
62    }
63
64    @Before
65    public void setUp() throws Exception {
66        super.setUp(this.getClass().getSimpleName());
67        mSimulatedCommands.setRadioPower(true, null);
68        mPhone.mCi = this.mSimulatedCommands;
69        mContextFixture.putStringArrayResource(com.android.internal.R.array.dial_string_replace,
70                new String[]{});
71
72        new GsmCdmaCTHandlerThread(TAG).start();
73
74        waitUntilReady();
75        logd("GsmCdmaCallTracker initiated, waiting for Power on");
76        /* Make sure radio state is power on before dial.
77         * When radio state changed from off to on, CallTracker
78         * will poll result from RIL. Avoid dialing triggered at the same*/
79        waitForMs(100);
80    }
81
82    @After
83    public void tearDown() throws Exception {
84        mCTUT = null;
85        super.tearDown();
86    }
87
88    @Test
89    @SmallTest
90    public void testMOCallDial() {
91        doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState();
92        assertEquals(PhoneConstants.State.IDLE, mCTUT.getState());
93        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mForegroundCall.getState());
94        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mBackgroundCall.getState());
95        assertEquals(0, mCTUT.mForegroundCall.getConnections().size());
96        try {
97            mCTUT.dial(mDialString);
98        } catch(Exception ex) {
99            ex.printStackTrace();
100            Assert.fail("unexpected exception thrown"+ex.getMessage()+ex.getStackTrace());
101        }
102
103        assertEquals(PhoneConstants.State.OFFHOOK, mCTUT.getState());
104        assertEquals(GsmCdmaCall.State.DIALING, mCTUT.mForegroundCall.getState());
105        assertEquals(1, mCTUT.mForegroundCall.getConnections().size());
106        /* verify the command is sent out to RIL */
107        verify(mSimulatedCommandsVerifier).dial(eq(PhoneNumberUtils.
108                        extractNetworkPortionAlt(mDialString)), anyInt(),
109                eq((UUSInfo) null),
110                isA(Message.class));
111    }
112
113    @Test
114    @SmallTest
115    public void testMOCallPickUp() {
116        testMOCallDial();
117        logd("Waiting for POLL CALL response from RIL");
118        TelephonyTestUtils.waitForMs(50);
119        logd("Pick Up MO call, expecting call state change event ");
120        mSimulatedCommands.progressConnectingToActive();
121        waitForMs(100);
122        assertEquals(GsmCdmaCall.State.ACTIVE, mCTUT.mForegroundCall.getState());
123        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mBackgroundCall.getState());
124    }
125
126    @Test
127    @MediumTest
128    public void testMOCallHangup() {
129        testMOCallDial();
130        logd("Waiting for POLL CALL response from RIL ");
131        TelephonyTestUtils.waitForMs(50);
132        assertEquals(GsmCdmaCall.State.DIALING, mCTUT.mForegroundCall.getState());
133        assertEquals(PhoneConstants.State.OFFHOOK, mCTUT.getState());
134        assertEquals(1, mCTUT.mForegroundCall.getConnections().size());
135        logd("Hang up MO call after MO call established ");
136        try {
137            mCTUT.hangup(mCTUT.mForegroundCall);
138        } catch(Exception ex) {
139            ex.printStackTrace();
140            Assert.fail("unexpected exception thrown" + ex.getMessage());
141        }
142        waitForMs(300);
143        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mForegroundCall.getState());
144        assertEquals(0, mCTUT.mForegroundCall.getConnections().size());
145        assertEquals(PhoneConstants.State.IDLE, mCTUT.getState());
146    }
147
148    @Test
149    @MediumTest
150    public void testMOCallDialPickUpHangup() {
151        testMOCallPickUp();
152        assertEquals(GsmCdmaCall.State.ACTIVE, mCTUT.mForegroundCall.getState());
153        assertEquals(PhoneConstants.State.OFFHOOK, mCTUT.getState());
154        assertEquals(1, mCTUT.mForegroundCall.getConnections().size());
155         /* get the reference of the connection before reject */
156        Connection mConnection = mCTUT.mForegroundCall.getConnections().get(0);
157        assertEquals(DisconnectCause.NOT_DISCONNECTED, mConnection.getDisconnectCause());
158        logd("hang up MO call after pickup");
159        try {
160            mCTUT.hangup(mCTUT.mForegroundCall);
161        } catch(Exception ex) {
162            ex.printStackTrace();
163            Assert.fail("unexpected exception thrown" + ex.getMessage());
164        }
165        /* request send to RIL still in disconnecting state */
166        waitForMs(300);
167        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mForegroundCall.getState());
168        assertEquals(0, mCTUT.mForegroundCall.getConnections().size());
169        assertEquals(PhoneConstants.State.IDLE, mCTUT.getState());
170        assertEquals(DisconnectCause.LOCAL, mConnection.getDisconnectCause());
171
172    }
173
174    @Test
175    @MediumTest
176    public void testMOCallPendingHangUp() {
177        testMOCallDial();
178        logd("MO call hangup before established[ getting result from RIL ]");
179        /* poll call result from RIL, find that there is a pendingMO call,
180         * Didn't do anything for hangup, clear during handle poll result */
181        try {
182            mCTUT.hangup(mCTUT.mForegroundCall);
183        } catch(Exception ex) {
184            ex.printStackTrace();
185            Assert.fail("unexpected exception thrown" + ex.getMessage());
186        }
187        waitForMs(300);
188        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mForegroundCall.getState());
189        assertEquals(0, mCTUT.mForegroundCall.getConnections().size());
190        assertEquals(PhoneConstants.State.IDLE, mCTUT.getState());
191    }
192
193    @Test
194    @MediumTest
195    public void testMOCallSwitch() {
196        testMOCallPickUp();
197        logd("MO call picked up, initiating a new MO call");
198        assertEquals(GsmCdmaCall.State.ACTIVE, mCTUT.mForegroundCall.getState());
199        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mBackgroundCall.getState());
200        assertEquals(1, mCTUT.mForegroundCall.getConnections().size());
201        assertEquals(0, mCTUT.mBackgroundCall.getConnections().size());
202
203        String mDialString = PhoneNumberUtils.stripSeparators("+17005554142");
204        try {
205            mCTUT.dial(mDialString);
206        } catch(Exception ex) {
207            ex.printStackTrace();
208            Assert.fail("unexpected exception thrown" + ex.getMessage());
209        }
210        waitForMs(200);
211        assertEquals(GsmCdmaCall.State.DIALING, mCTUT.mForegroundCall.getState());
212        assertEquals(GsmCdmaCall.State.HOLDING, mCTUT.mBackgroundCall.getState());
213        assertEquals(1, mCTUT.mForegroundCall.getConnections().size());
214        assertEquals(1, mCTUT.mBackgroundCall.getConnections().size());
215
216    }
217
218    @Test
219    @SmallTest
220    public void testMTCallRinging() {
221        /* Mock there is a MT call mRinging call and try to accept this MT call */
222        /* if we got a active state followed by another MT call-> move to background call */
223        assertEquals(PhoneConstants.State.IDLE, mCTUT.getState());
224        assertEquals(0, mCTUT.mRingingCall.getConnections().size());
225        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mForegroundCall.getState());
226        String mDialString = PhoneNumberUtils.stripSeparators("+17005554141");
227        logd("MT call Ringing");
228        mSimulatedCommands.triggerRing(mDialString);
229        waitForMs(50);
230        assertEquals(PhoneConstants.State.RINGING, mCTUT.getState());
231        assertEquals(1, mCTUT.mRingingCall.getConnections().size());
232    }
233
234    @Test
235    @SmallTest
236    public void testMTCallAccept() {
237        testMTCallRinging();
238        assertEquals(mCTUT.mForegroundCall.getConnections().size(),0);
239        logd("accept the MT call");
240        try{
241            mCTUT.acceptCall();
242        } catch(Exception ex) {
243            ex.printStackTrace();
244            Assert.fail("unexpected exception thrown" + ex.getMessage());
245        }
246        verify(mSimulatedCommandsVerifier).acceptCall(isA(Message.class));
247        /* send to the RIL */
248        TelephonyTestUtils.waitForMs(50);
249        assertEquals(PhoneConstants.State.OFFHOOK, mCTUT.getState());
250        assertEquals(GsmCdmaCall.State.ACTIVE, mCTUT.mForegroundCall.getState());
251        assertEquals(1, mCTUT.mForegroundCall.getConnections().size());
252        assertEquals(0, mCTUT.mRingingCall.getConnections().size());
253    }
254
255    @Test
256    @SmallTest
257    public void testMTCallReject() {
258        testMTCallRinging();
259        logd("MT call ringing and rejected ");
260        /* get the reference of the connection before reject */
261        Connection mConnection = mCTUT.mRingingCall.getConnections().get(0);
262        assertNotNull(mConnection);
263        assertEquals(DisconnectCause.NOT_DISCONNECTED, mConnection.getDisconnectCause());
264        try {
265            mCTUT.rejectCall();
266        } catch(Exception ex) {
267            ex.printStackTrace();
268            Assert.fail("unexpected exception thrown" + ex.getMessage());
269        }
270        waitForMs(50);
271        assertEquals(PhoneConstants.State.IDLE, mCTUT.getState());
272        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mForegroundCall.getState());
273        assertEquals(0, mCTUT.mForegroundCall.getConnections().size());
274        /* ? why rejectCall didnt -> hang up locally to set the cause to LOCAL? */
275        assertEquals(DisconnectCause.INCOMING_MISSED, mConnection.getDisconnectCause());
276
277    }
278
279    @Test
280    @MediumTest
281    public void testMOCallSwitchHangupForeGround() {
282        testMOCallSwitch();
283        logd("Hang up the foreground MO call while dialing ");
284        try {
285            mCTUT.hangup(mCTUT.mForegroundCall);
286        } catch(Exception ex) {
287            ex.printStackTrace();
288            Assert.fail("unexpected exception thrown" + ex.getMessage());
289        }
290        waitForMs(300);
291        logd(" Foreground Call is IDLE and BackGround Call is still HOLDING ");
292        /* if we want to hang up foreground call which is alerting state, hangup all */
293        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mForegroundCall.getState());
294        assertEquals(GsmCdmaCall.State.HOLDING, mCTUT.mBackgroundCall.getState());
295    }
296
297    @Test
298    @MediumTest
299    public void testMOCallPickUpHangUpResumeBackGround() {
300        testMOCallSwitch();
301        logd("Pick up the new MO Call");
302        try{
303            mSimulatedCommands.progressConnectingToActive();
304        } catch(Exception ex) {
305            ex.printStackTrace();
306            Assert.fail("unexpected exception thrown" + ex.getMessage());
307        }
308
309        waitForMs(200);
310        assertEquals(GsmCdmaCall.State.ACTIVE, mCTUT.mForegroundCall.getState());
311        assertEquals(GsmCdmaCall.State.HOLDING, mCTUT.mBackgroundCall.getState());
312
313        logd("Hang up the new MO Call");
314        try {
315            mCTUT.hangup(mCTUT.mForegroundCall);
316        } catch(Exception ex) {
317            ex.printStackTrace();
318            Assert.fail("unexpected exception thrown" + ex.getMessage());
319        }
320
321        waitForMs(300);
322        logd(" BackGround Call switch to ForeGround Call ");
323        assertEquals(GsmCdmaCall.State.ACTIVE, mCTUT.mForegroundCall.getState());
324        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mBackgroundCall.getState());
325    }
326
327    @Test @SmallTest
328    public void testVoiceCallStartListener(){
329        logd("register for voice call started event");
330        mCTUT.registerForVoiceCallStarted(mHandler, VOICE_CALL_STARTED_EVENT, null);
331        logd("voice call started");
332        testMOCallPickUp();
333        ArgumentCaptor<Message> mCaptorMessage = ArgumentCaptor.forClass(Message.class);
334        ArgumentCaptor<Long> mCaptorLong = ArgumentCaptor.forClass(Long.class);
335        verify(mHandler,times(1)).sendMessageAtTime(mCaptorMessage.capture(), mCaptorLong.capture());
336        assertEquals(VOICE_CALL_STARTED_EVENT, mCaptorMessage.getValue().what);
337
338    }
339
340    @Test @SmallTest
341    public void testVoiceCallEndedListener(){
342        logd("register for voice call ended event");
343        mCTUT.registerForVoiceCallEnded(mHandler, VOICE_CALL_ENDED_EVENT, null);
344        ArgumentCaptor<Message> mCaptorMessage = ArgumentCaptor.forClass(Message.class);
345        ArgumentCaptor<Long> mCaptorLong = ArgumentCaptor.forClass(Long.class);
346        testMOCallHangup();
347        verify(mHandler,times(1)).sendMessageAtTime(mCaptorMessage.capture(), mCaptorLong.capture());
348        assertEquals(VOICE_CALL_ENDED_EVENT, mCaptorMessage.getValue().what);
349    }
350
351    @Test @SmallTest
352    public void testUpdatePhoneType() {
353        // verify getCurrentCalls is called on init
354        verify(mSimulatedCommandsVerifier).getCurrentCalls(any(Message.class));
355
356        // update phone type (call the function on same thread as the call tracker)
357        Handler updatePhoneTypeHandler = new Handler(mCTUT.getLooper()) {
358            @Override
359            public void handleMessage(Message msg) {
360                mCTUT.updatePhoneType();
361            }
362        };
363        updatePhoneTypeHandler.sendEmptyMessage(0);
364        waitForMs(100);
365
366        // verify getCurrentCalls is called on updating phone type
367        verify(mSimulatedCommandsVerifier, times(2)).getCurrentCalls(any(Message.class));
368
369        // we'd like to verify that if phone type is updated, calls and callTracker go to idle.
370        // However, as soon as phone type is updated, call tracker queries for calls from RIL and
371        // will go back to OFFHOOK
372
373        // call tracker goes to OFFHOOK
374        testMOCallPickUp();
375
376        // update phone type - call tracker goes to IDLE and then due to getCurrentCalls(),
377        // goes back to OFFHOOK
378        updatePhoneTypeHandler.sendEmptyMessage(0);
379        waitForMs(100);
380
381        // verify CT and calls go to idle
382        assertEquals(PhoneConstants.State.OFFHOOK, mCTUT.getState());
383        assertEquals(GsmCdmaCall.State.ACTIVE, mCTUT.mForegroundCall.getState());
384        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mBackgroundCall.getState());
385        assertEquals(GsmCdmaCall.State.IDLE, mCTUT.mRingingCall.getState());
386    }
387}
388
389