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