Home | History | Annotate | Download | only in telephony
      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.quit();
    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<PhoneInternalInterface.DialArgs> dialArgsCaptor =
    148                 ArgumentCaptor.forClass(PhoneInternalInterface.DialArgs.class);
    149         verify(mPhone, times(1)).dial(mCaptorString.capture(), dialArgsCaptor.capture());
    150         assertEquals(PhoneNumberUtils.stripSeparators("+17005554141"),
    151                 mCaptorString.getValue());
    152         assertEquals(0, dialArgsCaptor.getValue().videoState);
    153     }
    154 
    155     @SmallTest @Test
    156     public void testBasicAcceptCall() throws Exception {
    157         CallManager.getInstance().acceptCall(mRingingCall);
    158         verify(mPhone, times(1)).acceptCall(anyInt());
    159     }
    160 
    161     @SmallTest @Test
    162     public void testBasicRejectCall() throws Exception {
    163         //verify can dial and dial function of the phone is being triggered
    164         CallManager.getInstance().rejectCall(mRingingCall);
    165         verify(mPhone, times(1)).rejectCall();
    166     }
    167 
    168     @SmallTest @Test
    169     public void testSendDtmf() throws Exception {
    170         CallManager.getInstance().sendDtmf('a');
    171         verify(mPhone, times(0)).sendDtmf(eq('a'));
    172 
    173         //has active fg Call
    174         doReturn(false).when(mFgCall).isIdle();
    175         assertEquals(mFgCall, CallManager.getInstance().getActiveFgCall());
    176         CallManager.getInstance().sendDtmf('a');
    177         verify(mPhone, times(1)).sendDtmf(eq('a'));
    178     }
    179 
    180     @SmallTest @Test
    181     public void testStartDtmf() throws Exception {
    182         doReturn(true).when(mFgCall).isIdle();
    183         assertFalse(CallManager.getInstance().startDtmf('a'));
    184         verify(mPhone, times(0)).startDtmf(anyChar());
    185 
    186         //has active fg Call
    187         doReturn(false).when(mFgCall).isIdle();
    188         assertEquals(mFgCall, CallManager.getInstance().getActiveFgCall());
    189         assertTrue(CallManager.getInstance().startDtmf('a'));
    190         verify(mPhone, times(1)).startDtmf('a');
    191     }
    192 
    193     @SmallTest @Test
    194     public void testStopDtmf() throws Exception {
    195         doReturn(true).when(mFgCall).isIdle();
    196         CallManager.getInstance().stopDtmf();
    197         verify(mPhone, times(0)).stopDtmf();
    198 
    199         //has active fg Call
    200         doReturn(false).when(mFgCall).isIdle();
    201         assertEquals(mPhone, CallManager.getInstance().getFgPhone());
    202         CallManager.getInstance().stopDtmf();
    203         verify(mPhone, times(1)).stopDtmf();
    204     }
    205 
    206     @SmallTest @Test
    207     public void testSendBurstDtmf() throws Exception {
    208         doReturn(true).when(mFgCall).isIdle();
    209         assertFalse(CallManager.getInstance().sendBurstDtmf("12*#", 0, 0, null));
    210         verify(mPhone, times(0)).sendBurstDtmf(anyString(), anyInt(), anyInt(), (Message) any());
    211 
    212         //has active fg Call
    213         doReturn(false).when(mFgCall).isIdle();
    214         assertTrue(CallManager.getInstance().sendBurstDtmf("12*#", 0, 0, null));
    215         verify(mPhone, times(1)).sendBurstDtmf("12*#", 0, 0, null);
    216     }
    217 
    218     @SmallTest @Test
    219     public void testSetGetMute() throws Exception {
    220         CallManager.getInstance().setMute(false);
    221         verify(mPhone, times(0)).setMute(anyBoolean());
    222 
    223         //has active fg Call
    224         doReturn(false).when(mFgCall).isIdle();
    225         CallManager.getInstance().setMute(false);
    226         verify(mPhone, times(1)).setMute(false);
    227 
    228         CallManager.getInstance().setMute(true);
    229         verify(mPhone, times(1)).setMute(true);
    230     }
    231 
    232     @SmallTest @Test
    233     public void testSwitchHoldingAndActive() throws Exception {
    234         /* case 1: only active call */
    235         doReturn(false).when(mFgCall).isIdle();
    236         CallManager.getInstance().switchHoldingAndActive(null);
    237         verify(mPhone, times(1)).switchHoldingAndActive();
    238         /* case 2: no active call but only held call, aka, unhold */
    239         doReturn(true).when(mFgCall).isIdle();
    240         CallManager.getInstance().switchHoldingAndActive(mBgCall);
    241         verify(mPhone, times(2)).switchHoldingAndActive();
    242         /* case 3: both active and held calls from same phone, aka, swap */
    243         doReturn(false).when(mFgCall).isIdle();
    244         CallManager.getInstance().switchHoldingAndActive(mBgCall);
    245         verify(mPhone, times(3)).switchHoldingAndActive();
    246         GsmCdmaPhone mPhoneHold = Mockito.mock(GsmCdmaPhone.class);
    247         /* case 4: active and held calls from different phones, aka, phone swap */
    248         doReturn(mPhoneHold).when(mBgCall).getPhone();
    249         CallManager.getInstance().switchHoldingAndActive(mBgCall);
    250         verify(mPhone, times(4)).switchHoldingAndActive();
    251         verify(mPhoneHold, times(1)).switchHoldingAndActive();
    252     }
    253 
    254     @SmallTest @Test
    255     public void testHangupForegroundResumeBackground() throws Exception {
    256         CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
    257         /* no active fgCall */
    258         verify(mPhone, times(0)).switchHoldingAndActive();
    259         verify(mFgCall, times(0)).hangup();
    260 
    261         /* have active foreground call, get hanged up */
    262         doReturn(false).when(mFgCall).isIdle();
    263         CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
    264         verify(mFgCall, times(1)).hangup();
    265         verify(mPhone, times(0)).switchHoldingAndActive();
    266 
    267         /* mock bgcall and fgcall from different phone */
    268         GsmCdmaPhone mPhoneHold = Mockito.mock(GsmCdmaPhone.class);
    269         doReturn(mPhoneHold).when(mBgCall).getPhone();
    270         CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
    271         verify(mFgCall, times(2)).hangup();
    272         /* always hangup fgcall and both phone trigger swap */
    273         verify(mPhoneHold, times(1)).switchHoldingAndActive();
    274         verify(mPhone, times(1)).switchHoldingAndActive();
    275     }
    276 
    277     @SmallTest @Test
    278     public void testFgCallActiveDial() throws Exception {
    279         /* set Fg/Bg Call state to active, verify CallManager Logical */
    280         doReturn(false).when(mFgCall).isIdle();
    281         doReturn(false).when(mBgCall).isIdle();
    282         assertTrue(CallManager.getInstance().hasActiveFgCall());
    283         assertTrue(CallManager.getInstance().hasActiveBgCall());
    284         assertTrue(CallManager.getInstance().hasActiveFgCall(mPhone.getSubId()));
    285         assertFalse(CallManager.getInstance().hasDisconnectedFgCall());
    286         /* try dial with non-idle foreground call and background call */
    287         CallManager.getInstance().dial(mPhone,
    288                 PhoneNumberUtils.stripSeparators("+17005554141"), 0);
    289         ArgumentCaptor<String> mCaptorString = ArgumentCaptor.forClass(String.class);
    290         ArgumentCaptor<PhoneInternalInterface.DialArgs> dialArgsCaptor =
    291                 ArgumentCaptor.forClass(PhoneInternalInterface.DialArgs.class);
    292 
    293         verify(mPhone, times(1)).dial(mCaptorString.capture(), dialArgsCaptor.capture());
    294         assertEquals(PhoneNumberUtils.stripSeparators("+17005554141"),
    295                 mCaptorString.getValue());
    296         assertEquals(0, dialArgsCaptor.getValue().videoState);
    297     }
    298 
    299     @Test @SmallTest
    300     public void testRegisterEvent() throws Exception {
    301         Field field = CallManager.class.getDeclaredField("EVENT_CALL_WAITING");
    302         field.setAccessible(true);
    303         int mEvent = (Integer) field.get(CallManager.getInstance());
    304         verify(mPhone, times(1)).registerForCallWaiting(isA(Handler.class),
    305                 eq(mEvent), isNull());
    306 
    307         field = CallManager.class.getDeclaredField("EVENT_PRECISE_CALL_STATE_CHANGED");
    308         field.setAccessible(true);
    309         mEvent = (Integer) field.get(CallManager.getInstance());
    310         verify(mPhone, times(1)).registerForPreciseCallStateChanged(isA(Handler.class),
    311                 eq(mEvent), isA(Object.class));
    312 
    313         field = CallManager.class.getDeclaredField("EVENT_RINGBACK_TONE");
    314         field.setAccessible(true);
    315         mEvent = (Integer) field.get(CallManager.getInstance());
    316         verify(mPhone, times(1)).registerForRingbackTone(isA(Handler.class),
    317                 eq(mEvent), isA(Object.class));
    318     }
    319 
    320     @Test @SmallTest
    321     public void testGetServiceState() throws Exception {
    322         // register for another phone
    323         ServiceState mSecondServiceState = mock(ServiceState.class);
    324         doReturn(mSecondServiceState).when(mSecondPhone).getServiceState();
    325 
    326         Message mRegisterPhone = mHandler.obtainMessage(PHONE_REGISTER_EVENT,
    327                 mSecondPhone);
    328         setReady(false);
    329         mRegisterPhone.sendToTarget();
    330 
    331         waitUntilReady();
    332 
    333         // mPhone: STATE_IN_SERVICE > mPhoneSecond: state STATE_OUT_OF_SERVICE
    334         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSecondServiceState).getState();
    335         assertEquals(ServiceState.STATE_IN_SERVICE, CallManager.getInstance().getServiceState());
    336 
    337         // mPhone: STATE_IN_SERVICE > mPhoneSecond: state STATE_EMERGENCY_ONLY
    338         doReturn(ServiceState.STATE_EMERGENCY_ONLY).when(mSecondServiceState).getState();
    339         assertEquals(ServiceState.STATE_IN_SERVICE, CallManager.getInstance().getServiceState());
    340 
    341         // mPhone: STATE_IN_SERVICE > mPhoneSecond: state STATE_POWER_OFF
    342         doReturn(ServiceState.STATE_POWER_OFF).when(mSecondServiceState).getState();
    343         assertEquals(ServiceState.STATE_IN_SERVICE, CallManager.getInstance().getServiceState());
    344 
    345         // mPhone: STATE_EMERGENCY_ONLY < mPhoneSecond: state STATE_OUT_OF_SERVICE
    346         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSecondServiceState).getState();
    347         doReturn(ServiceState.STATE_EMERGENCY_ONLY).when(mServiceState).getState();
    348         assertEquals(ServiceState.STATE_OUT_OF_SERVICE,
    349                 CallManager.getInstance().getServiceState());
    350 
    351         // mPhone: STATE_POWER_OFF < mPhoneSecond: state STATE_OUT_OF_SERVICE
    352         doReturn(ServiceState.STATE_POWER_OFF).when(mServiceState).getState();
    353         assertEquals(ServiceState.STATE_OUT_OF_SERVICE,
    354                 CallManager.getInstance().getServiceState());
    355 
    356         /* mPhone: STATE_POWER_OFF < mPhoneSecond: state STATE_EMERGENCY_ONLY
    357            but OUT_OF_SERVICE will replaces EMERGENCY_ONLY and POWER_OFF */
    358         doReturn(ServiceState.STATE_EMERGENCY_ONLY).when(mSecondServiceState).getState();
    359         assertEquals(ServiceState.STATE_OUT_OF_SERVICE,
    360                 CallManager.getInstance().getServiceState());
    361         CallManager.getInstance().unregisterPhone(mSecondPhone);
    362     }
    363 }
    364