alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (GSMPhoneTest.java)

This example Android source code file (GSMPhoneTest.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

android, asyncresult, callstateexception, connection, event_disconnect, event_phone_state_changed, event_ringing, exception, gsm, hello, message, mmicode, os, out, string, supp_service_failed, telephony, test, time, util

The GSMPhoneTest.java Android example source code

/*
 * Copyright (C) 2007 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 GSMTestHandler.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.gsm;

import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.telephony.ServiceState;
import android.test.AndroidTestCase;
import android.test.PerformanceTestCase;
import android.util.Log;

import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.MmiCode;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TestPhoneNotifier;
import com.android.internal.telephony.gsm.CallFailCause;
import com.android.internal.telephony.gsm.GSMPhone;
import com.android.internal.telephony.gsm.GSMTestHandler;
import com.android.internal.telephony.gsm.GsmMmiCode;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.test.SimulatedCommands;
import com.android.internal.telephony.test.SimulatedRadioControl;

import java.util.List;


public class GSMPhoneTest extends AndroidTestCase implements PerformanceTestCase {
    private SimulatedRadioControl mRadioControl;
    private GSMPhone mGSMPhone;
    private GSMTestHandler mGSMTestHandler;
    private Handler mHandler;

    private static final int EVENT_PHONE_STATE_CHANGED = 1;
    private static final int EVENT_DISCONNECT = 2;
    private static final int EVENT_RINGING = 3;
    private static final int EVENT_CHANNEL_OPENED = 4;
    private static final int EVENT_POST_DIAL = 5;
    private static final int EVENT_DONE = 6;
    private static final int EVENT_SSN = 7;
    private static final int EVENT_MMI_INITIATE = 8;
    private static final int EVENT_MMI_COMPLETE = 9;
    private static final int EVENT_IN_SERVICE = 10;
    private static final int SUPP_SERVICE_FAILED = 11;
    private static final int SERVICE_STATE_CHANGED = 12;
    private static final int EVENT_OEM_RIL_MESSAGE = 13;
    public static final int ANY_MESSAGE = -1;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mGSMTestHandler = new GSMTestHandler(mContext);

        mGSMTestHandler.start();
        synchronized (mGSMTestHandler) {
            do {
                mGSMTestHandler.wait();
            } while (mGSMTestHandler.getGSMPhone() == null);
        }

        mGSMPhone = mGSMTestHandler.getGSMPhone();
        mRadioControl = mGSMTestHandler.getSimulatedCommands();

        mHandler = mGSMTestHandler.getHandler();
        mGSMPhone.registerForPreciseCallStateChanged(mHandler, EVENT_PHONE_STATE_CHANGED, null);
        mGSMPhone.registerForNewRingingConnection(mHandler, EVENT_RINGING, null);
        mGSMPhone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null);

        mGSMPhone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL, null);

        mGSMPhone.registerForSuppServiceNotification(mHandler, EVENT_SSN, null);
        mGSMPhone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null);
        mGSMPhone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null);
        mGSMPhone.registerForSuppServiceFailed(mHandler, SUPP_SERVICE_FAILED, null);

        mGSMPhone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null);

        // wait until we get phone in both voice and data service
        Message msg;
        ServiceState state;

        do {
            msg = mGSMTestHandler.waitForMessage(SERVICE_STATE_CHANGED);
            assertNotNull("Message Time Out", msg);
            state = (ServiceState) ((AsyncResult) msg.obj).result;
        } while (state.getState() != ServiceState.STATE_IN_SERVICE);
    }

    @Override
    protected void tearDown() throws Exception {
        mRadioControl.shutdown();

        mGSMPhone.unregisterForPreciseCallStateChanged(mHandler);
        mGSMPhone.unregisterForNewRingingConnection(mHandler);
        mGSMPhone.unregisterForDisconnect(mHandler);
        mGSMPhone.setOnPostDialCharacter(mHandler, 0, null);
        mGSMPhone.unregisterForSuppServiceNotification(mHandler);
        mGSMPhone.unregisterForMmiInitiate(mHandler);
        mGSMPhone.unregisterForMmiComplete(mHandler);

        mGSMPhone = null;
        mRadioControl = null;
        mHandler = null;
        mGSMTestHandler.cleanup();

        super.tearDown();
    }

    // These test can only be run once.
    public int startPerformance(Intermediates intermediates) {
        return 1;
    }

    public boolean isPerformanceOnly() {
        return false;
    }


    //This test is causing the emulator screen to turn off. I don't understand
    //why, but I'm removing it until we can figure it out.
    public void brokenTestGeneral() throws Exception {
        Connection cn;
        Message msg;
        AsyncResult ar;

        // IDLE state

        assertEquals(Phone.State.IDLE, mGSMPhone.getState());
        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
        assertFalse(mGSMPhone.canConference());

        // One DIALING connection

        mRadioControl.setAutoProgressConnectingCall(false);

        mGSMPhone.dial("+13125551212");

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());

        msg = mGSMTestHandler.waitForMessage(EVENT_PHONE_STATE_CHANGED);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertEquals(Call.State.DIALING, mGSMPhone.getForegroundCall().getState());
        assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        /*do {
            mGSMTestHandler.waitForMessage(ANY_MESSAGE);
        } while (mGSMPhone.getForegroundCall().getConnections().size() == 0);*/

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.DIALING,
                mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        cn = mGSMPhone.getForegroundCall().getConnections().get(0);
        assertTrue(!cn.isIncoming());
        assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());

        assertEquals(Connection.DisconnectCause.NOT_DISCONNECTED, cn.getDisconnectCause());

        assertFalse(mGSMPhone.canConference());

        // One ALERTING connection

        mRadioControl.progressConnectingCallState();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        }
        while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ALERTING, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        cn = mGSMPhone.getForegroundCall().getConnections().get(0);
        assertTrue(!cn.isIncoming());
        assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());
        assertFalse(mGSMPhone.canConference());

        // One ACTIVE connection

        mRadioControl.progressConnectingCallState();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);

        cn = mGSMPhone.getForegroundCall().getConnections().get(0);
        assertTrue(!cn.isIncoming());
        assertEquals(Connection.PostDialState.COMPLETE, cn.getPostDialState());
        assertFalse(mGSMPhone.canConference());

        // One disconnected connection
        mGSMPhone.getForegroundCall().hangup();

        msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.IDLE, mGSMPhone.getState());
        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);

        assertFalse(mGSMPhone.canConference());

        cn = mGSMPhone.getForegroundCall().getEarliestConnection();

        assertEquals(Call.State.DISCONNECTED, cn.getState());

        // Back to idle state

        mGSMPhone.clearDisconnected();

        assertEquals(Phone.State.IDLE, mGSMPhone.getState());
        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        assertFalse(mGSMPhone.canConference());

        // cn left over from before phone.clearDisconnected();

        assertEquals(Call.State.DISCONNECTED, cn.getState());

        // One ringing (INCOMING) call

        mRadioControl.triggerRing("18005551212");

        msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertTrue(mGSMPhone.getRingingCall().isRinging());

        ar = (AsyncResult) msg.obj;
        cn = (Connection) ar.result;
        assertTrue(cn.isRinging());
        assertEquals(mGSMPhone.getRingingCall(), cn.getCall());

        assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.INCOMING, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());

        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        cn = mGSMPhone.getRingingCall().getConnections().get(0);
        assertTrue(cn.isIncoming());
        assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());

        assertFalse(mGSMPhone.canConference());

        // One mobile terminated active call
        mGSMPhone.acceptCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getRingingCall().getConnections().size() == 1);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertFalse(mGSMPhone.getRingingCall().isRinging());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE,
                mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);

        cn = mGSMPhone.getForegroundCall().getConnections().get(0);
        assertTrue(cn.isIncoming());
        assertEquals(Connection.PostDialState.NOT_STARTED, cn.getPostDialState());

        assertFalse(mGSMPhone.canConference());

        // One disconnected (local hangup) call

        try {
            Connection conn;
            conn = mGSMPhone.getForegroundCall().getConnections().get(0);
            conn.hangup();
        } catch (CallStateException ex) {
            ex.printStackTrace();
            fail("unexpected ex");
        }

        msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.IDLE, mGSMPhone.getState());
        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertFalse(mGSMPhone.getRingingCall().isRinging());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.DISCONNECTED,
                mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertTrue(mGSMPhone.getForegroundCall().getEarliestConnectTime() > 0);

        cn = mGSMPhone.getForegroundCall().getEarliestConnection();

        assertEquals(Call.State.DISCONNECTED, cn.getState());

        assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());

        assertFalse(mGSMPhone.canConference());

        // Back to idle state

        mGSMPhone.clearDisconnected();

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertFalse(mGSMPhone.getRingingCall().isRinging());

        assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        assertFalse(mGSMPhone.canConference());

        // cn left over from before phone.clearDisconnected();

        assertEquals(Call.State.DISCONNECTED, cn.getState());

        // One ringing call

        mRadioControl.triggerRing("18005551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getRingingCall().getConnections().isEmpty());

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertTrue(mGSMPhone.getRingingCall().isRinging());

        assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.INCOMING, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());

        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        assertFalse(mGSMPhone.canConference());

        // One rejected call
        mGSMPhone.rejectCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.IDLE);

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertFalse(mGSMPhone.getRingingCall().isRinging());

        assertEquals(1, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getRingingCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getRingingCall().getEarliestConnectTime());

        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        cn = mGSMPhone.getRingingCall().getEarliestConnection();
        assertEquals(Call.State.DISCONNECTED, cn.getState());

        assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());

        assertFalse(mGSMPhone.canConference());

        // Back to idle state

        mGSMPhone.clearDisconnected();

        assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(0, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestCreateTime());
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        assertFalse(mGSMPhone.canConference());
        assertEquals(Call.State.DISCONNECTED, cn.getState());

        // One ringing call

        mRadioControl.triggerRing("18005551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getRingingCall().getConnections().isEmpty());

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertTrue(mGSMPhone.getRingingCall().isRinging());

        cn = mGSMPhone.getRingingCall().getEarliestConnection();

        // Ringing call disconnects

        mRadioControl.triggerHangupForeground();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.IDLE);

        assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());

        // One Ringing Call

        mRadioControl.triggerRing("18005551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.RINGING);


        cn = mGSMPhone.getRingingCall().getEarliestConnection();

        // One answered call
        mGSMPhone.acceptCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.OFFHOOK);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // one holding call
        mGSMPhone.switchHoldingAndActive();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);


        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

        // one active call
        mGSMPhone.switchHoldingAndActive();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        }
        while (mGSMPhone.getBackgroundCall().getState() == Call.State.HOLDING);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // One disconnected call in the foreground slot

        mRadioControl.triggerHangupAll();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.IDLE);

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());

        // Test missed calls

        mRadioControl.triggerRing("18005551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.RINGING);

        mGSMPhone.rejectCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (msg.what != EVENT_DISCONNECT);

        ar = (AsyncResult) msg.obj;
        cn = (Connection) ar.result;

        assertEquals(Connection.DisconnectCause.INCOMING_MISSED, cn.getDisconnectCause());
        assertEquals(Phone.State.IDLE, mGSMPhone.getState());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());

        // Test incoming not missed calls

        mRadioControl.triggerRing("18005551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.RINGING);

        cn = mGSMPhone.getRingingCall().getEarliestConnection();

        mGSMPhone.acceptCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.OFFHOOK);

        assertEquals(Connection.DisconnectCause.NOT_DISCONNECTED, cn.getDisconnectCause());
        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());

        try {
            mGSMPhone.getForegroundCall().hangup();
        } catch (CallStateException ex) {
            ex.printStackTrace();
            fail("unexpected ex");
        }

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState()
                != Call.State.DISCONNECTED);

        assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());

        //
        // Test held and hangup held calls
        //

        // One ALERTING call
        mGSMPhone.dial("+13125551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.OFFHOOK);

        assertTrue(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        mRadioControl.progressConnectingCallState();
        mRadioControl.progressConnectingCallState();

        // One ACTIVE call

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        // One ACTIVE call, one ringing call

        mRadioControl.triggerRing("18005551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.RINGING);

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertTrue(mGSMPhone.getRingingCall().isRinging());

        // One HOLDING call, one ACTIVE call
        mGSMPhone.acceptCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.OFFHOOK);

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
        assertTrue(mGSMPhone.canConference());

        // Conference the two
        mGSMPhone.conference();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertTrue(mGSMPhone.getForegroundCall().isMultiparty());
        assertFalse(mGSMPhone.canConference());

        // Hold the multiparty call
        mGSMPhone.switchHoldingAndActive();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        }
        while (mGSMPhone.getBackgroundCall().getState() != Call.State.HOLDING);

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertTrue(mGSMPhone.getBackgroundCall().isMultiparty());
        assertFalse(mGSMPhone.canConference());

        // Multiparty call on hold, call waiting added

        mRadioControl.triggerRing("18005558355");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.RINGING);

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertTrue(mGSMPhone.getRingingCall().isRinging());

        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
        assertTrue(mGSMPhone.getBackgroundCall().isMultiparty());
        assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
        assertFalse(mGSMPhone.canConference());

        // Hangup conference call, ringing call still around
        mGSMPhone.getBackgroundCall().hangup();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() != Call.State.DISCONNECTED);

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getBackgroundCall().getState());

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertTrue(mGSMPhone.getRingingCall().isRinging());

        // Reject waiting call
        mGSMPhone.rejectCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.IDLE);

        assertFalse(mGSMPhone.getForegroundCall().isDialingOrAlerting());
        assertFalse(mGSMPhone.getRingingCall().isRinging());
    }

    public void testOutgoingCallFailImmediately() throws Exception {
        Message msg;

        // Test outgoing call fail-immediately edge case
        // This happens when a call terminated before ever appearing in a
        // call list
        // This should land the immediately-failing call in the
        // ForegroundCall list as an IDLE call
        mRadioControl.setNextDialFailImmediately(true);

        Connection cn = mGSMPhone.dial("+13125551212");

        msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
        assertNotNull("Message Time Out", msg);
        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
    }

    public void testHangupOnOutgoing() throws Exception {
        Connection cn;
        Message msg;

        mRadioControl.setAutoProgressConnectingCall(false);

        // Test 1: local hangup in "DIALING" state
        mGSMPhone.dial("+13125551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        }
        while (mGSMPhone.getForegroundCall().getState() != Call.State.DIALING);

        cn = mGSMPhone.getForegroundCall().getEarliestConnection();

        mGSMPhone.getForegroundCall().hangup();

        msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
        assertNotNull("Message Time Out", msg);
        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());

        // Test 2: local hangup in "ALERTING" state
        mGSMPhone.dial("+13125551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.OFFHOOK);

        mRadioControl.progressConnectingCallState();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        }
        while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);

        cn = mGSMPhone.getForegroundCall().getEarliestConnection();

        mGSMPhone.getForegroundCall().hangup();

        msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());

        // Test 3: local immediate hangup before GSM index is
        // assigned (CallTracker.hangupPendingMO case)

        mRadioControl.pauseResponses();

        cn = mGSMPhone.dial("+13125551212");

        cn.hangup();

        mRadioControl.resumeResponses();

        msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
        assertNotNull("Message Time Out", msg);
        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());

        assertEquals(Connection.DisconnectCause.LOCAL,
                mGSMPhone.getForegroundCall().getEarliestConnection().getDisconnectCause());
    }

    public void testHangupOnChannelClose() throws Exception {
        mGSMPhone.dial("+13125551212");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getConnections().isEmpty());

        mRadioControl.shutdown();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
            mGSMPhone.clearDisconnected();
        } while (!mGSMPhone.getForegroundCall().getConnections().isEmpty());
    }

    public void testIncallMmiCallDeflection() throws Exception {
        Message msg;

        // establish an active call
        mGSMPhone.dial("+13125551212");

        do {
            mRadioControl.progressConnectingCallState();
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // establish a ringing (WAITING) call

        mRadioControl.triggerRing("18005551212");

        msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertTrue(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // Simulate entering 0 followed by SEND: release all held calls
        // or sets UDUB for a waiting call.
        mGSMPhone.handleInCallMmiCommands("0");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertFalse(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // change the active call to holding call
        mGSMPhone.switchHoldingAndActive();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);


        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

        // Simulate entering 0 followed by SEND: release all held calls
        // or sets UDUB for a waiting call.
        mGSMPhone.handleInCallMmiCommands("0");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() == Call.State.HOLDING);

        assertEquals(Phone.State.IDLE, mGSMPhone.getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getBackgroundCall().getState());
    }

    public void testIncallMmiCallWaiting() throws Exception {
        Message msg;

        // establish an active call
        mGSMPhone.dial("+13125551212");

        do {
            mRadioControl.progressConnectingCallState();
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // establish a ringing (WAITING) call

        mRadioControl.triggerRing("18005551212");

        do {
            msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
            assertNotNull("Message Time Out", msg);
        } while (msg.what != EVENT_RINGING);

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertTrue(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // Simulate entering 1 followed by SEND: release all active calls
        // (if any exist) and accepts the other (held or waiting) call.

        mGSMPhone.handleInCallMmiCommands("1");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertFalse(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals("18005551212",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());

        // change the active call to holding call
        mGSMPhone.switchHoldingAndActive();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);

        assertEquals(Call.State.IDLE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

        // Simulate entering 1 followed by SEND: release all active calls
        // (if any exist) and accepts the other (held or waiting) call.
        mGSMPhone.handleInCallMmiCommands("1");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
        assertEquals("18005551212",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());

        // at this point, the active call with number==18005551212 should
        // have the gsm index of 2

        mRadioControl.triggerRing("16505550100");

        msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertTrue(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // Simulate entering "12" followed by SEND: release the call with
        // gsm index equals to 2.
        mGSMPhone.handleInCallMmiCommands("12");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertTrue(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        mGSMPhone.acceptCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getState() != Phone.State.OFFHOOK);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertFalse(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // at this point, the call with number==16505550100 should
        // have the gsm index of 1
        mGSMPhone.dial("+13125551212");

        do {
            mRadioControl.progressConnectingCallState();
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE ||
                mGSMPhone.getBackgroundCall().getState() != Call.State.HOLDING);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

        // at this point, the active call with number==13125551212 should
        // have the gsm index of 2

        // Simulate entering "11" followed by SEND: release the call with
        // gsm index equals to 1. This should not be allowed, and a
        // Supplementary Service notification must be received.
        mGSMPhone.handleInCallMmiCommands("11");

        msg = mGSMTestHandler.waitForMessage(SUPP_SERVICE_FAILED);
        assertNotNull("Message Time Out", msg);
        assertFalse("IncallMmiCallWaiting: command should not work on holding call", msg == null);

        // Simulate entering "12" followed by SEND: release the call with
        // gsm index equals to 2.
        mGSMPhone.handleInCallMmiCommands("12");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

        // Simulate entering 1 followed by SEND: release all active calls
        // (if any exist) and accepts the other (held or waiting) call.
        mGSMPhone.handleInCallMmiCommands("1");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
        assertEquals("16505550100",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());

        // Simulate entering "11" followed by SEND: release the call with
        // gsm index equals to 1.
        mGSMPhone.handleInCallMmiCommands("11");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
    }

    public void testIncallMmiCallHold() throws Exception {
        Message msg;

        // establish an active call
        mGSMPhone.dial("13125551212");

        do {
            mRadioControl.progressConnectingCallState();
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // establish a ringing (WAITING) call

        mRadioControl.triggerRing("18005551212");

        msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertTrue(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // simulate entering 2 followed by SEND: place all active calls
        // (if any exist) on hold and accepts the other (held or waiting)
        // call

        mGSMPhone.handleInCallMmiCommands("2");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getRingingCall().getState() == Call.State.WAITING);


        assertFalse(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE,
                mGSMPhone.getForegroundCall().getState());
        assertEquals("18005551212",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
        assertEquals("13125551212",
                mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());

        // swap the active and holding calls
        mGSMPhone.handleInCallMmiCommands("2");

        msg = mGSMTestHandler.waitForMessage(EVENT_PHONE_STATE_CHANGED);
        assertNotNull("Message Time Out", msg);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals("13125551212",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
        assertEquals("18005551212",
                mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());

        // merge the calls
        mGSMPhone.conference();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
        assertEquals(2, mGSMPhone.getForegroundCall().getConnections().size());

        // at this point, we have an active conference call, with
        // call(1) = 13125551212 and call(2) = 18005551212

        // Simulate entering "23" followed by SEND: places all active call
        // on hold except call 3. This should fail and a supplementary service
        // failed notification should be received.

        mGSMPhone.handleInCallMmiCommands("23");

        msg = mGSMTestHandler.waitForMessage(SUPP_SERVICE_FAILED);
        assertNotNull("Message Time Out", msg);
        assertFalse("IncallMmiCallHold: separate should have failed!", msg == null);

        // Simulate entering "21" followed by SEND: places all active call
        // on hold except call 1.
        mGSMPhone.handleInCallMmiCommands("21");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() == Call.State.IDLE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals("13125551212",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
        assertEquals("18005551212",
                mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());
    }

    public void testIncallMmiMultipartyServices() throws Exception {
        // establish an active call
        mGSMPhone.dial("13125551212");

        do {
            mRadioControl.progressConnectingCallState();
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        // dial another call
        mGSMPhone.dial("18005551212");

        do {
            mRadioControl.progressConnectingCallState();
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

        mGSMPhone.handleInCallMmiCommands("3");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);

        assertEquals(Phone.State.OFFHOOK, mGSMPhone.getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals("18005551212",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
        assertEquals("13125551212",
                mGSMPhone.getForegroundCall().getConnections().get(1).getAddress());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
    }

    public void testCallIndex() throws Exception {
        Message msg;

        // establish the first call
        mGSMPhone.dial("16505550100");

        do {
            mRadioControl.progressConnectingCallState();
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        String baseNumber = "1650555010";

        for (int i = 1; i < 6; i++) {
            String number = baseNumber + i;

            mGSMPhone.dial(number);

            do {
                mRadioControl.progressConnectingCallState();
                assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
            } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

            assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
            assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

            if (mGSMPhone.getBackgroundCall().getConnections().size() >= 5) {
                break;
            }

            mGSMPhone.conference();

            do {
                assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
            } while (mGSMPhone.getBackgroundCall().getState() != Call.State.IDLE);

            assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
            assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
        }

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals("16505550105",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

        // create an incoming call, this call should have the call index
        // of 7
        mRadioControl.triggerRing("18005551212");

        msg = mGSMTestHandler.waitForMessage(EVENT_RINGING);
        assertNotNull("Message Time Out", msg);

        assertEquals(Phone.State.RINGING, mGSMPhone.getState());
        assertTrue(mGSMPhone.getRingingCall().isRinging());
        assertEquals(Call.State.WAITING, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());

        // hangup the background call and accept the ringing call
        mGSMPhone.getBackgroundCall().hangup();
        mGSMPhone.acceptCall();

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getRingingCall().getState() != Call.State.IDLE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals("18005551212",
                mGSMPhone.getForegroundCall().getConnections().get(0).getAddress());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
        assertEquals("16505550105",
                mGSMPhone.getBackgroundCall().getConnections().get(0).getAddress());

        mGSMPhone.handleInCallMmiCommands("17");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.HOLDING, mGSMPhone.getBackgroundCall().getState());
        assertEquals("16505550105",
                mGSMPhone.getBackgroundCall().getConnections().get(0).
                        getAddress());

        mGSMPhone.handleInCallMmiCommands("1");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() != Call.State.ACTIVE);

        assertEquals(Call.State.ACTIVE, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        mGSMPhone.handleInCallMmiCommands("16");

        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (mGSMPhone.getForegroundCall().getState() == Call.State.ACTIVE);

        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());
    }

    public void testPostDialSequences() throws Exception {
        Message msg;
        AsyncResult ar;
        Connection cn;

        mGSMPhone.dial("+13125551212,1234;5N8xx");

        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        ar = (AsyncResult) (msg.obj);
        cn = (Connection) (ar.result);
        assertEquals(',', msg.arg1);
        assertEquals("1234;5N8", cn.getRemainingPostDialString());


        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals('1', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        assertEquals(Connection.PostDialState.STARTED, ar.userObj);


        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals('2', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        assertEquals(Connection.PostDialState.STARTED, ar.userObj);


        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals('3', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        assertEquals(Connection.PostDialState.STARTED, ar.userObj);


        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals('4', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        assertEquals(Connection.PostDialState.STARTED, ar.userObj);


        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals(';', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        cn = (Connection) (ar.result);
        assertEquals(Connection.PostDialState.WAIT, cn.getPostDialState());
        assertEquals(Connection.PostDialState.WAIT, ar.userObj);
        cn.proceedAfterWaitChar();


        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals('5', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        assertEquals(Connection.PostDialState.STARTED, ar.userObj);


        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertEquals('N', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        cn = (Connection) (ar.result);
        assertEquals(Connection.PostDialState.WILD, cn.getPostDialState());
        assertEquals(Connection.PostDialState.WILD, ar.userObj);
        cn.proceedAfterWildChar(",6;7");


        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        ar = (AsyncResult) (msg.obj);
        cn = (Connection) (ar.result);
        assertEquals(',', msg.arg1);
        assertEquals("6;78", cn.getRemainingPostDialString());

        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals('6', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        assertEquals(Connection.PostDialState.STARTED, ar.userObj);

        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals(';', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        cn = (Connection) (ar.result);
        assertEquals(Connection.PostDialState.WAIT, cn.getPostDialState());
        assertEquals(Connection.PostDialState.WAIT, ar.userObj);
        cn.proceedAfterWaitChar();

        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals('7', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        assertEquals(Connection.PostDialState.STARTED, ar.userObj);

        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals('8', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        assertEquals(Connection.PostDialState.STARTED, ar.userObj);

        // Bogus chars at end should be ignored
        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals(0, msg.arg1);
        ar = (AsyncResult) (msg.obj);
        cn = (Connection) (ar.result);
        assertEquals(Connection.PostDialState.COMPLETE,
                cn.getPostDialState());
        assertEquals(Connection.PostDialState.COMPLETE, ar.userObj);
    }

    public void testPostDialCancel() throws Exception {
        Message msg;
        AsyncResult ar;
        Connection cn;

        mGSMPhone.dial("+13125551212,N");
        mRadioControl.progressConnectingToActive();

        mRadioControl.progressConnectingToActive();

        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertNotNull("Message Time Out", msg);
        assertEquals(',', msg.arg1);

        msg = mGSMTestHandler.waitForMessage(EVENT_POST_DIAL);
        assertEquals('N', msg.arg1);
        ar = (AsyncResult) (msg.obj);
        cn = (Connection) (ar.result);
        assertEquals(Connection.PostDialState.WILD, cn.getPostDialState());
        cn.cancelPostDial();

        assertEquals(Connection.PostDialState.CANCELLED, cn.getPostDialState());
    }

    public void testOutgoingCallFail() throws Exception {
        Message msg;
        /*
        * normal clearing
        */

        mRadioControl.setNextCallFailCause(CallFailCause.NORMAL_CLEARING);
        mRadioControl.setAutoProgressConnectingCall(false);

        Connection cn = mGSMPhone.dial("+13125551212");

        mRadioControl.progressConnectingCallState();

        // I'm just progressing the call state to
        // ensure getCurrentCalls() gets processed...
        // Normally these failure conditions would happen in DIALING
        // not ALERTING
        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (cn.getState() == Call.State.DIALING);


        mRadioControl.triggerHangupAll();
        msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
        assertNotNull("Message Time Out", msg);
        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        /*
        * busy
        */

        mRadioControl.setNextCallFailCause(CallFailCause.USER_BUSY);
        mRadioControl.setAutoProgressConnectingCall(false);

        cn = mGSMPhone.dial("+13125551212");

        mRadioControl.progressConnectingCallState();

        // I'm just progressing the call state to
        // ensure getCurrentCalls() gets processed...
        // Normally these failure conditions would happen in DIALING
        // not ALERTING
        do {
            assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));
        } while (cn.getState() == Call.State.DIALING);


        mRadioControl.triggerHangupAll();
        msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);
        assertNotNull("Message Time Out", msg);
        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(Connection.DisconnectCause.BUSY, cn.getDisconnectCause());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.DISCONNECTED,
                mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());

        /*
        * congestion
        */

        mRadioControl.setNextCallFailCause(CallFailCause.NO_CIRCUIT_AVAIL);
        mRadioControl.setAutoProgressConnectingCall(false);

        cn = mGSMPhone.dial("+13125551212");

        mRadioControl.progressConnectingCallState();

        // I'm just progressing the call state to
        // ensure getCurrentCalls() gets processed...
        // Normally these failure conditions would happen in DIALING
        // not ALERTING
        do {
            msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
            assertNotNull("Message Time Out", msg);
        } while (cn.getState() == Call.State.DIALING);


        mRadioControl.triggerHangupAll();

        // Unlike the while loops above, this one waits
        // for a "phone state changed" message back to "idle"
        do {
            msg = mGSMTestHandler.waitForMessage(ANY_MESSAGE);
            assertNotNull("Message Time Out", msg);
        } while (!(msg.what == EVENT_PHONE_STATE_CHANGED
                && mGSMPhone.getState() == Phone.State.IDLE));

        assertEquals(Phone.State.IDLE, mGSMPhone.getState());

        assertEquals(Connection.DisconnectCause.CONGESTION, cn.getDisconnectCause());

        assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());
        assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());
        assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());

        assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());
        assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());
        assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());

        assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);
        assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
    }

    public void testSSNotification() throws Exception {
        // MO
        runTest(0, SuppServiceNotification.MO_CODE_UNCONDITIONAL_CF_ACTIVE);
        runTest(0, SuppServiceNotification.MO_CODE_CALL_IS_WAITING);
        runTest(0, SuppServiceNotification.MO_CODE_CALL_DEFLECTED);

        // MT
        runTest(1, SuppServiceNotification.MT_CODE_FORWARDED_CALL);
        runTest(1, SuppServiceNotification.MT_CODE_CALL_CONNECTED_ECT);
        runTest(1, SuppServiceNotification.MT_CODE_ADDITIONAL_CALL_FORWARDED);
    }

    private void runTest(int type, int code) {
        Message msg;

        mRadioControl.triggerSsn(type, code);

        msg = mGSMTestHandler.waitForMessage(EVENT_SSN);
        assertNotNull("Message Time Out", msg);
        AsyncResult ar = (AsyncResult) msg.obj;

        assertNull(ar.exception);

        SuppServiceNotification notification =
                (SuppServiceNotification) ar.result;

        assertEquals(type, notification.notificationType);
        assertEquals(code, notification.code);
    }

    public void testUssd() throws Exception {
        // Quick hack to work around a race condition in this test:
        // We may initiate a USSD MMI before GSMPhone receives its initial
        // GSMTestHandler.EVENT_RADIO_OFF_OR_NOT_AVAILABLE event.  When the phone sees this
        // event, it will cancel the just issued USSD MMI, which we don't
        // want.  So sleep a little first.
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            // do nothing
        }

        verifyNormal();
        verifyCancel();
        varifyNetworkInitiated();
    }

    private void varifyNetworkInitiated() {
        Message msg;
        AsyncResult ar;
        MmiCode mmi;

        // Receive an incoming NOTIFY
        mRadioControl.triggerIncomingUssd("0", "NOTIFY message");
        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
        assertNotNull("Message Time Out", msg);
        ar = (AsyncResult) msg.obj;
        mmi = (MmiCode) ar.result;

        assertFalse(mmi.isUssdRequest());

        // Receive a REQUEST and send response
        mRadioControl.triggerIncomingUssd("1", "REQUEST Message");
        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
        assertNotNull("Message Time Out", msg);
        ar = (AsyncResult) msg.obj;
        mmi = (MmiCode) ar.result;

        assertTrue(mmi.isUssdRequest());

        mGSMPhone.sendUssdResponse("## TEST: TEST_GSMPhone responding...");
        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
        assertNotNull("Message Time Out", msg);
        ar = (AsyncResult) msg.obj;
        mmi = (MmiCode) ar.result;

        GsmMmiCode gsmMmi = (GsmMmiCode) mmi;
        assertTrue(gsmMmi.isPendingUSSD());
        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
        assertNotNull("Message Time Out", msg);
        ar = (AsyncResult) msg.obj;
        mmi = (MmiCode) ar.result;

        assertNull(ar.exception);
        assertFalse(mmi.isUssdRequest());

        // Receive a REQUEST and cancel
        mRadioControl.triggerIncomingUssd("1", "REQUEST Message");
        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
        assertNotNull("Message Time Out", msg);
        ar = (AsyncResult) msg.obj;
        mmi = (MmiCode) ar.result;

        assertTrue(mmi.isUssdRequest());

        mmi.cancel();
        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
        assertNotNull("Message Time Out", msg);

        ar = (AsyncResult) msg.obj;
        mmi = (MmiCode) ar.result;

        assertNull(ar.exception);
        assertEquals(MmiCode.State.CANCELLED, mmi.getState());

        List mmiList = mGSMPhone.getPendingMmiCodes();
        assertEquals(0, mmiList.size());
    }

    private void verifyNormal() throws CallStateException {
        Message msg;
        AsyncResult ar;
        MmiCode mmi;

        mGSMPhone.dial("#646#");

        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
        assertNotNull("Message Time Out", msg);

        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
        assertNotNull("Message Time Out", msg);

        ar = (AsyncResult) msg.obj;
        mmi = (MmiCode) ar.result;
        assertEquals(MmiCode.State.COMPLETE, mmi.getState());
    }


    private void verifyCancel() throws CallStateException {
        /**
         * This case makes an assumption that dial() will add the USSD
         * to the "pending MMI codes" list before it returns.  This seems
         * like reasonable semantics. It also assumes that the USSD
         * request in question won't complete until we get back to the
         * event loop, thus cancel() is safe.
         */
        Message msg;

        mGSMPhone.dial("#646#");

        List<? extends MmiCode> pendingMmis = mGSMPhone.getPendingMmiCodes();

        assertEquals(1, pendingMmis.size());

        MmiCode mmi = pendingMmis.get(0);
        assertTrue(mmi.isCancelable());
        mmi.cancel();

        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
        assertNotNull("Message Time Out", msg);

        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
        assertNotNull("Message Time Out", msg);

        AsyncResult ar = (AsyncResult) msg.obj;
        mmi = (MmiCode) ar.result;

        assertEquals(MmiCode.State.CANCELLED, mmi.getState());
    }

    public void testRilHooks() throws Exception {
        //
        // These test cases all assume the RIL OEM hooks
        // just echo back their input
        //

        Message msg;
        AsyncResult ar;

        // null byte array

        mGSMPhone.invokeOemRilRequestRaw(null, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));

        msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
        assertNotNull("Message Time Out", msg);

        ar = ((AsyncResult) msg.obj);

        assertNull(ar.result);
        assertNull(ar.exception);

        // empty byte array

        mGSMPhone.invokeOemRilRequestRaw(new byte[0], mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));

        msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
        assertNotNull("Message Time Out", msg);

        ar = ((AsyncResult) msg.obj);

        assertEquals(0, ((byte[]) (ar.result)).length);
        assertNull(ar.exception);

        // byte array with data

        mGSMPhone.invokeOemRilRequestRaw("Hello".getBytes("utf-8"),
                mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));

        msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
        assertNotNull("Message Time Out", msg);

        ar = ((AsyncResult) msg.obj);

        assertEquals("Hello", new String(((byte[]) (ar.result)), "utf-8"));
        assertNull(ar.exception);

        // null strings

        mGSMPhone.invokeOemRilRequestStrings(null, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));

        msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
        assertNotNull("Message Time Out", msg);

        ar = ((AsyncResult) msg.obj);

        assertNull(ar.result);
        assertNull(ar.exception);

        // empty byte array

        mGSMPhone.invokeOemRilRequestStrings(new String[0],
                mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));

        msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
        assertNotNull("Message Time Out", msg);

        ar = ((AsyncResult) msg.obj);

        assertEquals(0, ((String[]) (ar.result)).length);
        assertNull(ar.exception);

        // Strings with data

        String s[] = new String[1];

        s[0] = "Hello";

        mGSMPhone.invokeOemRilRequestStrings(s, mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE));

        msg = mGSMTestHandler.waitForMessage(EVENT_OEM_RIL_MESSAGE);
        assertNotNull("Message Time Out", msg);

        ar = ((AsyncResult) msg.obj);

        assertEquals("Hello", ((String[]) (ar.result))[0]);
        assertEquals(1, ((String[]) (ar.result)).length);
        assertNull(ar.exception);
    }

    public void testMmi() throws Exception {
        mRadioControl.setAutoProgressConnectingCall(false);

        // "valid" MMI sequences
        runValidMmi("*#67#", false);
        runValidMmi("##43*11#", false);
        runValidMmi("#33*1234*11#", false);
        runValidMmi("*21*6505551234**5#", false);
        runValidMmi("**03**1234*4321*4321#", false);
        // pound string
        runValidMmi("5308234092307540923#", true);
        // short code
        runValidMmi("22", true);
        // as part of call setup
        runValidMmiWithConnect("*31#6505551234");

        // invalid MMI sequences
        runNotMmi("6505551234");
        runNotMmi("1234#*12#34566654");
        runNotMmi("*#*#12#*");
    }

    private void runValidMmi(String dialString, boolean cancelable) throws CallStateException {
        Connection c = mGSMPhone.dial(dialString);
        assertNull(c);
        Message msg = mGSMTestHandler.waitForMessage(EVENT_MMI_INITIATE);
        assertNotNull("Message Time Out", msg);
        // Should not be cancelable.
        AsyncResult ar = (AsyncResult) msg.obj;
        MmiCode mmi = (MmiCode) ar.result;
        assertEquals(cancelable, mmi.isCancelable());

        msg = mGSMTestHandler.waitForMessage(EVENT_MMI_COMPLETE);
        assertNotNull("Message Time Out", msg);
    }

    private void runValidMmiWithConnect(String dialString) throws CallStateException {
        mRadioControl.pauseResponses();

        Connection c = mGSMPhone.dial(dialString);
        assertNotNull(c);

        hangup(c);
    }

    private void hangup(Connection cn) throws CallStateException {
        cn.hangup();

        mRadioControl.resumeResponses();
        assertNotNull(mGSMTestHandler.waitForMessage(EVENT_DISCONNECT));

    }

    private void runNotMmi(String dialString) throws CallStateException {
        mRadioControl.pauseResponses();

        Connection c = mGSMPhone.dial(dialString);
        assertNotNull(c);

        hangup(c);
    }
}

Other Android examples (source code examples)

Here is a short list of links related to this Android GSMPhoneTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.