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