a255f263d103327c9d5ea6d3f8b140670d324a0b
[android/platform/frameworks/opt/telephony.git] / tests / telephonytests / src / com / android / internal / telephony / CallManagerTest.java
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  */
16 package com.android.internal.telephony;
17
18 import android.os.Handler;
19 import android.os.HandlerThread;
20 import android.os.Message;
21 import android.telephony.PhoneNumberUtils;
22 import android.telephony.ServiceState;
23 import android.test.suitebuilder.annotation.SmallTest;
24
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.mockito.ArgumentCaptor;
29 import org.mockito.Mock;
30 import org.mockito.Mockito;
31
32 import java.lang.reflect.Field;
33
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.assertFalse;
36 import static org.junit.Assert.assertTrue;
37 import static org.mockito.Matchers.anyBoolean;
38 import static org.mockito.Matchers.anyInt;
39 import static org.mockito.Matchers.eq;
40 import static org.mockito.Matchers.isA;
41 import static org.mockito.Matchers.isNull;
42 import static org.mockito.Mockito.doReturn;
43 import static org.mockito.Mockito.times;
44 import static org.mockito.Mockito.verify;
45 import static org.mockito.Mockito.mock;
46 import static org.mockito.Mockito.any;
47 import static org.mockito.Mockito.anyChar;
48 import static org.mockito.Mockito.anyString;
49
50 public class CallManagerTest extends TelephonyTest {
51
52     @Mock
53     GsmCdmaCall mFgCall;
54     @Mock
55     GsmCdmaCall mBgCall;
56     @Mock
57     GsmCdmaCall mRingingCall;
58     @Mock
59     Phone mSecondPhone;
60
61     private CallManagerHandlerThread mCallManagerHandlerThread;
62     private Handler mHandler;
63     private static final int PHONE_REGISTER_EVENT = 0;
64
65     private class CallManagerHandlerThread extends HandlerThread {
66         private CallManagerHandlerThread(String name) {
67             super(name);
68         }
69         @Override
70         public void onLooperPrepared() {
71             /* CallManager is a static object with private constructor,no need call constructor */
72             registerForPhone(mPhone);
73
74             // create a custom handler for the Handler Thread
75             mHandler = new Handler(mCallManagerHandlerThread.getLooper()) {
76                 @Override
77                 public void handleMessage(Message msg) {
78                     switch (msg.what) {
79                         case PHONE_REGISTER_EVENT:
80                             logd("Phone registered with CallManager");
81                             registerForPhone((Phone) msg.obj);
82                             setReady(true);
83                             break;
84                         default:
85                             logd("Unknown Event " + msg.what);
86                     }
87                 }
88             };
89
90             setReady(true);
91         }
92
93         private void registerForPhone(Phone mPhone) {
94             CallManager.getInstance().registerPhone(mPhone);
95         }
96     }
97
98     @Before
99     public void setUp() throws Exception {
100         super.setUp(this.getClass().getSimpleName());
101         restoreInstance(CallManager.class, "INSTANCE", null);
102         /* Mock Phone and Call, initially all calls are idle */
103         doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState();
104         doReturn(mBgCall).when(mPhone).getBackgroundCall();
105         doReturn(mFgCall).when(mPhone).getForegroundCall();
106         doReturn(mRingingCall).when(mPhone).getRingingCall();
107         doReturn(mPhone).when(mBgCall).getPhone();
108         doReturn(mPhone).when(mFgCall).getPhone();
109         doReturn(mPhone).when(mRingingCall).getPhone();
110         doReturn(Call.State.IDLE).when(mBgCall).getState();
111         doReturn(Call.State.IDLE).when(mFgCall).getState();
112         doReturn(Call.State.IDLE).when(mRingingCall).getState();
113         doReturn(true).when(mBgCall).isIdle();
114         doReturn(true).when(mFgCall).isIdle();
115         doReturn(true).when(mRingingCall).isIdle();
116
117         mCallManagerHandlerThread = new CallManagerHandlerThread(TAG);
118         mCallManagerHandlerThread.start();
119         waitUntilReady();
120     }
121
122     @After
123     public void tearDown() throws Exception {
124         CallManager.getInstance().unregisterPhone(mPhone);
125         mCallManagerHandlerThread.quitSafely();
126         super.tearDown();
127     }
128
129     @SmallTest @Test
130     public void testSanity() {
131         assertEquals(mPhone, CallManager.getInstance().getDefaultPhone());
132         assertFalse(CallManager.getInstance().hasActiveBgCall());
133         assertFalse(CallManager.getInstance().hasActiveRingingCall());
134         assertFalse(CallManager.getInstance().hasActiveFgCall());
135         /* return the default phone if there is no any active call */
136         assertEquals(mPhone, CallManager.getInstance().getRingingPhone());
137         assertEquals(mPhone, CallManager.getInstance().getBgPhone());
138         assertEquals(mPhone, CallManager.getInstance().getFgPhone());
139     }
140
141     @SmallTest @Test
142     public void testBasicDial() throws Exception {
143         //verify can dial and dial function of the phone is being triggered
144         CallManager.getInstance().dial(mPhone,
145                 PhoneNumberUtils.stripSeparators("+17005554141"), 0);
146         ArgumentCaptor<String> mCaptorString = ArgumentCaptor.forClass(String.class);
147         ArgumentCaptor<Integer> mCaptorInt = ArgumentCaptor.forClass(Integer.class);
148         verify(mPhone, times(1)).dial(mCaptorString.capture(), mCaptorInt.capture());
149         assertEquals(PhoneNumberUtils.stripSeparators("+17005554141"),
150                 mCaptorString.getValue());
151         assertEquals(0, mCaptorInt.getValue().intValue());
152     }
153
154     @SmallTest @Test
155     public void testBasicAcceptCall() throws Exception {
156         CallManager.getInstance().acceptCall(mRingingCall);
157         verify(mPhone, times(1)).acceptCall(anyInt());
158     }
159
160     @SmallTest @Test
161     public void testBasicRejectCall() throws Exception {
162         //verify can dial and dial function of the phone is being triggered
163         CallManager.getInstance().rejectCall(mRingingCall);
164         verify(mPhone, times(1)).rejectCall();
165     }
166
167     @SmallTest @Test
168     public void testSendDtmf() throws Exception {
169         CallManager.getInstance().sendDtmf('a');
170         verify(mPhone, times(0)).sendDtmf(eq('a'));
171
172         //has active fg Call
173         doReturn(false).when(mFgCall).isIdle();
174         assertEquals(mFgCall, CallManager.getInstance().getActiveFgCall());
175         CallManager.getInstance().sendDtmf('a');
176         verify(mPhone, times(1)).sendDtmf(eq('a'));
177     }
178
179     @SmallTest @Test
180     public void testStartDtmf() throws Exception {
181         doReturn(true).when(mFgCall).isIdle();
182         assertFalse(CallManager.getInstance().startDtmf('a'));
183         verify(mPhone, times(0)).startDtmf(anyChar());
184
185         //has active fg Call
186         doReturn(false).when(mFgCall).isIdle();
187         assertEquals(mFgCall, CallManager.getInstance().getActiveFgCall());
188         assertTrue(CallManager.getInstance().startDtmf('a'));
189         verify(mPhone, times(1)).startDtmf('a');
190     }
191
192     @SmallTest @Test
193     public void testStopDtmf() throws Exception {
194         doReturn(true).when(mFgCall).isIdle();
195         CallManager.getInstance().stopDtmf();
196         verify(mPhone, times(0)).stopDtmf();
197
198         //has active fg Call
199         doReturn(false).when(mFgCall).isIdle();
200         assertEquals(mPhone, CallManager.getInstance().getFgPhone());
201         CallManager.getInstance().stopDtmf();
202         verify(mPhone, times(1)).stopDtmf();
203     }
204
205     @SmallTest @Test
206     public void testSendBurstDtmf() throws Exception {
207         doReturn(true).when(mFgCall).isIdle();
208         assertFalse(CallManager.getInstance().sendBurstDtmf("12*#", 0, 0, null));
209         verify(mPhone, times(0)).sendBurstDtmf(anyString(), anyInt(), anyInt(), (Message) any());
210
211         //has active fg Call
212         doReturn(false).when(mFgCall).isIdle();
213         assertTrue(CallManager.getInstance().sendBurstDtmf("12*#", 0, 0, null));
214         verify(mPhone, times(1)).sendBurstDtmf("12*#", 0, 0, null);
215     }
216
217     @SmallTest @Test
218     public void testSetGetMute() throws Exception {
219         CallManager.getInstance().setMute(false);
220         verify(mPhone, times(0)).setMute(anyBoolean());
221
222         //has active fg Call
223         doReturn(false).when(mFgCall).isIdle();
224         CallManager.getInstance().setMute(false);
225         verify(mPhone, times(1)).setMute(false);
226
227         CallManager.getInstance().setMute(true);
228         verify(mPhone, times(1)).setMute(true);
229     }
230
231     @SmallTest @Test
232     public void testSwitchHoldingAndActive() throws Exception {
233         /* case 1: only active call */
234         doReturn(false).when(mFgCall).isIdle();
235         CallManager.getInstance().switchHoldingAndActive(null);
236         verify(mPhone, times(1)).switchHoldingAndActive();
237         /* case 2: no active call but only held call, aka, unhold */
238         doReturn(true).when(mFgCall).isIdle();
239         CallManager.getInstance().switchHoldingAndActive(mBgCall);
240         verify(mPhone, times(2)).switchHoldingAndActive();
241         /* case 3: both active and held calls from same phone, aka, swap */
242         doReturn(false).when(mFgCall).isIdle();
243         CallManager.getInstance().switchHoldingAndActive(mBgCall);
244         verify(mPhone, times(3)).switchHoldingAndActive();
245         GsmCdmaPhone mPhoneHold = Mockito.mock(GsmCdmaPhone.class);
246         /* case 4: active and held calls from different phones, aka, phone swap */
247         doReturn(mPhoneHold).when(mBgCall).getPhone();
248         CallManager.getInstance().switchHoldingAndActive(mBgCall);
249         verify(mPhone, times(4)).switchHoldingAndActive();
250         verify(mPhoneHold, times(1)).switchHoldingAndActive();
251     }
252
253     @SmallTest @Test
254     public void testHangupForegroundResumeBackground() throws Exception {
255         CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
256         /* no active fgCall */
257         verify(mPhone, times(0)).switchHoldingAndActive();
258         verify(mFgCall, times(0)).hangup();
259
260         /* have active foreground call, get hanged up */
261         doReturn(false).when(mFgCall).isIdle();
262         CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
263         verify(mFgCall, times(1)).hangup();
264         verify(mPhone, times(0)).switchHoldingAndActive();
265
266         /* mock bgcall and fgcall from different phone */
267         GsmCdmaPhone mPhoneHold = Mockito.mock(GsmCdmaPhone.class);
268         doReturn(mPhoneHold).when(mBgCall).getPhone();
269         CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
270         verify(mFgCall, times(2)).hangup();
271         /* always hangup fgcall and both phone trigger swap */
272         verify(mPhoneHold, times(1)).switchHoldingAndActive();
273         verify(mPhone, times(1)).switchHoldingAndActive();
274     }
275
276     @SmallTest @Test
277     public void testFgCallActiveDial() throws Exception {
278         /* set Fg/Bg Call state to active, verify CallManager Logical */
279         doReturn(false).when(mFgCall).isIdle();
280         doReturn(false).when(mBgCall).isIdle();
281         assertTrue(CallManager.getInstance().hasActiveFgCall());
282         assertTrue(CallManager.getInstance().hasActiveBgCall());
283         assertTrue(CallManager.getInstance().hasActiveFgCall(mPhone.getSubId()));
284         assertFalse(CallManager.getInstance().hasDisconnectedFgCall());
285         /* try dial with non-idle foreground call and background call */
286         CallManager.getInstance().dial(mPhone,
287                 PhoneNumberUtils.stripSeparators("+17005554141"), 0);
288         ArgumentCaptor<String> mCaptorString = ArgumentCaptor.forClass(String.class);
289         ArgumentCaptor<Integer> mCaptorInt = ArgumentCaptor.forClass(Integer.class);
290
291         verify(mPhone, times(1)).dial(mCaptorString.capture(), mCaptorInt.capture());
292         assertEquals(PhoneNumberUtils.stripSeparators("+17005554141"),
293                 mCaptorString.getValue());
294         assertEquals(0, mCaptorInt.getValue().intValue());
295     }
296
297     @Test @SmallTest
298     public void testRegisterEvent() throws Exception {
299         Field field = CallManager.class.getDeclaredField("EVENT_CALL_WAITING");
300         field.setAccessible(true);
301         int mEvent = (Integer) field.get(CallManager.getInstance());
302         verify(mPhone, times(1)).registerForCallWaiting(isA(Handler.class),
303                 eq(mEvent), isNull());
304
305         field = CallManager.class.getDeclaredField("EVENT_PRECISE_CALL_STATE_CHANGED");
306         field.setAccessible(true);
307         mEvent = (Integer) field.get(CallManager.getInstance());
308         verify(mPhone, times(1)).registerForPreciseCallStateChanged(isA(Handler.class),
309                 eq(mEvent), isA(Object.class));
310
311         field = CallManager.class.getDeclaredField("EVENT_RINGBACK_TONE");
312         field.setAccessible(true);
313         mEvent = (Integer) field.get(CallManager.getInstance());
314         verify(mPhone, times(1)).registerForRingbackTone(isA(Handler.class),
315                 eq(mEvent), isA(Object.class));
316     }
317
318     @Test @SmallTest
319     public void testGetServiceState() throws Exception {
320         // register for another phone
321         ServiceState mSecondServiceState = mock(ServiceState.class);
322         doReturn(mSecondServiceState).when(mSecondPhone).getServiceState();
323
324         Message mRegisterPhone = mHandler.obtainMessage(PHONE_REGISTER_EVENT,
325                 mSecondPhone);
326         setReady(false);
327         mRegisterPhone.sendToTarget();
328
329         waitUntilReady();
330
331         // mPhone: STATE_IN_SERVICE > mPhoneSecond: state STATE_OUT_OF_SERVICE
332         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSecondServiceState).getState();
333         assertEquals(ServiceState.STATE_IN_SERVICE, CallManager.getInstance().getServiceState());
334
335         // mPhone: STATE_IN_SERVICE > mPhoneSecond: state STATE_EMERGENCY_ONLY
336         doReturn(ServiceState.STATE_EMERGENCY_ONLY).when(mSecondServiceState).getState();
337         assertEquals(ServiceState.STATE_IN_SERVICE, CallManager.getInstance().getServiceState());
338
339         // mPhone: STATE_IN_SERVICE > mPhoneSecond: state STATE_POWER_OFF
340         doReturn(ServiceState.STATE_POWER_OFF).when(mSecondServiceState).getState();
341         assertEquals(ServiceState.STATE_IN_SERVICE, CallManager.getInstance().getServiceState());
342
343         // mPhone: STATE_EMERGENCY_ONLY < mPhoneSecond: state STATE_OUT_OF_SERVICE
344         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSecondServiceState).getState();
345         doReturn(ServiceState.STATE_EMERGENCY_ONLY).when(mServiceState).getState();
346         assertEquals(ServiceState.STATE_OUT_OF_SERVICE,
347                 CallManager.getInstance().getServiceState());
348
349         // mPhone: STATE_POWER_OFF < mPhoneSecond: state STATE_OUT_OF_SERVICE
350         doReturn(ServiceState.STATE_POWER_OFF).when(mServiceState).getState();
351         assertEquals(ServiceState.STATE_OUT_OF_SERVICE,
352                 CallManager.getInstance().getServiceState());
353
354         /* mPhone: STATE_POWER_OFF < mPhoneSecond: state STATE_EMERGENCY_ONLY
355            but OUT_OF_SERVICE will replaces EMERGENCY_ONLY and POWER_OFF */
356         doReturn(ServiceState.STATE_EMERGENCY_ONLY).when(mSecondServiceState).getState();
357         assertEquals(ServiceState.STATE_OUT_OF_SERVICE,
358                 CallManager.getInstance().getServiceState());
359         CallManager.getInstance().unregisterPhone(mSecondPhone);
360     }
361 }