/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
import static com.android.internal.telephony.Phone.EVENT_ICC_CHANGED;
import static com.android.internal.telephony.Phone.EVENT_SRVCC_STATE_CHANGED;
import static com.android.internal.telephony.Phone.EVENT_UICC_APPS_ENABLEMENT_STATUS_CHANGED;
import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.nullable;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import android.os.WorkSource;
import android.preference.PreferenceManager;
import android.telecom.VideoProfile;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityCdma;
import android.telephony.CellIdentityGsm;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

import androidx.test.filters.FlakyTest;

import com.android.internal.telephony.test.SimulatedCommands;
import com.android.internal.telephony.uicc.IccCardApplicationStatus;
import com.android.internal.telephony.uicc.IccCardStatus;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.IccVmNotSupportedException;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.UiccProfile;
import com.android.internal.telephony.uicc.UiccSlot;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;

import java.util.List;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class GsmCdmaPhoneTest extends TelephonyTest {
    @Mock
    private Handler mTestHandler;
    @Mock
    private UiccSlot mUiccSlot;
    @Mock
    private CommandsInterface mMockCi;

    //mPhoneUnderTest
    private GsmCdmaPhone mPhoneUT;

    private static final int EVENT_EMERGENCY_CALLBACK_MODE_EXIT = 1;
    private static final int EVENT_EMERGENCY_CALL_TOGGLE = 2;
    private static final int EVENT_SET_ICC_LOCK_ENABLED = 3;

    private void switchToGsm() {
        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_VOICE_RADIO_TECH_CHANGED,
                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_GSM}, null)));
        processAllMessages();
        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
    }

    private void switchToCdma() {
        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_IS95A);
        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_VOICE_RADIO_TECH_CHANGED,
                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_IS95A}, null)));
        processAllMessages();
        assertEquals(PhoneConstants.PHONE_TYPE_CDMA, mPhoneUT.getPhoneType());
    }

    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());

        doReturn(false).when(mSST).isDeviceShuttingDown();

        mPhoneUT = new GsmCdmaPhone(mContext, mSimulatedCommands, mNotifier, true, 0,
            PhoneConstants.PHONE_TYPE_GSM, mTelephonyComponentFactory);
        mPhoneUT.setVoiceCallSessionStats(mVoiceCallSessionStats);
        ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
        verify(mUiccController).registerForIccChanged(eq(mPhoneUT), integerArgumentCaptor.capture(),
                nullable(Object.class));
        Message msg = Message.obtain();
        msg.what = integerArgumentCaptor.getValue();
        mPhoneUT.sendMessage(msg);
        processAllMessages();
    }

    @After
    public void tearDown() throws Exception {
        mPhoneUT.removeCallbacksAndMessages(null);
        mPhoneUT = null;
        super.tearDown();
    }

    @Test
    @SmallTest
    public void testPhoneTypeSwitch() {
        assertTrue(mPhoneUT.isPhoneTypeGsm());
        switchToCdma();
        assertTrue(mPhoneUT.isPhoneTypeCdmaLte());
    }

    @Test
    @SmallTest
    public void testGetServiceState() {
        ServiceState serviceState = new ServiceState();
        mSST.mSS = serviceState;
        assertEquals(serviceState, mPhoneUT.getServiceState());
    }

    @Test
    @SmallTest
    public void testGetMergedServiceState() throws Exception {
        ServiceState imsServiceState = new ServiceState();

        NetworkRegistrationInfo imsPsWwanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
                .build();

        NetworkRegistrationInfo imsPsWlanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
                .build();

        // Only PS states are tracked for IMS.
        imsServiceState.addNetworkRegistrationInfo(imsPsWwanRegInfo);
        imsServiceState.addNetworkRegistrationInfo(imsPsWlanRegInfo);

        // Voice reg state in this case is whether or not IMS is registered.
        imsServiceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
        imsServiceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
        imsServiceState.setIwlanPreferred(true);
        doReturn(imsServiceState).when(mImsPhone).getServiceState();

        replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);

        ServiceState serviceState = new ServiceState();

        NetworkRegistrationInfo csWwanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
                .build();

        NetworkRegistrationInfo psWwanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
                .build();

        NetworkRegistrationInfo psWlanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
                .build();

        serviceState.addNetworkRegistrationInfo(csWwanRegInfo);
        serviceState.addNetworkRegistrationInfo(psWwanRegInfo);
        serviceState.addNetworkRegistrationInfo(psWlanRegInfo);
        serviceState.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
        serviceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
        serviceState.setIwlanPreferred(true);

        mSST.mSS = serviceState;
        mPhoneUT.mSST = mSST;

        ServiceState mergedServiceState = mPhoneUT.getServiceState();

        assertEquals(ServiceState.STATE_IN_SERVICE, mergedServiceState.getState());
        assertEquals(ServiceState.STATE_IN_SERVICE, mergedServiceState.getDataRegistrationState());
        assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, mergedServiceState.getDataNetworkType());
    }

    /**
     * Some vendors do not provide a voice registration for LTE when attached to LTE only (no CSFB
     * available). In this case, we should still get IN_SERVICE for voice service state, since
     * IMS is registered.
     */
    @Test
    @SmallTest
    public void testGetMergedServiceStateNoCsfb() throws Exception {
        ServiceState imsServiceState = new ServiceState();

        NetworkRegistrationInfo imsPsWwanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
                .build();

        NetworkRegistrationInfo imsPsWlanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
                .build();

        // Only PS states are tracked for IMS.
        imsServiceState.addNetworkRegistrationInfo(imsPsWwanRegInfo);
        imsServiceState.addNetworkRegistrationInfo(imsPsWlanRegInfo);

        // Voice reg state in this case is whether or not IMS is registered.
        imsServiceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
        imsServiceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
        imsServiceState.setIwlanPreferred(true);
        doReturn(imsServiceState).when(mImsPhone).getServiceState();

        replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);

        ServiceState serviceState = new ServiceState();

        NetworkRegistrationInfo csWwanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_UNKNOWN)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
                .build();

        NetworkRegistrationInfo psWwanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
                .build();

        NetworkRegistrationInfo psWlanRegInfo = new NetworkRegistrationInfo.Builder()
                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
                .setRegistrationState(
                        NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
                .build();

        serviceState.addNetworkRegistrationInfo(csWwanRegInfo);
        serviceState.addNetworkRegistrationInfo(psWwanRegInfo);
        serviceState.addNetworkRegistrationInfo(psWlanRegInfo);
        // No CSFB, voice is OOS for LTE only attach
        serviceState.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
        serviceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
        serviceState.setIwlanPreferred(true);

        mSST.mSS = serviceState;
        mPhoneUT.mSST = mSST;

        ServiceState mergedServiceState = mPhoneUT.getServiceState();

        assertEquals(ServiceState.STATE_IN_SERVICE, mergedServiceState.getState());
        assertEquals(ServiceState.STATE_IN_SERVICE, mergedServiceState.getDataRegistrationState());
        assertEquals(TelephonyManager.NETWORK_TYPE_LTE, mergedServiceState.getDataNetworkType());
    }

    @Test
    @SmallTest
    public void testGetSubscriberIdForGsmPhone() {
        final String subscriberId = "123456789";
        IccRecords iccRecords = Mockito.mock(IccRecords.class);
        doReturn(subscriberId).when(iccRecords).getIMSI();
        doReturn(iccRecords).when(mUiccController)
                .getIccRecords(anyInt() /* phoneId */, eq(UiccController.APP_FAM_3GPP));

        // Ensure the phone type is GSM
        GsmCdmaPhone spyPhone = spy(mPhoneUT);
        doReturn(false).when(spyPhone).isPhoneTypeCdma();
        doReturn(false).when(spyPhone).isPhoneTypeCdmaLte();
        doReturn(true).when(spyPhone).isPhoneTypeGsm();

        assertEquals(subscriberId, spyPhone.getSubscriberId());
    }

    @Test
    @SmallTest
    public void testGetSubscriberIdForCdmaLtePhone() {
        final String subscriberId = "abcdefghijk";
        IccRecords iccRecords = Mockito.mock(IccRecords.class);
        doReturn(subscriberId).when(iccRecords).getIMSI();
        doReturn(iccRecords).when(mUiccController)
                .getIccRecords(anyInt() /* phoneId */, eq(UiccController.APP_FAM_3GPP));

        // Ensure the phone type is CdmaLte
        GsmCdmaPhone spyPhone = spy(mPhoneUT);
        doReturn(false).when(spyPhone).isPhoneTypeCdma();
        doReturn(true).when(spyPhone).isPhoneTypeCdmaLte();
        doReturn(false).when(spyPhone).isPhoneTypeGsm();

        assertEquals(subscriberId, spyPhone.getSubscriberId());
    }

    @Test
    @SmallTest
    public void testGetSubscriberIdForCdmaPhone() {
        final String subscriberId = "987654321";
        doReturn(subscriberId).when(mSST).getImsi();

        // Ensure the phone type is GSM
        GsmCdmaPhone spyPhone = spy(mPhoneUT);
        doReturn(true).when(spyPhone).isPhoneTypeCdma();
        doReturn(false).when(spyPhone).isPhoneTypeCdmaLte();
        doReturn(false).when(spyPhone).isPhoneTypeGsm();

        assertEquals(subscriberId, spyPhone.getSubscriberId());
    }

    @Test
    @SmallTest
    public void testGetCellLocation() {
        // GSM
        CellIdentity cellLocation = new CellIdentityGsm();
        WorkSource workSource = new WorkSource(Process.myUid(),
            mContext.getPackageName());
        doReturn(cellLocation).when(mSST).getCellIdentity();
        assertEquals(cellLocation, mPhoneUT.getCellIdentity());

        // Switch to CDMA
        switchToCdma();

        CellIdentityCdma cdmaCellLocation = new CellIdentityCdma();
        doReturn(cdmaCellLocation).when(mSST).getCellIdentity();

        CellIdentityCdma actualCellLocation =
                (CellIdentityCdma) mPhoneUT.getCellIdentity();

        assertEquals(actualCellLocation, cdmaCellLocation);
    }

    @Test
    @SmallTest
    public void testGetPhoneType() {
        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());

        // Switch to CDMA
        switchToCdma();

        assertEquals(PhoneConstants.PHONE_TYPE_CDMA, mPhoneUT.getPhoneType());
    }

    @Test
    @SmallTest
    public void testGetDataConnectionState() {
        // There are several cases possible. Testing few of them for now.
        // 1. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn != APN_TYPE_EMERGENCY
        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSST).getCurrentDataConnectionState();
        assertEquals(PhoneConstants.DataState.DISCONNECTED, mPhoneUT.getDataConnectionState(
                PhoneConstants.APN_TYPE_ALL));

        // 2. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY, apn
        // not connected
        doReturn(DctConstants.State.IDLE).when(mDcTracker).getState(
                PhoneConstants.APN_TYPE_EMERGENCY);
        assertEquals(PhoneConstants.DataState.DISCONNECTED, mPhoneUT.getDataConnectionState(
                PhoneConstants.APN_TYPE_EMERGENCY));

        // 3. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY,
        // APN is connected, callTracker state = idle
        doReturn(DctConstants.State.CONNECTED).when(mDcTracker).getState(
                PhoneConstants.APN_TYPE_EMERGENCY);
        mCT.mState = PhoneConstants.State.IDLE;
        assertEquals(PhoneConstants.DataState.CONNECTED, mPhoneUT.getDataConnectionState(
                PhoneConstants.APN_TYPE_EMERGENCY));

        // 3. GSM, getCurrentDataConnectionState != STATE_IN_SERVICE, apn = APN_TYPE_EMERGENCY,
        // APN enabled and CONNECTED, callTracker state != idle, !isConcurrentVoiceAndDataAllowed
        mCT.mState = PhoneConstants.State.RINGING;
        doReturn(false).when(mSST).isConcurrentVoiceAndDataAllowed();
        assertEquals(PhoneConstants.DataState.SUSPENDED, mPhoneUT.getDataConnectionState(
                PhoneConstants.APN_TYPE_EMERGENCY));
    }

    @Test
    @SmallTest
    public void testHandleInCallMmiCommands() {
        try {
            // Switch to CDMA
            switchToCdma();

            assertFalse(mPhoneUT.handleInCallMmiCommands("0"));

            // Switch to GSM
            switchToGsm();

            mCT.mForegroundCall = mGsmCdmaCall;
            mCT.mBackgroundCall = mGsmCdmaCall;
            mCT.mRingingCall = mGsmCdmaCall;
            doReturn(GsmCdmaCall.State.IDLE).when(mGsmCdmaCall).getState();

            // !isInCall
            assertFalse(mPhoneUT.handleInCallMmiCommands("0"));

            // isInCall
            doReturn(GsmCdmaCall.State.ACTIVE).when(mGsmCdmaCall).getState();
            assertTrue(mPhoneUT.handleInCallMmiCommands("0"));

            // empty dialString
            assertFalse(mPhoneUT.handleInCallMmiCommands(""));
            assertFalse(mPhoneUT.handleInCallMmiCommands(null));

        } catch (Exception e) {
            fail(e.toString());
        }
    }

    @Test
    @SmallTest
    public void testDial() throws Exception {
        try {
            mSST.mSS = mServiceState;
            doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState();

            mCT.mForegroundCall = mGsmCdmaCall;
            mCT.mBackgroundCall = mGsmCdmaCall;
            mCT.mRingingCall = mGsmCdmaCall;
            doReturn(GsmCdmaCall.State.IDLE).when(mGsmCdmaCall).getState();

            replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);

            Connection connection = mPhoneUT.dial("1234567890",
                    new PhoneInternalInterface.DialArgs.Builder().build());
            verify(mCT).dialGsm("1234567890", null, null);
        } catch (CallStateException e) {
            fail();
        }
    }

    @Test
    @SmallTest
    public void testWpsDialOverCs() throws Exception {
        try {
            setupForWpsCallTest();

            mContextFixture.getCarrierConfigBundle().putBoolean(
                    CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, false);

            mPhoneUT.dial("*27216505551212", new PhoneInternalInterface.DialArgs.Builder().build());

            verify(mCT).dialGsm("*27216505551212", null, null);
            verify(mImsCT).hangupAllConnections();
        } catch (CallStateException e) {
            fail();
        }
    }

    @Test
    @SmallTest
    public void testWpsClirActiveDialOverCs() throws Exception {
        try {
            setupForWpsCallTest();

            mContextFixture.getCarrierConfigBundle().putBoolean(
                    CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, false);

            mPhoneUT.dial("*31#*27216505551212",
                    new PhoneInternalInterface.DialArgs.Builder().build());

            verify(mCT).dialGsm("*27216505551212", CommandsInterface.CLIR_SUPPRESSION, null, null);
            verify(mImsCT).hangupAllConnections();
        } catch (CallStateException e) {
            fail();
        }
    }

    @Test
    @SmallTest
    public void testWpsClirInactiveDialOverCs() throws Exception {
        try {
            setupForWpsCallTest();

            mContextFixture.getCarrierConfigBundle().putBoolean(
                    CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, false);

            mPhoneUT.dial("#31#*27216505551212",
                    new PhoneInternalInterface.DialArgs.Builder().build());

            verify(mCT).dialGsm("*27216505551212", CommandsInterface.CLIR_INVOCATION, null, null);
            verify(mImsCT).hangupAllConnections();
        } catch (CallStateException e) {
            fail();
        }
    }

    @Test
    @SmallTest
    public void testWpsDialOverIms() throws Exception {
        try {
            setupForWpsCallTest();

            mContextFixture.getCarrierConfigBundle().putBoolean(
                    CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);

            mPhoneUT.dial("*27216505551212",
                    new PhoneInternalInterface.DialArgs.Builder().build());
            verify(mCT).dialGsm("*27216505551212", null, null);
            verify(mImsCT, never()).hangupAllConnections();
        } catch (CallStateException e) {
            fail();
        }
    }

    @Test
    @SmallTest
    public void testWpsClirActiveDialOverIms() throws Exception {
        try {
            setupForWpsCallTest();

            mContextFixture.getCarrierConfigBundle().putBoolean(
                    CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);

            mPhoneUT.dial("*31#*27216505551212",
                    new PhoneInternalInterface.DialArgs.Builder().build());
            verify(mCT).dialGsm("*27216505551212", CommandsInterface.CLIR_SUPPRESSION, null, null);
            verify(mImsCT, never()).hangupAllConnections();
        } catch (CallStateException e) {
            fail();
        }
    }

    @Test
    @SmallTest
    public void testWpsClirInactiveDialOverIms() throws Exception {
        try {
            setupForWpsCallTest();

            mContextFixture.getCarrierConfigBundle().putBoolean(
                    CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);

            mPhoneUT.dial("#31#*27216505551212",
                    new PhoneInternalInterface.DialArgs.Builder().build());

            verify(mCT).dialGsm("*27216505551212", CommandsInterface.CLIR_INVOCATION, null, null);
            verify(mImsCT, never()).hangupAllConnections();
        } catch (CallStateException e) {
            fail();
        }
    }

    @Test
    @SmallTest
    public void testHandlePinMmi() {
        assertFalse(mPhoneUT.handlePinMmi("1234567890"));
    }

    @Test
    @SmallTest
    public void testEmergencySmsMode() {
        String emergencyNumber = "111";
        String nonEmergencyNumber = "222";
        int timeout = 200;
        mContextFixture.getCarrierConfigBundle().putInt(
                CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT, timeout);
        doReturn(true).when(mTelephonyManager).isEmergencyNumber(emergencyNumber);

        mPhoneUT.notifySmsSent(nonEmergencyNumber);
        processAllMessages();
        assertFalse(mPhoneUT.isInEmergencySmsMode());

        mPhoneUT.notifySmsSent(emergencyNumber);
        processAllMessages();
        assertTrue(mPhoneUT.isInEmergencySmsMode());
        // mTimeLastEmergencySmsSentMs uses System.currentTimeMillis()
        waitForMs(timeout + 5);
        processAllMessages();
        assertFalse(mPhoneUT.isInEmergencySmsMode());

        // Feature not supported
        mContextFixture.getCarrierConfigBundle().putInt(
                CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT, 0);
        mPhoneUT.notifySmsSent(emergencyNumber);
        processAllMessages();
        assertFalse(mPhoneUT.isInEmergencySmsMode());
    }

    @Test
    @SmallTest
    public void testSendBurstDtmf() {
        //Should do nothing for GSM
        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
                anyInt(), nullable(Message.class));

        switchToCdma();
        //invalid character
        mPhoneUT.sendBurstDtmf("12345a67890", 0, 0, null);
        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
                anyInt(), nullable(Message.class));

        //state IDLE
        mCT.mState = PhoneConstants.State.IDLE;
        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
                anyInt(), nullable(Message.class));

        //state RINGING
        mCT.mState = PhoneConstants.State.RINGING;
        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
                anyInt(), nullable(Message.class));

        mCT.mState = PhoneConstants.State.OFFHOOK;
        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
        verify(mSimulatedCommandsVerifier).sendBurstDtmf("1234567890", 0, 0, null);
    }

    @Test
    @SmallTest
    public void testVoiceMailNumberGsm() {
        String voiceMailNumber = "1234567890";
        // first test for GSM
        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());

        // no resource or sharedPreference set -- should be null
        assertEquals(null, mPhoneUT.getVoiceMailNumber());

        // config_telephony_use_own_number_for_voicemail
        mContextFixture.getCarrierConfigBundle()
                .putBoolean(CarrierConfigManager
                        .KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, true);
        doReturn(voiceMailNumber).when(mSimRecords).getMsisdnNumber();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());

        // voicemail number from config
        mContextFixture.getCarrierConfigBundle().
                putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING, voiceMailNumber);
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());

        // voicemail number from config for roaming network
        String voiceMailNumberForRoaming = "1234567892";
        mContextFixture.getCarrierConfigBundle()
                .putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_STRING,
                        voiceMailNumberForRoaming);

        // voicemail number from config for roaming network and ims unregistered
        String voiceMailNumberForImsRoamingAndUnregistered = "1234567893";
        mContextFixture.getCarrierConfigBundle().putString(
                CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING,
                        voiceMailNumberForImsRoamingAndUnregistered);

        //Verify voicemail number for home
        doReturn(false).when(mSST.mSS).getRoaming();
        doReturn(true).when(mSST).isImsRegistered();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
        //Move to ims condition, verify voicemail number for ims unregistered
        doReturn(false).when(mSST).isImsRegistered();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
        //Move to roaming condition, verify voicemail number for roaming
        doReturn(true).when(mSST.mSS).getRoaming();
        assertEquals(voiceMailNumberForImsRoamingAndUnregistered, mPhoneUT.getVoiceMailNumber());
        //Move to ims condition, verify voicemail number for roaming
        doReturn(true).when(mSST).isImsRegistered();
        assertEquals(voiceMailNumberForRoaming, mPhoneUT.getVoiceMailNumber());
        //Move to home condition, verify voicemail number for home
        doReturn(false).when(mSST.mSS).getRoaming();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());

        // voicemail number that is explicitly set
        voiceMailNumber = "1234567891";
        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
        verify(mSimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
                nullable(Message.class));

        doReturn(voiceMailNumber).when(mSimRecords).getVoiceMailNumber();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
    }

    @Test
    @SmallTest
    public void testVoiceMailNumberCdma() {
        switchToCdma();
        String voiceMailNumber = "1234567890";

        // config_telephony_use_own_number_for_voicemail
        mContextFixture.getCarrierConfigBundle()
                .putBoolean(CarrierConfigManager
                                .KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, true);
        doReturn(voiceMailNumber).when(mSST).getMdnNumber();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());

        // voicemail number from config
        voiceMailNumber = "1234567891";
        mContextFixture.getCarrierConfigBundle().
                putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING, voiceMailNumber);
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());

        // voicemail number from config for roaming network
        String voiceMailNumberForRoaming = "1234567892";
        mContextFixture.getCarrierConfigBundle()
                .putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_STRING,
                        voiceMailNumberForRoaming);

        // voicemail number from config for roaming network and ims unregistered
        String voiceMailNumberForImsRoamingAndUnregistered = "1234567893";
        mContextFixture.getCarrierConfigBundle().putString(
                CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING,
                        voiceMailNumberForImsRoamingAndUnregistered);

        //Verify voicemail number for home
        doReturn(false).when(mSST.mSS).getRoaming();
        doReturn(true).when(mSST).isImsRegistered();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
        //Move to ims condition, verify voicemail number for ims unregistered
        doReturn(false).when(mSST).isImsRegistered();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
        //Move to roaming condition, verify voicemail number for roaming
        doReturn(true).when(mSST.mSS).getRoaming();
        assertEquals(voiceMailNumberForImsRoamingAndUnregistered, mPhoneUT.getVoiceMailNumber());
        //Move to ims condition, verify voicemail number for roaming
        doReturn(true).when(mSST).isImsRegistered();
        assertEquals(voiceMailNumberForRoaming, mPhoneUT.getVoiceMailNumber());
        //Move to home condition, verify voicemail number for home
        doReturn(false).when(mSST.mSS).getRoaming();
        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());

        // voicemail number from sharedPreference
        voiceMailNumber = "1234567893";
        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
        InOrder inOrder = inOrder(mSimRecords);
        inOrder.verify(mSimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
                messageArgumentCaptor.capture());

        // SIM does not support voicemail number (IccVmNotSupportedException) so should be saved in
        // shared pref
        Message msg = messageArgumentCaptor.getValue();
        AsyncResult.forMessage(msg).exception =
                new IccVmNotSupportedException("setVoiceMailNumber not implemented");
        msg.sendToTarget();
        processAllMessages();

        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());

        // voicemail number from SIM
        voiceMailNumber = "1234567894";
        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
        messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
        inOrder.verify(mSimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
                messageArgumentCaptor.capture());

        // successfully saved on SIM
        msg = messageArgumentCaptor.getValue();
        AsyncResult.forMessage(msg);
        msg.sendToTarget();
        processAllMessages();

        doReturn(voiceMailNumber).when(mSimRecords).getVoiceMailNumber();

        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
    }

    @FlakyTest
    @Test
    @Ignore
    public void testVoiceMailCount() {
        // initial value
        assertEquals(0, mPhoneUT.getVoiceMessageCount());

        // old sharedPreference set (testing upgrade from M to N scenario)
        SharedPreferences sharedPreferences =
                PreferenceManager.getDefaultSharedPreferences(mContext);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        String imsi = "1234567890";
        editor.putString("vm_id_key", imsi);
        editor.putInt("vm_count_key", 5);
        editor.apply();
        doReturn(imsi).when(mSimRecords).getIMSI();

        // updateVoiceMail should read old shared pref and delete it and new sharedPref should be
        // updated now
        doReturn(-1).when(mSimRecords).getVoiceMessageCount();
        mPhoneUT.updateVoiceMail();
        assertEquals(5, mPhoneUT.getVoiceMessageCount());
        assertEquals(null, sharedPreferences.getString("vm_id_key", null));
        assertEquals(5, sharedPreferences.getInt("vm_count_key" + mPhoneUT.getSubId(), 0));

        // sim records return count as 0, that overrides shared preference
        doReturn(0).when(mSimRecords).getVoiceMessageCount();
        mPhoneUT.updateVoiceMail();
        assertEquals(0, mPhoneUT.getVoiceMessageCount());

        // sim records return count as -1
        doReturn(-1).when(mSimRecords).getVoiceMessageCount();
        mPhoneUT.updateVoiceMail();
        assertEquals(-1, mPhoneUT.getVoiceMessageCount());

        // sim records return count as -1 and sharedPreference says 0
        mPhoneUT.setVoiceMessageCount(0);
        mPhoneUT.updateVoiceMail();
        assertEquals(-1, mPhoneUT.getVoiceMessageCount());

        // sim records return count as -1 and sharedPreference says 2
        mPhoneUT.setVoiceMessageCount(2);
        mPhoneUT.updateVoiceMail();
        assertEquals(2, mPhoneUT.getVoiceMessageCount());

        // sim records return count as 0 and sharedPreference says 2
        doReturn(0).when(mSimRecords).getVoiceMessageCount();
        mPhoneUT.setVoiceMessageCount(2);
        mPhoneUT.updateVoiceMail();
        assertEquals(0, mPhoneUT.getVoiceMessageCount());
    }

    @Test
    @SmallTest
    public void testGetCallForwardingOption() {
        // invalid reason (-1)
        mPhoneUT.getCallForwardingOption(-1, null);
        verify(mSimulatedCommandsVerifier, times(0)).queryCallForwardStatus(
                anyInt(), anyInt(), nullable(String.class), nullable(Message.class));

        // valid reason
        String imsi = "1234567890";
        doReturn(imsi).when(mSimRecords).getIMSI();
        mPhoneUT.getCallForwardingOption(CF_REASON_UNCONDITIONAL, null);
        verify(mSimulatedCommandsVerifier).queryCallForwardStatus(
                eq(CF_REASON_UNCONDITIONAL), eq(CommandsInterface.SERVICE_CLASS_VOICE),
                nullable(String.class), nullable(Message.class));
        processAllMessages();
        verify(mSimRecords).setVoiceCallForwardingFlag(anyInt(), anyBoolean(),
                nullable(String.class));

        // should have updated shared preferences
        SharedPreferences sharedPreferences = PreferenceManager.
                getDefaultSharedPreferences(mContext);
        assertEquals(IccRecords.CALL_FORWARDING_STATUS_DISABLED,
                sharedPreferences.getInt(Phone.CF_STATUS + mPhoneUT.getSubId(),
                        IccRecords.CALL_FORWARDING_STATUS_ENABLED));

        // clean up
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.remove(Phone.CF_STATUS + mPhoneUT.getSubId());
        editor.apply();
    }

    @Test
    @SmallTest
    public void testSetCallForwardingOption() {
        String cfNumber = "1234567890";

        // invalid action
        mPhoneUT.setCallForwardingOption(-1, CF_REASON_UNCONDITIONAL,
                cfNumber, 0, null);
        verify(mSimulatedCommandsVerifier, times(0)).setCallForward(anyInt(), anyInt(), anyInt(),
                nullable(String.class), anyInt(), nullable(Message.class));

        // valid action
        mPhoneUT.setCallForwardingOption(CF_ACTION_ENABLE, CF_REASON_UNCONDITIONAL, cfNumber, 0,
                null);
        verify(mSimulatedCommandsVerifier).setCallForward(eq(CF_ACTION_ENABLE),
                eq(CF_REASON_UNCONDITIONAL), anyInt(), eq(cfNumber), eq(0),
                nullable(Message.class));
        processAllMessages();
        verify(mSimRecords).setVoiceCallForwardingFlag(anyInt(), anyBoolean(), eq(cfNumber));
    }

    /**
     * GsmCdmaPhone handles a lot of messages. This function verifies behavior for messages that are
     * received when obj is created and that are received on phone type switch
     */
    @FlakyTest
    @Ignore
    @Test
    @SmallTest
    public void testHandleInitialMessages() {
        // EVENT_RADIO_AVAILABLE
        verify(mSimulatedCommandsVerifier).getBasebandVersion(nullable(Message.class));
        verify(mSimulatedCommandsVerifier).getDeviceIdentity(nullable(Message.class));
        verify(mSimulatedCommandsVerifier).getRadioCapability(nullable(Message.class));
        // once as part of constructor, and once on radio available
        verify(mSimulatedCommandsVerifier, times(2)).startLceService(anyInt(), anyBoolean(),
                nullable(Message.class));

        // EVENT_RADIO_ON
        verify(mSimulatedCommandsVerifier).getVoiceRadioTechnology(nullable(Message.class));
        verify(mSimulatedCommandsVerifier).setPreferredNetworkType(
                eq(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA), nullable(Message.class));

        // verify responses for above requests:
        // baseband version
        verify(mTelephonyManager).setBasebandVersionForPhone(eq(mPhoneUT.getPhoneId()),
                nullable(String.class));
        // IMEI
        assertEquals(SimulatedCommands.FAKE_IMEI, mPhoneUT.getImei());
        // IMEISV
        assertEquals(SimulatedCommands.FAKE_IMEISV, mPhoneUT.getDeviceSvn());
        // radio capability
        verify(mSimulatedCommandsVerifier).getNetworkSelectionMode(nullable(Message.class));

        switchToCdma(); // this leads to eventRadioAvailable handling on cdma

        // EVENT_RADIO_AVAILABLE
        verify(mSimulatedCommandsVerifier, times(2)).getBasebandVersion(nullable(Message.class));
        verify(mSimulatedCommandsVerifier, times(2)).getDeviceIdentity(nullable(Message.class));
        verify(mSimulatedCommandsVerifier, times(3)).startLceService(anyInt(), anyBoolean(),
                nullable(Message.class));

        // EVENT_RADIO_ON
        verify(mSimulatedCommandsVerifier, times(2)).getVoiceRadioTechnology(
                nullable(Message.class));
        // once on radio on, and once on get baseband version
        verify(mSimulatedCommandsVerifier, times(3)).setPreferredNetworkType(
                eq(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA), nullable(Message.class));

        // verify responses for above requests:
        // baseband version
        verify(mTelephonyManager, times(2)).setBasebandVersionForPhone(eq(mPhoneUT.getPhoneId()),
                nullable(String.class));
        // device identity
        assertEquals(SimulatedCommands.FAKE_IMEI, mPhoneUT.getImei());
        assertEquals(SimulatedCommands.FAKE_IMEISV, mPhoneUT.getDeviceSvn());
        assertEquals(SimulatedCommands.FAKE_ESN, mPhoneUT.getEsn());
        assertEquals(SimulatedCommands.FAKE_MEID, mPhoneUT.getMeid());
    }

    @Test
    @SmallTest
    public void testEmergencyCallbackMessages() throws Exception {
        verify(mSimulatedCommandsVerifier).setEmergencyCallbackMode(eq(mPhoneUT), anyInt(),
                nullable(Object.class));
        verify(mSimulatedCommandsVerifier).registerForExitEmergencyCallbackMode(eq(mPhoneUT),
                anyInt(), nullable(Object.class));

        // verify handling of emergency callback mode
        mSimulatedCommands.notifyEmergencyCallbackMode();
        processAllMessages();

        verifyEcbmIntentSent(1 /*times*/, true /*isInEcm*/);
        assertTrue(mPhoneUT.isInEcm());

        // verify that wakeLock is acquired in ECM
        assertTrue(mPhoneUT.getWakeLock().isHeld());

        mPhoneUT.setOnEcbModeExitResponse(mTestHandler, EVENT_EMERGENCY_CALLBACK_MODE_EXIT, null);
        mPhoneUT.registerForEmergencyCallToggle(mTestHandler, EVENT_EMERGENCY_CALL_TOGGLE, null);

        // verify handling of emergency callback mode exit
        mSimulatedCommands.notifyExitEmergencyCallbackMode();
        processAllMessages();

        verifyEcbmIntentSent(2 /*times*/, false /*isInEcm*/);
        assertFalse(mPhoneUT.isInEcm());

        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);

        // verify EcmExitRespRegistrant and mEmergencyCallToggledRegistrants are notified
        verify(mTestHandler, times(2)).sendMessageAtTime(messageArgumentCaptor.capture(),
                anyLong());
        List<Message> msgList = messageArgumentCaptor.getAllValues();
        assertEquals(EVENT_EMERGENCY_CALLBACK_MODE_EXIT, msgList.get(0).what);
        assertEquals(EVENT_EMERGENCY_CALL_TOGGLE, msgList.get(1).what);

        // verify setInternalDataEnabled
        verify(mDataEnabledSettings).setInternalDataEnabled(true);

        // verify wakeLock released
        assertFalse(mPhoneUT.getWakeLock().isHeld());
    }

    private void verifyEcbmIntentSent(int times, boolean isInEcm) throws Exception {
        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext, atLeast(times)).sendStickyBroadcastAsUser(intentArgumentCaptor.capture(),
                any());
        Intent intent = intentArgumentCaptor.getValue();
        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
        assertEquals(isInEcm, intent.getBooleanExtra(
                TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false));
    }

    @Test
    @SmallTest
    public void testEcmCancelledPreservedThroughSrvcc() throws Exception {
        replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);
        assertFalse(mPhoneUT.isEcmCanceledForEmergency());
        // Set ECM cancelled state on ImsPhone to be transferred via migrateFrom
        doReturn(true).when(mImsPhone).isEcmCanceledForEmergency();
        verify(mSimulatedCommandsVerifier).registerForSrvccStateChanged(any(),
                eq(EVENT_SRVCC_STATE_CHANGED), any());

        // Start SRVCC
        Message msg = Message.obtain();
        msg.what = EVENT_SRVCC_STATE_CHANGED;
        msg.obj = new AsyncResult(null, new int[]{TelephonyManager.SRVCC_STATE_HANDOVER_STARTED},
                null);
        mPhoneUT.sendMessage(msg);
        processAllMessages();

        // verify ECM cancelled is transferred correctly.
        assertTrue(mPhoneUT.isEcmCanceledForEmergency());
    }

    @Test
    @SmallTest
    public void testModemResetInEmergencyCallbackMessages() {
        verify(mSimulatedCommandsVerifier).setEmergencyCallbackMode(eq(mPhoneUT), anyInt(),
                nullable(Object.class));
        verify(mSimulatedCommandsVerifier).registerForModemReset(eq(mPhoneUT),
                anyInt(), nullable(Object.class));

        switchToCdma();
        // verify handling of emergency callback mode
        mSimulatedCommands.notifyEmergencyCallbackMode();
        processAllMessages();

        // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
        try {
            verify(mContext, atLeast(1)).sendStickyBroadcastAsUser(intentArgumentCaptor.capture(),
                    any());
        } catch (Exception e) {
            fail("Unexpected exception: " + e.getStackTrace());
        }

        Intent intent = intentArgumentCaptor.getValue();
        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
        assertEquals(true, intent.getBooleanExtra(
                TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false));
        assertEquals(true, mPhoneUT.isInEcm());

        // verify that wakeLock is acquired in ECM
        assertEquals(true, mPhoneUT.getWakeLock().isHeld());

        mPhoneUT.setOnEcbModeExitResponse(mTestHandler, EVENT_EMERGENCY_CALLBACK_MODE_EXIT, null);
        mPhoneUT.registerForEmergencyCallToggle(mTestHandler, EVENT_EMERGENCY_CALL_TOGGLE, null);

        // verify handling of emergency callback mode exit when modem resets
        mSimulatedCommands.notifyModemReset();
        processAllMessages();

        // verify ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
        try {
            verify(mContext, atLeast(2)).sendStickyBroadcastAsUser(intentArgumentCaptor.capture(),
                    any());
        } catch (Exception e) {
            fail("Unexpected exception: " + e.getStackTrace());
        }

        intent = intentArgumentCaptor.getValue();
        assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, intent.getAction());
        assertEquals(false, intent.getBooleanExtra(
                TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, true));
        assertEquals(false, mPhoneUT.isInEcm());

        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);

        // verify EcmExitRespRegistrant and mEmergencyCallToggledRegistrants are notified
        verify(mTestHandler, times(2)).sendMessageAtTime(messageArgumentCaptor.capture(),
                anyLong());
        List<Message> msgList = messageArgumentCaptor.getAllValues();
        assertEquals(EVENT_EMERGENCY_CALLBACK_MODE_EXIT, msgList.get(0).what);
        assertEquals(EVENT_EMERGENCY_CALL_TOGGLE, msgList.get(1).what);

        // verify setInternalDataEnabled
        verify(mDataEnabledSettings).setInternalDataEnabled(true);

        // verify wakeLock released
        assertEquals(false, mPhoneUT.getWakeLock().isHeld());
    }

    @Test
    @SmallTest
    public void testCallForwardingIndicator() {
        doReturn(IccRecords.CALL_FORWARDING_STATUS_UNKNOWN).when(mSimRecords).
                getVoiceCallForwardingFlag();

        // invalid subId
        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID).when(mSubscriptionController).
                getSubIdUsingPhoneId(anyInt());
        assertEquals(false, mPhoneUT.getCallForwardingIndicator());

        // valid subId, sharedPreference not present
        int subId1 = 0;
        int subId2 = 1;
        doReturn(subId1).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
        assertEquals(false, mPhoneUT.getCallForwardingIndicator());

        // old sharedPreference present
        String imsi = "1234";
        doReturn(imsi).when(mSimRecords).getIMSI();
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString(Phone.CF_ID, imsi);
        editor.putInt(Phone.CF_STATUS, IccRecords.CALL_FORWARDING_STATUS_ENABLED);
        editor.apply();
        assertEquals(true, mPhoneUT.getCallForwardingIndicator());

        // old sharedPreference should be removed now
        assertEquals(null, sp.getString(Phone.CF_ID, null));
        assertEquals(IccRecords.CALL_FORWARDING_STATUS_UNKNOWN,
                sp.getInt(Phone.CF_ID, IccRecords.CALL_FORWARDING_STATUS_UNKNOWN));

        // now verify value from new sharedPreference
        assertEquals(true, mPhoneUT.getCallForwardingIndicator());

        // check for another subId
        doReturn(subId2).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
        assertEquals(false, mPhoneUT.getCallForwardingIndicator());

        // set value for the new subId in sharedPreference
        editor.putInt(Phone.CF_STATUS + subId2, IccRecords.CALL_FORWARDING_STATUS_ENABLED);
        editor.apply();
        assertEquals(true, mPhoneUT.getCallForwardingIndicator());

        // switching back to previous subId, stored value should still be available
        doReturn(subId1).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
        assertEquals(true, mPhoneUT.getCallForwardingIndicator());

        // cleanup
        editor.remove(Phone.CF_STATUS + subId1);
        editor.remove(Phone.CF_STATUS + subId2);
        editor.apply();
    }

    @Test
    @SmallTest
    public void testGetIccCardUnknownAndAbsent() {
        // If UiccSlot.isStateUnknown is true, we should return a dummy IccCard with the state
        // set to UNKNOWN
        doReturn(null).when(mUiccController).getUiccProfileForPhone(anyInt());
        UiccSlot mockSlot = mock(UiccSlot.class);
        doReturn(mockSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
        doReturn(true).when(mockSlot).isStateUnknown();

        IccCard iccCard = mPhoneUT.getIccCard();
        assertEquals(IccCardConstants.State.UNKNOWN, iccCard.getState());

        // if isStateUnknown is false, we should return a dummy IccCard with the state set to
        // ABSENT
        doReturn(false).when(mockSlot).isStateUnknown();
        iccCard = mPhoneUT.getIccCard();
        assertEquals(IccCardConstants.State.ABSENT, iccCard.getState());
    }

    @Test
    @SmallTest
    public void testGetEmptyIccCard() {
        doReturn(null).when(mUiccController).getUiccProfileForPhone(anyInt());

        IccCard iccCard = mPhoneUT.getIccCard();

        // The iccCard should be a dummy object, not null.
        assertTrue(!(iccCard instanceof UiccProfile));

        assertTrue(iccCard != null);
        assertEquals(IccCardConstants.State.UNKNOWN, iccCard.getState());
        assertEquals(null, iccCard.getIccRecords());
        assertEquals(false, iccCard.getIccLockEnabled());
        assertEquals(false, iccCard.getIccFdnEnabled());
        assertEquals(false, iccCard.isApplicationOnIcc(
                IccCardApplicationStatus.AppType.APPTYPE_SIM));
        assertEquals(false, iccCard.hasIccCard());
        assertEquals(false, iccCard.getIccPin2Blocked());
        assertEquals(false, iccCard.getIccPuk2Blocked());

        Message onComplete = mTestHandler.obtainMessage(EVENT_SET_ICC_LOCK_ENABLED);
        iccCard.setIccLockEnabled(true, "password", onComplete);

        processAllMessages();

        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
        // Verify that message is sent back with exception.
        verify(mTestHandler, times(1)).sendMessageAtTime(messageArgumentCaptor.capture(),
                anyLong());
        Message message = messageArgumentCaptor.getAllValues().get(0);
        AsyncResult ret = (AsyncResult) message.obj;
        assertEquals(EVENT_SET_ICC_LOCK_ENABLED, message.what);
        assertTrue(ret.exception != null);
    }

    @Test
    @SmallTest
    public void testGetCsCallRadioTech() {
        ServiceState ss = new ServiceState();
        mSST.mSS = ss;

        // vrs in-service, vrat umts, expected umts
        ss.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
        NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_UMTS)
                .build();
        ss.addNetworkRegistrationInfo(nri);
        assertEquals(mPhoneUT.getCsCallRadioTech(), ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);

        // vrs oos, vrat umts, expected unknown
        ss.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
        assertEquals(mPhoneUT.getCsCallRadioTech(), ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);

        // vrs in-service, vrat lte, expected unknown
        ss.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
        nri = new NetworkRegistrationInfo.Builder()
                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
                .build();
        ss.addNetworkRegistrationInfo(nri);
        assertEquals(mPhoneUT.getCsCallRadioTech(), ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
    }

    @Test
    @SmallTest
    public void testGetLine1NumberForGsmPhone() {
        final String msisdn = "+1234567890";
        doReturn(msisdn).when(mSimRecords).getMsisdnNumber();

        switchToGsm();
        assertEquals(msisdn, mPhoneUT.getLine1Number());
    }

    @Test
    @SmallTest
    public void testGetLine1NumberForCdmaPhone() {
        final String mdn = "1234567890";
        final String msisdn = "+1234567890";
        doReturn(mdn).when(mSST).getMdnNumber();
        doReturn(msisdn).when(mSimRecords).getMsisdnNumber();

        switchToCdma();
        assertEquals(mdn, mPhoneUT.getLine1Number());

        mContextFixture.getCarrierConfigBundle().putBoolean(
                CarrierConfigManager.KEY_USE_USIM_BOOL, true);
        assertEquals(msisdn, mPhoneUT.getLine1Number());
    }

    @Test
    @SmallTest
    public void testEnableUiccApplications() throws Exception {
        mPhoneUT.mCi = mMockCi;
        // UiccSlot is null. Doing nothing.
        mPhoneUT.enableUiccApplications(true, null);
        verify(mMockCi, never()).enableUiccApplications(anyBoolean(), any());

        // Card state is not PRESENT. Doing nothing.
        doReturn(mUiccSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
        doReturn(IccCardStatus.CardState.CARDSTATE_ABSENT).when(mUiccSlot).getCardState();
        mPhoneUT.enableUiccApplications(true, null);
        verify(mMockCi, never()).enableUiccApplications(anyBoolean(), any());

        doReturn(IccCardStatus.CardState.CARDSTATE_PRESENT).when(mUiccSlot).getCardState();
        Message message = Message.obtain();
        mPhoneUT.enableUiccApplications(true, message);
        verify(mMockCi).enableUiccApplications(eq(true), eq(message));
    }

    @Test
    @SmallTest
    public void testReapplyUiccApplicationEnablementNotNeeded() throws Exception {
        mPhoneUT.mCi = mMockCi;
        // UiccSlot is null, or not present, or mUiccApplicationsEnabled is not available, or IccId
        // is not available, Doing nothing.
        doReturn(mUiccSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
        Message.obtain(mPhoneUT, EVENT_ICC_CHANGED, null).sendToTarget();
        processAllMessages();
        doReturn(IccCardStatus.CardState.CARDSTATE_ABSENT).when(mUiccSlot).getCardState();
        Message.obtain(mPhoneUT, EVENT_ICC_CHANGED, null).sendToTarget();
        processAllMessages();
        doReturn(IccCardStatus.CardState.CARDSTATE_PRESENT).when(mUiccSlot).getCardState();
        Message.obtain(mPhoneUT, EVENT_ICC_CHANGED, null).sendToTarget();
        Message.obtain(mPhoneUT, EVENT_UICC_APPS_ENABLEMENT_STATUS_CHANGED,
                new AsyncResult(null, true, null)).sendToTarget();
        processAllMessages();
        verify(mSubscriptionController, never()).getSubInfoForIccId(any());

        // Have IccId defined. But expected value and current value are the same. So no RIL command
        // should be sent.
        String iccId = "Fake iccId";
        doReturn(iccId).when(mUiccSlot).getIccId();
        Message.obtain(mPhoneUT, EVENT_ICC_CHANGED, null).sendToTarget();
        processAllMessages();
        verify(mSubscriptionController).getSubInfoForIccId(iccId);
        verify(mMockCi, never()).enableUiccApplications(anyBoolean(), any());
    }

    @Test
    @SmallTest
    public void testReapplyUiccApplicationEnablementSuccess() throws Exception {
        mPhoneUT.mCi = mMockCi;
        // Set SIM to be present, with a fake iccId, and notify enablement being false.
        doReturn(mUiccSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
        doReturn(IccCardStatus.CardState.CARDSTATE_PRESENT).when(mUiccSlot).getCardState();
        String iccId = "Fake iccId";
        doReturn(iccId).when(mUiccSlot).getIccId();
        Message.obtain(mPhoneUT, EVENT_UICC_APPS_ENABLEMENT_STATUS_CHANGED,
                new AsyncResult(null, false, null)).sendToTarget();
        processAllMessages();

        // Should try to enable uicc applications as by default hey are expected to be true.
        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
        verify(mMockCi, times(1)).enableUiccApplications(eq(true), messageCaptor.capture());
        // Send message back with no exception.
        AsyncResult.forMessage(messageCaptor.getValue(), null, null);
        messageCaptor.getValue().sendToTarget();
        processAllMessages();

        // There shouldn't be any retry message.
        moveTimeForward(5000);
        processAllMessages();
        verify(mMockCi, times(1)).enableUiccApplications(eq(true), any());
    }

    @Test
    @SmallTest
    public void testSetRadioPower() throws Exception {
        mPhoneUT.setRadioPower(false);
        verify(mSST).setRadioPower(false, false, false, false);

        // Turn on radio for emergency call.
        mPhoneUT.setRadioPower(true, true, false, true);
        verify(mSST).setRadioPower(true, true, false, true);
    }

    @Test
    @SmallTest
    public void testReapplyUiccApplicationEnablementRetry() throws Exception {
        mPhoneUT.mCi = mMockCi;
        // Set SIM to be present, with a fake iccId, and notify enablement being false.
        doReturn(mUiccSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
        doReturn(IccCardStatus.CardState.CARDSTATE_PRESENT).when(mUiccSlot).getCardState();
        String iccId = "Fake iccId";
        doReturn(iccId).when(mUiccSlot).getIccId();
        Message.obtain(mPhoneUT, EVENT_UICC_APPS_ENABLEMENT_STATUS_CHANGED,
                new AsyncResult(null, false, null)).sendToTarget();
        processAllMessages();

        // Should try to enable uicc applications as by default hey are expected to be true.
        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
        verify(mMockCi).enableUiccApplications(eq(true), messageCaptor.capture());
        clearInvocations(mMockCi);
        for (int i = 0; i < GsmCdmaPhone.ENABLE_UICC_APPS_MAX_RETRIES; i++) {
            // Send message back with SIM_BUSY exception. Should retry.
            AsyncResult.forMessage(messageCaptor.getValue(), null, new CommandException(
                    CommandException.Error.SIM_BUSY));
            messageCaptor.getValue().sendToTarget();
            processAllMessages();
            // There should be a retry message.
            moveTimeForward(5000);
            processAllMessages();
            verify(mMockCi).enableUiccApplications(eq(true), messageCaptor.capture());
            clearInvocations(mMockCi);
        }

        // Reaches max retries. Should NOT retry.
        AsyncResult.forMessage(messageCaptor.getValue(), null, new CommandException(
                CommandException.Error.SIM_BUSY));
        messageCaptor.getValue().sendToTarget();
        processAllMessages();
        // There should NOT be a retry message.
        moveTimeForward(5000);
        processAllMessages();
        verify(mMockCi, never()).enableUiccApplications(eq(true), messageCaptor.capture());
        clearInvocations(mMockCi);
    }

    @Test
    @SmallTest
    public void testSendUssdInService() throws Exception {
        PhoneInternalInterface.DialArgs dialArgs = new PhoneInternalInterface.DialArgs
                .Builder().setVideoState(VideoProfile.STATE_AUDIO_ONLY).build();

        setupTestSendUssd(dialArgs);

        // ServiceState is in service.
        doReturn(ServiceState.STATE_IN_SERVICE).when(mSST.mSS).getState();
        mPhoneUT.dial("*135#", dialArgs);
        verify(mMockCi).sendUSSD(eq("*135#"), any());
    }

    @Test
    @SmallTest
    public void testSendUssdInOutOfService() throws Exception {
        PhoneInternalInterface.DialArgs dialArgs = new PhoneInternalInterface.DialArgs
                .Builder().setVideoState(VideoProfile.STATE_AUDIO_ONLY).build();

        setupTestSendUssd(dialArgs);

        // ServiceState is out of service
        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mSST.mSS)
                .getState(); /* CS out of service */
        doReturn(ServiceState.STATE_IN_SERVICE).when(mSST.mSS).getDataRegState();
        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_GSM).when(mSST.mSS)
                .getRilDataRadioTechnology(); /* PS not in LTE */
        mPhoneUT.dial("*135#", dialArgs);
        verify(mMockCi).sendUSSD(eq("*135#"), any());
    }

    @Test
    @SmallTest
    public void testSendUssdInAirplaneMode() throws Exception {
        PhoneInternalInterface.DialArgs dialArgs = new PhoneInternalInterface.DialArgs
                .Builder().setVideoState(VideoProfile.STATE_AUDIO_ONLY).build();

        setupTestSendUssd(dialArgs);

        // ServiceState is airplane mode.
        doReturn(ServiceState.STATE_POWER_OFF).when(mSST.mSS).getState(); /* CS POWER_OFF */
        mPhoneUT.dial("*135#", dialArgs);
        verify(mMockCi).sendUSSD(eq("*135#"), any());
    }

    private void setupTestSendUssd(PhoneInternalInterface.DialArgs dialArgs) throws Exception {
        mPhoneUT.mCi = mMockCi;
        ServiceState mImsServiceState = Mockito.mock(ServiceState.class);
        CallStateException callStateException = Mockito.mock(CallStateException.class);

        // Enable VoWiFi
        doReturn(true).when(mImsManager).isVolteEnabledByPlatform();
        doReturn(true).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser();
        doReturn(mImsServiceState).when(mImsPhone).getServiceState();
        doReturn(ServiceState.STATE_IN_SERVICE).when(mImsServiceState).getState();
        doReturn(true).when(mImsPhone).isWifiCallingEnabled();

        // Disable UT/XCAP
        doReturn(false).when(mImsPhone).isUtEnabled();

        // Throw CallStateException(Phone.CS_FALLBACK) from ImsPhone.dial().
        doReturn(Phone.CS_FALLBACK).when(callStateException).getMessage();
        doThrow(callStateException).when(mImsPhone).dial("*135#", dialArgs);

        replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);
    }

    @Test
    public void testEventCarrierConfigChanged() {
        mPhoneUT.mCi = mMockCi;
        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(Phone.EVENT_CARRIER_CONFIG_CHANGED));
        processAllMessages();

        ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
        verify(mMockCi).getRadioCapability(captor.capture());
        assertEquals(captor.getValue().what, Phone.EVENT_GET_RADIO_CAPABILITY);
    }

    private void setupForWpsCallTest() throws Exception {
        mSST.mSS = mServiceState;
        doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState();
        when(mImsPhone.getCallTracker()).thenReturn(mImsCT);
        mCT.mForegroundCall = mGsmCdmaCall;
        mCT.mBackgroundCall = mGsmCdmaCall;
        mCT.mRingingCall = mGsmCdmaCall;
        doReturn(GsmCdmaCall.State.IDLE).when(mGsmCdmaCall).getState();
        replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);
    }
}
