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