/*
 * Copyright (C) 2006 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.phone;

import android.app.Activity;
import android.app.ActivityOptions;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothHeadsetPhone;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.media.AudioManager;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.telephony.ServiceState;
import android.text.TextUtils;
import android.text.method.DialerKeyListener;
import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallManager;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.MmiCode;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyCapabilities;
import com.android.phone.Constants.CallStatusCode;
import com.android.phone.InCallUiState.InCallScreenMode;
import com.android.phone.OtaUtils.CdmaOtaScreenState;

import java.util.List;


/**
 * Phone app "in call" screen.
 */
public class InCallScreen extends Activity
        implements View.OnClickListener {
    private static final String LOG_TAG = "InCallScreen";

    private static final boolean DBG =
            (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
    private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2);

    /**
     * Intent extra used to specify whether the DTMF dialpad should be
     * initially visible when bringing up the InCallScreen.  (If this
     * extra is present, the dialpad will be initially shown if the extra
     * has the boolean value true, and initially hidden otherwise.)
     */
    // TODO: Should be EXTRA_SHOW_DIALPAD for consistency.
    static final String SHOW_DIALPAD_EXTRA = "com.android.phone.ShowDialpad";

    /**
     * Intent extra to specify the package name of the gateway
     * provider.  Used to get the name displayed in the in-call screen
     * during the call setup. The value is a string.
     */
    // TODO: This extra is currently set by the gateway application as
    // a temporary measure. Ultimately, the framework will securely
    // set it.
    /* package */ static final String EXTRA_GATEWAY_PROVIDER_PACKAGE =
            "com.android.phone.extra.GATEWAY_PROVIDER_PACKAGE";

    /**
     * Intent extra to specify the URI of the provider to place the
     * call. The value is a string. It holds the gateway address
     * (phone gateway URL should start with the 'tel:' scheme) that
     * will actually be contacted to call the number passed in the
     * intent URL or in the EXTRA_PHONE_NUMBER extra.
     */
    // TODO: Should the value be a Uri (Parcelable)? Need to make sure
    // MMI code '#' don't get confused as URI fragments.
    /* package */ static final String EXTRA_GATEWAY_URI =
            "com.android.phone.extra.GATEWAY_URI";

    // Amount of time (in msec) that we display the "Call ended" state.
    // The "short" value is for calls ended by the local user, and the
    // "long" value is for calls ended by the remote caller.
    private static final int CALL_ENDED_SHORT_DELAY =  200;  // msec
    private static final int CALL_ENDED_LONG_DELAY = 2000;  // msec
    private static final int CALL_ENDED_EXTRA_LONG_DELAY = 5000;  // msec

    // Amount of time that we display the PAUSE alert Dialog showing the
    // post dial string yet to be send out to the n/w
    private static final int PAUSE_PROMPT_DIALOG_TIMEOUT = 2000;  //msec

    // Amount of time that we display the provider info if applicable.
    private static final int PROVIDER_INFO_TIMEOUT = 5000;  // msec

    // These are values for the settings of the auto retry mode:
    // 0 = disabled
    // 1 = enabled
    // TODO (Moto):These constants don't really belong here,
    // they should be moved to Settings where the value is being looked up in the first place
    static final int AUTO_RETRY_OFF = 0;
    static final int AUTO_RETRY_ON = 1;

    // Message codes; see mHandler below.
    // Note message codes < 100 are reserved for the PhoneApp.
    private static final int PHONE_STATE_CHANGED = 101;
    private static final int PHONE_DISCONNECT = 102;
    private static final int EVENT_HEADSET_PLUG_STATE_CHANGED = 103;
    private static final int POST_ON_DIAL_CHARS = 104;
    private static final int WILD_PROMPT_CHAR_ENTERED = 105;
    private static final int ADD_VOICEMAIL_NUMBER = 106;
    private static final int DONT_ADD_VOICEMAIL_NUMBER = 107;
    private static final int DELAYED_CLEANUP_AFTER_DISCONNECT = 108;
    private static final int SUPP_SERVICE_FAILED = 110;
    private static final int REQUEST_UPDATE_BLUETOOTH_INDICATION = 114;
    private static final int PHONE_CDMA_CALL_WAITING = 115;
    private static final int REQUEST_CLOSE_SPC_ERROR_NOTICE = 118;
    private static final int REQUEST_CLOSE_OTA_FAILURE_NOTICE = 119;
    private static final int EVENT_PAUSE_DIALOG_COMPLETE = 120;
    private static final int EVENT_HIDE_PROVIDER_INFO = 121;  // Time to remove the info.
    private static final int REQUEST_UPDATE_SCREEN = 122;
    private static final int PHONE_INCOMING_RING = 123;
    private static final int PHONE_NEW_RINGING_CONNECTION = 124;

    // When InCallScreenMode is UNDEFINED set the default action
    // to ACTION_UNDEFINED so if we are resumed the activity will
    // know its undefined. In particular checkIsOtaCall will return
    // false.
    public static final String ACTION_UNDEFINED = "com.android.phone.InCallScreen.UNDEFINED";

    /** Status codes returned from syncWithPhoneState(). */
    private enum SyncWithPhoneStateStatus {
        /**
         * Successfully updated our internal state based on the telephony state.
         */
        SUCCESS,

        /**
         * There was no phone state to sync with (i.e. the phone was
         * completely idle).  In most cases this means that the
         * in-call UI shouldn't be visible in the first place, unless
         * we need to remain in the foreground while displaying an
         * error message.
         */
        PHONE_NOT_IN_USE
    }

    private boolean mRegisteredForPhoneStates;

    private PhoneGlobals mApp;
    private CallManager mCM;

    // TODO: need to clean up all remaining uses of mPhone.
    // (There may be more than one Phone instance on the device, so it's wrong
    // to just keep a single mPhone field.  Instead, any time we need a Phone
    // reference we should get it dynamically from the CallManager, probably
    // based on the current foreground Call.)
    private Phone mPhone;

    private BluetoothHeadset mBluetoothHeadset;
    private BluetoothAdapter mBluetoothAdapter;
    private boolean mBluetoothConnectionPending;
    private long mBluetoothConnectionRequestTime;

    /** Main in-call UI elements. */
    private CallCard mCallCard;

    // UI controls:
    private InCallControlState mInCallControlState;
    private InCallTouchUi mInCallTouchUi;
    private RespondViaSmsManager mRespondViaSmsManager;  // see internalRespondViaSms()
    private ManageConferenceUtils mManageConferenceUtils;

    // DTMF Dialer controller and its view:
    private DTMFTwelveKeyDialer mDialer;

    private EditText mWildPromptText;

    // Various dialogs we bring up (see dismissAllDialogs()).
    // TODO: convert these all to use the "managed dialogs" framework.
    //
    // The MMI started dialog can actually be one of 2 items:
    //   1. An alert dialog if the MMI code is a normal MMI
    //   2. A progress dialog if the user requested a USSD
    private Dialog mMmiStartedDialog;
    private AlertDialog mMissingVoicemailDialog;
    private AlertDialog mGenericErrorDialog;
    private AlertDialog mSuppServiceFailureDialog;
    private AlertDialog mWaitPromptDialog;
    private AlertDialog mWildPromptDialog;
    private AlertDialog mCallLostDialog;
    private AlertDialog mPausePromptDialog;
    private AlertDialog mExitingECMDialog;
    // NOTE: if you add a new dialog here, be sure to add it to dismissAllDialogs() also.

    // ProgressDialog created by showProgressIndication()
    private ProgressDialog mProgressDialog;

    // TODO: If the Activity class ever provides an easy way to get the
    // current "activity lifecycle" state, we can remove these flags.
    private boolean mIsDestroyed = false;
    private boolean mIsForegroundActivity = false;
    private boolean mIsForegroundActivityForProximity = false;
    private PowerManager mPowerManager;

    // For use with Pause/Wait dialogs
    private String mPostDialStrAfterPause;
    private boolean mPauseInProgress = false;

    // Info about the most-recently-disconnected Connection, which is used
    // to determine what should happen when exiting the InCallScreen after a
    // call.  (This info is set by onDisconnect(), and used by
    // delayedCleanupAfterDisconnect().)
    private Connection.DisconnectCause mLastDisconnectCause;

    /** In-call audio routing options; see switchInCallAudio(). */
    public enum InCallAudioMode {
        SPEAKER,    // Speakerphone
        BLUETOOTH,  // Bluetooth headset (if available)
        EARPIECE,   // Handset earpiece (or wired headset, if connected)
    }


    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (mIsDestroyed) {
                if (DBG) log("Handler: ignoring message " + msg + "; we're destroyed!");
                return;
            }
            if (!mIsForegroundActivity) {
                if (DBG) log("Handler: handling message " + msg + " while not in foreground");
                // Continue anyway; some of the messages below *want* to
                // be handled even if we're not the foreground activity
                // (like DELAYED_CLEANUP_AFTER_DISCONNECT), and they all
                // should at least be safe to handle if we're not in the
                // foreground...
            }

            switch (msg.what) {
                case SUPP_SERVICE_FAILED:
                    onSuppServiceFailed((AsyncResult) msg.obj);
                    break;

                case PHONE_STATE_CHANGED:
                    onPhoneStateChanged((AsyncResult) msg.obj);
                    break;

                case PHONE_DISCONNECT:
                    onDisconnect((AsyncResult) msg.obj);
                    break;

                case EVENT_HEADSET_PLUG_STATE_CHANGED:
                    // Update the in-call UI, since some UI elements (such
                    // as the "Speaker" button) may change state depending on
                    // whether a headset is plugged in.
                    // TODO: A full updateScreen() is overkill here, since
                    // the value of PhoneApp.isHeadsetPlugged() only affects a
                    // single onscreen UI element.  (But even a full updateScreen()
                    // is still pretty cheap, so let's keep this simple
                    // for now.)
                    updateScreen();

                    // Also, force the "audio mode" popup to refresh itself if
                    // it's visible, since one of its items is either "Wired
                    // headset" or "Handset earpiece" depending on whether the
                    // headset is plugged in or not.
                    mInCallTouchUi.refreshAudioModePopup();  // safe even if the popup's not active

                    break;

                // TODO: sort out MMI code (probably we should remove this method entirely).
                // See also MMI handling code in onResume()
                // case PhoneApp.MMI_INITIATE:
                // onMMIInitiate((AsyncResult) msg.obj);
                //    break;

                case PhoneGlobals.MMI_CANCEL:
                    onMMICancel();
                    break;

                // handle the mmi complete message.
                // since the message display class has been replaced with
                // a system dialog in PhoneUtils.displayMMIComplete(), we
                // should finish the activity here to close the window.
                case PhoneGlobals.MMI_COMPLETE:
                    onMMIComplete((MmiCode) ((AsyncResult) msg.obj).result);
                    break;

                case POST_ON_DIAL_CHARS:
                    handlePostOnDialChars((AsyncResult) msg.obj, (char) msg.arg1);
                    break;

                case ADD_VOICEMAIL_NUMBER:
                    addVoiceMailNumberPanel();
                    break;

                case DONT_ADD_VOICEMAIL_NUMBER:
                    dontAddVoiceMailNumber();
                    break;

                case DELAYED_CLEANUP_AFTER_DISCONNECT:
                    delayedCleanupAfterDisconnect();
                    break;

                case REQUEST_UPDATE_BLUETOOTH_INDICATION:
                    if (VDBG) log("REQUEST_UPDATE_BLUETOOTH_INDICATION...");
                    // The bluetooth headset state changed, so some UI
                    // elements may need to update.  (There's no need to
                    // look up the current state here, since any UI
                    // elements that care about the bluetooth state get it
                    // directly from PhoneApp.showBluetoothIndication().)
                    updateScreen();
                    break;

                case PHONE_CDMA_CALL_WAITING:
                    if (DBG) log("Received PHONE_CDMA_CALL_WAITING event ...");
                    Connection cn = mCM.getFirstActiveRingingCall().getLatestConnection();

                    // Only proceed if we get a valid connection object
                    if (cn != null) {
                        // Finally update screen with Call waiting info and request
                        // screen to wake up
                        updateScreen();
                        mApp.updateWakeState();
                    }
                    break;

                case REQUEST_CLOSE_SPC_ERROR_NOTICE:
                    if (mApp.otaUtils != null) {
                        mApp.otaUtils.onOtaCloseSpcNotice();
                    }
                    break;

                case REQUEST_CLOSE_OTA_FAILURE_NOTICE:
                    if (mApp.otaUtils != null) {
                        mApp.otaUtils.onOtaCloseFailureNotice();
                    }
                    break;

                case EVENT_PAUSE_DIALOG_COMPLETE:
                    if (mPausePromptDialog != null) {
                        if (DBG) log("- DISMISSING mPausePromptDialog.");
                        mPausePromptDialog.dismiss();  // safe even if already dismissed
                        mPausePromptDialog = null;
                    }
                    break;

                case EVENT_HIDE_PROVIDER_INFO:
                    mApp.inCallUiState.providerInfoVisible = false;
                    if (mCallCard != null) {
                        mCallCard.updateState(mCM);
                    }
                    break;
                case REQUEST_UPDATE_SCREEN:
                    updateScreen();
                    break;

                case PHONE_INCOMING_RING:
                    onIncomingRing();
                    break;

                case PHONE_NEW_RINGING_CONNECTION:
                    onNewRingingConnection();
                    break;

                default:
                    Log.wtf(LOG_TAG, "mHandler: unexpected message: " + msg);
                    break;
            }
        }
    };

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
                    // Listen for ACTION_HEADSET_PLUG broadcasts so that we
                    // can update the onscreen UI when the headset state changes.
                    // if (DBG) log("mReceiver: ACTION_HEADSET_PLUG");
                    // if (DBG) log("==> intent: " + intent);
                    // if (DBG) log("    state: " + intent.getIntExtra("state", 0));
                    // if (DBG) log("    name: " + intent.getStringExtra("name"));
                    // send the event and add the state as an argument.
                    Message message = Message.obtain(mHandler, EVENT_HEADSET_PLUG_STATE_CHANGED,
                            intent.getIntExtra("state", 0), 0);
                    mHandler.sendMessage(message);
                }
            }
        };


    @Override
    protected void onCreate(Bundle icicle) {
        Log.i(LOG_TAG, "onCreate()...  this = " + this);
        Profiler.callScreenOnCreate();
        super.onCreate(icicle);

        // Make sure this is a voice-capable device.
        if (!PhoneGlobals.sVoiceCapable) {
            // There should be no way to ever reach the InCallScreen on a
            // non-voice-capable device, since this activity is not exported by
            // our manifest, and we explicitly disable any other external APIs
            // like the CALL intent and ITelephony.showCallScreen().
            // So the fact that we got here indicates a phone app bug.
            Log.wtf(LOG_TAG, "onCreate() reached on non-voice-capable device");
            finish();
            return;
        }

        mApp = PhoneGlobals.getInstance();
        mApp.setInCallScreenInstance(this);

        // set this flag so this activity will stay in front of the keyguard
        int flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
        if (mApp.getPhoneState() == PhoneConstants.State.OFFHOOK) {
            // While we are in call, the in-call screen should dismiss the keyguard.
            // This allows the user to press Home to go directly home without going through
            // an insecure lock screen.
            // But we do not want to do this if there is no active call so we do not
            // bypass the keyguard if the call is not answered or declined.
            flags |= WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
        }

        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.flags |= flags;
        if (!mApp.proximitySensorModeEnabled()) {
            // If we don't have a proximity sensor, then the in-call screen explicitly
            // controls user activity.  This is to prevent spurious touches from waking
            // the display.
            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
        }
        getWindow().setAttributes(lp);

        setPhone(mApp.phone);  // Sets mPhone

        mCM =  mApp.mCM;
        log("- onCreate: phone state = " + mCM.getState());

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.getProfileProxy(getApplicationContext(), mBluetoothProfileServiceListener,
                                    BluetoothProfile.HEADSET);
        }

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        // Inflate everything in incall_screen.xml and add it to the screen.
        setContentView(R.layout.incall_screen);

        // If in landscape, then one of the ViewStubs (instead of <include>) is used for the
        // incall_touch_ui, because CDMA and GSM button layouts are noticeably different.
        final ViewStub touchUiStub = (ViewStub) findViewById(
                mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA
                ? R.id.inCallTouchUiCdmaStub : R.id.inCallTouchUiStub);
        if (touchUiStub != null) touchUiStub.inflate();

        initInCallScreen();

        registerForPhoneStates();

        // No need to change wake state here; that happens in onResume() when we
        // are actually displayed.

        // Handle the Intent we were launched with, but only if this is the
        // the very first time we're being launched (ie. NOT if we're being
        // re-initialized after previously being shut down.)
        // Once we're up and running, any future Intents we need
        // to handle will come in via the onNewIntent() method.
        if (icicle == null) {
            if (DBG) log("onCreate(): this is our very first launch, checking intent...");
            internalResolveIntent(getIntent());
        }

        Profiler.callScreenCreated();
        if (DBG) log("onCreate(): exit");
    }

     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
             new BluetoothProfile.ServiceListener() {
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
             mBluetoothHeadset = (BluetoothHeadset) proxy;
             if (VDBG) log("- Got BluetoothHeadset: " + mBluetoothHeadset);
         }

         @Override
         public void onServiceDisconnected(int profile) {
             mBluetoothHeadset = null;
         }
    };

    /**
     * Sets the Phone object used internally by the InCallScreen.
     *
     * In normal operation this is called from onCreate(), and the
     * passed-in Phone object comes from the PhoneApp.
     * For testing, test classes can use this method to
     * inject a test Phone instance.
     */
    /* package */ void setPhone(Phone phone) {
        mPhone = phone;
    }

    @Override
    protected void onResume() {
        if (DBG) log("onResume()...");
        super.onResume();

        mIsForegroundActivity = true;
        mIsForegroundActivityForProximity = true;

        // The flag shouldn't be turned on when there are actual phone calls.
        if (mCM.hasActiveFgCall() || mCM.hasActiveBgCall() || mCM.hasActiveRingingCall()) {
            mApp.inCallUiState.showAlreadyDisconnectedState = false;
        }

        final InCallUiState inCallUiState = mApp.inCallUiState;
        if (VDBG) inCallUiState.dumpState();

        updateExpandedViewState();

        // ...and update the in-call notification too, since the status bar
        // icon needs to be hidden while we're the foreground activity:
        mApp.notificationMgr.updateInCallNotification();

        // Listen for broadcast intents that might affect the onscreen UI.
        registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));

        // Keep a "dialer session" active when we're in the foreground.
        // (This is needed to play DTMF tones.)
        mDialer.startDialerSession();

        // Restore various other state from the InCallUiState object:

        // Update the onscreen dialpad state to match the InCallUiState.
        if (inCallUiState.showDialpad) {
            openDialpadInternal(false);  // no "opening" animation
        } else {
            closeDialpadInternal(false);  // no "closing" animation
        }

        // Reset the dialpad context
        // TODO: Dialpad digits should be set here as well (once they are saved)
        mDialer.setDialpadContext(inCallUiState.dialpadContextText);

        // If there's a "Respond via SMS" popup still around since the
        // last time we were the foreground activity, make sure it's not
        // still active!
        // (The popup should *never* be visible initially when we first
        // come to the foreground; it only ever comes up in response to
        // the user selecting the "SMS" option from the incoming call
        // widget.)
        mRespondViaSmsManager.dismissPopup();  // safe even if already dismissed

        // Display an error / diagnostic indication if necessary.
        //
        // When the InCallScreen comes to the foreground, we normally we
        // display the in-call UI in whatever state is appropriate based on
        // the state of the telephony framework (e.g. an outgoing call in
        // DIALING state, an incoming call, etc.)
        //
        // But if the InCallUiState has a "pending call status code" set,
        // that means we need to display some kind of status or error
        // indication to the user instead of the regular in-call UI.  (The
        // most common example of this is when there's some kind of
        // failure while initiating an outgoing call; see
        // CallController.placeCall().)
        //
        boolean handledStartupError = false;
        if (inCallUiState.hasPendingCallStatusCode()) {
            if (DBG) log("- onResume: need to show status indication!");
            showStatusIndication(inCallUiState.getPendingCallStatusCode());

            // Set handledStartupError to ensure that we won't bail out below.
            // (We need to stay here in the InCallScreen so that the user
            // is able to see the error dialog!)
            handledStartupError = true;
        }

        // Set the volume control handler while we are in the foreground.
        final boolean bluetoothConnected = isBluetoothAudioConnected();

        if (bluetoothConnected) {
            setVolumeControlStream(AudioManager.STREAM_BLUETOOTH_SCO);
        } else {
            setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
        }

        takeKeyEvents(true);

        // If an OTASP call is in progress, use the special OTASP-specific UI.
        boolean inOtaCall = false;
        if (TelephonyCapabilities.supportsOtasp(mPhone)) {
            inOtaCall = checkOtaspStateOnResume();
        }
        if (!inOtaCall) {
            // Always start off in NORMAL mode
            setInCallScreenMode(InCallScreenMode.NORMAL);
        }

        // Before checking the state of the CallManager, clean up any
        // connections in the DISCONNECTED state.
        // (The DISCONNECTED state is used only to drive the "call ended"
        // UI; it's totally useless when *entering* the InCallScreen.)
        mCM.clearDisconnected();

        // Update the onscreen UI to reflect the current telephony state.
        SyncWithPhoneStateStatus status = syncWithPhoneState();

        // Note there's no need to call updateScreen() here;
        // syncWithPhoneState() already did that if necessary.

        if (status != SyncWithPhoneStateStatus.SUCCESS) {
            if (DBG) log("- onResume: syncWithPhoneState failed! status = " + status);
            // Couldn't update the UI, presumably because the phone is totally
            // idle.

            // Even though the phone is idle, though, we do still need to
            // stay here on the InCallScreen if we're displaying an
            // error dialog (see "showStatusIndication()" above).

            if (handledStartupError) {
                // Stay here for now.  We'll eventually leave the
                // InCallScreen when the user presses the dialog's OK
                // button (see bailOutAfterErrorDialog()), or when the
                // progress indicator goes away.
                Log.i(LOG_TAG, "  ==> syncWithPhoneState failed, but staying here anyway.");
            } else {
                // The phone is idle, and we did NOT handle a
                // startup error during this pass thru onResume.
                //
                // This basically means that we're being resumed because of
                // some action *other* than a new intent.  (For example,
                // the user pressing POWER to wake up the device, causing
                // the InCallScreen to come back to the foreground.)
                //
                // In this scenario we do NOT want to stay here on the
                // InCallScreen: we're not showing any useful info to the
                // user (like a dialog), and the in-call UI itself is
                // useless if there's no active call.  So bail out.

                Log.i(LOG_TAG, "  ==> syncWithPhoneState failed; bailing out!");
                dismissAllDialogs();

                // Force the InCallScreen to truly finish(), rather than just
                // moving it to the back of the activity stack (which is what
                // our finish() method usually does.)
                // This is necessary to avoid an obscure scenario where the
                // InCallScreen can get stuck in an inconsistent state, somehow
                // causing a *subsequent* outgoing call to fail (bug 4172599).
                endInCallScreenSession(true /* force a real finish() call */);
                return;
            }
        } else if (TelephonyCapabilities.supportsOtasp(mPhone)) {
            if (inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL ||
                    inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED) {
                if (mCallCard != null) mCallCard.setVisibility(View.GONE);
                updateScreen();
                return;
            }
        }

        // InCallScreen is now active.
        EventLog.writeEvent(EventLogTags.PHONE_UI_ENTER);

        // Update the poke lock and wake lock when we move to the foreground.
        // This will be no-op when prox sensor is effective.
        mApp.updateWakeState();

        // Restore the mute state if the last mute state change was NOT
        // done by the user.
        if (mApp.getRestoreMuteOnInCallResume()) {
            // Mute state is based on the foreground call
            PhoneUtils.restoreMuteState();
            mApp.setRestoreMuteOnInCallResume(false);
        }

        Profiler.profileViewCreate(getWindow(), InCallScreen.class.getName());

        // If there's a pending MMI code, we'll show a dialog here.
        //
        // Note: previously we had shown the dialog when MMI_INITIATE event's coming
        // from telephony layer, while right now we don't because the event comes
        // too early (before in-call screen is prepared).
        // Now we instead check pending MMI code and show the dialog here.
        //
        // This *may* cause some problem, e.g. when the user really quickly starts
        // MMI sequence and calls an actual phone number before the MMI request
        // being completed, which is rather rare.
        //
        // TODO: streamline this logic and have a UX in a better manner.
        // Right now syncWithPhoneState() above will return SUCCESS based on
        // mPhone.getPendingMmiCodes().isEmpty(), while we check it again here.
        // Also we show pre-populated in-call UI under the dialog, which looks
        // not great. (issue 5210375, 5545506)
        // After cleaning them, remove commented-out MMI handling code elsewhere.
        if (!mPhone.getPendingMmiCodes().isEmpty()) {
            if (mMmiStartedDialog == null) {
                MmiCode mmiCode = mPhone.getPendingMmiCodes().get(0);
                Message message = Message.obtain(mHandler, PhoneGlobals.MMI_CANCEL);
                mMmiStartedDialog = PhoneUtils.displayMMIInitiate(this, mmiCode,
                        message, mMmiStartedDialog);
                // mInCallScreen needs to receive MMI_COMPLETE/MMI_CANCEL event from telephony,
                // which will dismiss the entire screen.
            }
        }

        // This means the screen is shown even though there's no connection, which only happens
        // when the phone call has hung up while the screen is turned off at that moment.
        // We want to show "disconnected" state with photos with appropriate elapsed time for
        // the finished phone call.
        if (mApp.inCallUiState.showAlreadyDisconnectedState) {
            // if (DBG) {
            log("onResume(): detected \"show already disconnected state\" situation."
                    + " set up DELAYED_CLEANUP_AFTER_DISCONNECT message with "
                    + CALL_ENDED_LONG_DELAY + " msec delay.");
            //}
            mHandler.removeMessages(DELAYED_CLEANUP_AFTER_DISCONNECT);
            mHandler.sendEmptyMessageDelayed(DELAYED_CLEANUP_AFTER_DISCONNECT,
                    CALL_ENDED_LONG_DELAY);
        }

        if (VDBG) log("onResume() done.");
    }

    // onPause is guaranteed to be called when the InCallScreen goes
    // in the background.
    @Override
    protected void onPause() {
        if (DBG) log("onPause()...");
        super.onPause();

        if (mPowerManager.isScreenOn()) {
            // Set to false when the screen went background *not* by screen turned off. Probably
            // the user bailed out of the in-call screen (by pressing BACK, HOME, etc.)
            mIsForegroundActivityForProximity = false;
        }
        mIsForegroundActivity = false;

        // Force a clear of the provider info frame. Since the
        // frame is removed using a timed message, it is
        // possible we missed it if the prev call was interrupted.
        mApp.inCallUiState.providerInfoVisible = false;

        // "show-already-disconnected-state" should be effective just during the first wake-up.
        // We should never allow it to stay true after that.
        mApp.inCallUiState.showAlreadyDisconnectedState = false;

        // A safety measure to disable proximity sensor in case call failed
        // and the telephony state did not change.
        mApp.setBeginningCall(false);

        // Make sure the "Manage conference" chronometer is stopped when
        // we move away from the foreground.
        mManageConferenceUtils.stopConferenceTime();

        // as a catch-all, make sure that any dtmf tones are stopped
        // when the UI is no longer in the foreground.
        mDialer.onDialerKeyUp(null);

        // Release any "dialer session" resources, now that we're no
        // longer in the foreground.
        mDialer.stopDialerSession();

        // If the device is put to sleep as the phone call is ending,
        // we may see cases where the DELAYED_CLEANUP_AFTER_DISCONNECT
        // event gets handled AFTER the device goes to sleep and wakes
        // up again.

        // This is because it is possible for a sleep command
        // (executed with the End Call key) to come during the 2
        // seconds that the "Call Ended" screen is up.  Sleep then
        // pauses the device (including the cleanup event) and
        // resumes the event when it wakes up.

        // To fix this, we introduce a bit of code that pushes the UI
        // to the background if we pause and see a request to
        // DELAYED_CLEANUP_AFTER_DISCONNECT.

        // Note: We can try to finish directly, by:
        //  1. Removing the DELAYED_CLEANUP_AFTER_DISCONNECT messages
        //  2. Calling delayedCleanupAfterDisconnect directly

        // However, doing so can cause problems between the phone
        // app and the keyguard - the keyguard is trying to sleep at
        // the same time that the phone state is changing.  This can
        // end up causing the sleep request to be ignored.
        if (mHandler.hasMessages(DELAYED_CLEANUP_AFTER_DISCONNECT)
                && mCM.getState() != PhoneConstants.State.RINGING) {
            if (DBG) log("DELAYED_CLEANUP_AFTER_DISCONNECT detected, moving UI to background.");
            endInCallScreenSession();
        }

        EventLog.writeEvent(EventLogTags.PHONE_UI_EXIT);

        // Dismiss any dialogs we may have brought up, just to be 100%
        // sure they won't still be around when we get back here.
        dismissAllDialogs();

        updateExpandedViewState();

        // ...and the in-call notification too:
        mApp.notificationMgr.updateInCallNotification();
        // ...and *always* reset the system bar back to its normal state
        // when leaving the in-call UI.
        // (While we're the foreground activity, we disable navigation in
        // some call states; see InCallTouchUi.updateState().)
        mApp.notificationMgr.statusBarHelper.enableSystemBarNavigation(true);

        // Unregister for broadcast intents.  (These affect the visible UI
        // of the InCallScreen, so we only care about them while we're in the
        // foreground.)
        unregisterReceiver(mReceiver);

        // Make sure we revert the poke lock and wake lock when we move to
        // the background.
        mApp.updateWakeState();

        // clear the dismiss keyguard flag so we are back to the default state
        // when we next resume
        updateKeyguardPolicy(false);

        // See also PhoneApp#updatePhoneState(), which takes care of all the other release() calls.
        if (mApp.getUpdateLock().isHeld() && mApp.getPhoneState() == PhoneConstants.State.IDLE) {
            if (DBG) {
                log("Release UpdateLock on onPause() because there's no active phone call.");
            }
            mApp.getUpdateLock().release();
        }
    }

    @Override
    protected void onStop() {
        if (DBG) log("onStop()...");
        super.onStop();

        stopTimer();

        PhoneConstants.State state = mCM.getState();
        if (DBG) log("onStop: state = " + state);

        if (state == PhoneConstants.State.IDLE) {
            if (mRespondViaSmsManager.isShowingPopup()) {
                // This means that the user has been opening the "Respond via SMS" dialog even
                // after the incoming call hanging up, and the screen finally went background.
                // In that case we just close the dialog and exit the whole in-call screen.
                mRespondViaSmsManager.dismissPopup();
            }

            // when OTA Activation, OTA Success/Failure dialog or OTA SPC
            // failure dialog is running, do not destroy inCallScreen. Because call
            // is already ended and dialog will not get redrawn on slider event.
            if ((mApp.cdmaOtaProvisionData != null) && (mApp.cdmaOtaScreenState != null)
                    && ((mApp.cdmaOtaScreenState.otaScreenState !=
                            CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION)
                        && (mApp.cdmaOtaScreenState.otaScreenState !=
                            CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG)
                        && (!mApp.cdmaOtaProvisionData.inOtaSpcState))) {
                // we don't want the call screen to remain in the activity history
                // if there are not active or ringing calls.
                if (DBG) log("- onStop: calling finish() to clear activity history...");
                moveTaskToBack(true);
                if (mApp.otaUtils != null) {
                    mApp.otaUtils.cleanOtaScreen(true);
                }
            }
        }
    }

    @Override
    protected void onDestroy() {
        Log.i(LOG_TAG, "onDestroy()...  this = " + this);
        super.onDestroy();

        // Set the magic flag that tells us NOT to handle any handler
        // messages that come in asynchronously after we get destroyed.
        mIsDestroyed = true;

        mApp.setInCallScreenInstance(null);

        // Clear out the InCallScreen references in various helper objects
        // (to let them know we've been destroyed).
        if (mCallCard != null) {
            mCallCard.setInCallScreenInstance(null);
        }
        if (mInCallTouchUi != null) {
            mInCallTouchUi.setInCallScreenInstance(null);
        }
        mRespondViaSmsManager.setInCallScreenInstance(null);

        mDialer.clearInCallScreenReference();
        mDialer = null;

        unregisterForPhoneStates();
        // No need to change wake state here; that happens in onPause() when we
        // are moving out of the foreground.

        if (mBluetoothHeadset != null) {
            mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
            mBluetoothHeadset = null;
        }

        // Dismiss all dialogs, to be absolutely sure we won't leak any of
        // them while changing orientation.
        dismissAllDialogs();

        // If there's an OtaUtils instance around, clear out its
        // references to our internal widgets.
        if (mApp.otaUtils != null) {
            mApp.otaUtils.clearUiWidgets();
        }
    }

    /**
     * Dismisses the in-call screen.
     *
     * We never *really* finish() the InCallScreen, since we don't want to
     * get destroyed and then have to be re-created from scratch for the
     * next call.  Instead, we just move ourselves to the back of the
     * activity stack.
     *
     * This also means that we'll no longer be reachable via the BACK
     * button (since moveTaskToBack() puts us behind the Home app, but the
     * home app doesn't allow the BACK key to move you any farther down in
     * the history stack.)
     *
     * (Since the Phone app itself is never killed, this basically means
     * that we'll keep a single InCallScreen instance around for the
     * entire uptime of the device.  This noticeably improves the UI
     * responsiveness for incoming calls.)
     */
    @Override
    public void finish() {
        if (DBG) log("finish()...");
        moveTaskToBack(true);
    }

    /**
     * End the current in call screen session.
     *
     * This must be called when an InCallScreen session has
     * complete so that the next invocation via an onResume will
     * not be in an old state.
     */
    public void endInCallScreenSession() {
        if (DBG) log("endInCallScreenSession()... phone state = " + mCM.getState());
        endInCallScreenSession(false);
    }

    /**
     * Internal version of endInCallScreenSession().
     *
     * @param forceFinish If true, force the InCallScreen to
     *        truly finish() rather than just calling moveTaskToBack().
     *        @see finish()
     */
    private void endInCallScreenSession(boolean forceFinish) {
        if (DBG) {
            log("endInCallScreenSession(" + forceFinish + ")...  phone state = " + mCM.getState());
        }
        if (forceFinish) {
            Log.i(LOG_TAG, "endInCallScreenSession(): FORCING a call to super.finish()!");
            super.finish();  // Call super.finish() rather than our own finish() method,
                             // which actually just calls moveTaskToBack().
        } else {
            moveTaskToBack(true);
        }
        setInCallScreenMode(InCallScreenMode.UNDEFINED);
    }

    /**
     * True when this Activity is in foreground (between onResume() and onPause()).
     */
    /* package */ boolean isForegroundActivity() {
        return mIsForegroundActivity;
    }

    /**
     * Returns true when the Activity is in foreground (between onResume() and onPause()),
     * or, is in background due to user's bailing out of the screen, not by screen turning off.
     *
     * @see #isForegroundActivity()
     */
    /* package */ boolean isForegroundActivityForProximity() {
        return mIsForegroundActivityForProximity;
    }

    /* package */ void updateKeyguardPolicy(boolean dismissKeyguard) {
        if (dismissKeyguard) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        } else {
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        }
    }

    private void registerForPhoneStates() {
        if (!mRegisteredForPhoneStates) {
            mCM.registerForPreciseCallStateChanged(mHandler, PHONE_STATE_CHANGED, null);
            mCM.registerForDisconnect(mHandler, PHONE_DISCONNECT, null);
            // TODO: sort out MMI code (probably we should remove this method entirely).
            // See also MMI handling code in onResume()
            // mCM.registerForMmiInitiate(mHandler, PhoneApp.MMI_INITIATE, null);

            // register for the MMI complete message.  Upon completion,
            // PhoneUtils will bring up a system dialog instead of the
            // message display class in PhoneUtils.displayMMIComplete().
            // We'll listen for that message too, so that we can finish
            // the activity at the same time.
            mCM.registerForMmiComplete(mHandler, PhoneGlobals.MMI_COMPLETE, null);
            mCM.registerForCallWaiting(mHandler, PHONE_CDMA_CALL_WAITING, null);
            mCM.registerForPostDialCharacter(mHandler, POST_ON_DIAL_CHARS, null);
            mCM.registerForSuppServiceFailed(mHandler, SUPP_SERVICE_FAILED, null);
            mCM.registerForIncomingRing(mHandler, PHONE_INCOMING_RING, null);
            mCM.registerForNewRingingConnection(mHandler, PHONE_NEW_RINGING_CONNECTION, null);
            mRegisteredForPhoneStates = true;
        }
    }

    private void unregisterForPhoneStates() {
        mCM.unregisterForPreciseCallStateChanged(mHandler);
        mCM.unregisterForDisconnect(mHandler);
        mCM.unregisterForMmiInitiate(mHandler);
        mCM.unregisterForMmiComplete(mHandler);
        mCM.unregisterForCallWaiting(mHandler);
        mCM.unregisterForPostDialCharacter(mHandler);
        mCM.unregisterForSuppServiceFailed(mHandler);
        mCM.unregisterForIncomingRing(mHandler);
        mCM.unregisterForNewRingingConnection(mHandler);
        mRegisteredForPhoneStates = false;
    }

    /* package */ void updateAfterRadioTechnologyChange() {
        if (DBG) Log.d(LOG_TAG, "updateAfterRadioTechnologyChange()...");

        // Reset the call screen since the calls cannot be transferred
        // across radio technologies.
        resetInCallScreenMode();

        // Unregister for all events from the old obsolete phone
        unregisterForPhoneStates();

        // (Re)register for all events relevant to the new active phone
        registerForPhoneStates();

        // And finally, refresh the onscreen UI.  (Note that it's safe
        // to call requestUpdateScreen() even if the radio change ended up
        // causing us to exit the InCallScreen.)
        requestUpdateScreen();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        log("onNewIntent: intent = " + intent + ", phone state = " + mCM.getState());

        // We're being re-launched with a new Intent.  Since it's possible for a
        // single InCallScreen instance to persist indefinitely (even if we
        // finish() ourselves), this sequence can potentially happen any time
        // the InCallScreen needs to be displayed.

        // Stash away the new intent so that we can get it in the future
        // by calling getIntent().  (Otherwise getIntent() will return the
        // original Intent from when we first got created!)
        setIntent(intent);

        // Activities are always paused before receiving a new intent, so
        // we can count on our onResume() method being called next.

        // Just like in onCreate(), handle the intent.
        internalResolveIntent(intent);
    }

    private void internalResolveIntent(Intent intent) {
        if (intent == null || intent.getAction() == null) {
            return;
        }
        String action = intent.getAction();
        if (DBG) log("internalResolveIntent: action=" + action);

        // In gingerbread and earlier releases, the InCallScreen used to
        // directly handle certain intent actions that could initiate phone
        // calls, namely ACTION_CALL and ACTION_CALL_EMERGENCY, and also
        // OtaUtils.ACTION_PERFORM_CDMA_PROVISIONING.
        //
        // But it doesn't make sense to tie those actions to the InCallScreen
        // (or especially to the *activity lifecycle* of the InCallScreen).
        // Instead, the InCallScreen should only be concerned with running the
        // onscreen UI while in a call.  So we've now offloaded the call-control
        // functionality to a new module called CallController, and OTASP calls
        // are now launched from the OtaUtils startInteractiveOtasp() or
        // startNonInteractiveOtasp() methods.
        //
        // So now, the InCallScreen is only ever launched using the ACTION_MAIN
        // action, and (upon launch) performs no functionality other than
        // displaying the UI in a state that matches the current telephony
        // state.

        if (action.equals(intent.ACTION_MAIN)) {
            // This action is the normal way to bring up the in-call UI.
            //
            // Most of the interesting work of updating the onscreen UI (to
            // match the current telephony state) happens in the
            // syncWithPhoneState() => updateScreen() sequence that happens in
            // onResume().
            //
            // But we do check here for one extra that can come along with the
            // ACTION_MAIN intent:

            if (intent.hasExtra(SHOW_DIALPAD_EXTRA)) {
                // SHOW_DIALPAD_EXTRA can be used here to specify whether the DTMF
                // dialpad should be initially visible.  If the extra isn't
                // present at all, we just leave the dialpad in its previous state.

                boolean showDialpad = intent.getBooleanExtra(SHOW_DIALPAD_EXTRA, false);
                if (VDBG) log("- internalResolveIntent: SHOW_DIALPAD_EXTRA: " + showDialpad);

                // If SHOW_DIALPAD_EXTRA is specified, that overrides whatever
                // the previous state of inCallUiState.showDialpad was.
                mApp.inCallUiState.showDialpad = showDialpad;

                final boolean hasActiveCall = mCM.hasActiveFgCall();
                final boolean hasHoldingCall = mCM.hasActiveBgCall();

                // There's only one line in use, AND it's on hold, at which we're sure the user
                // wants to use the dialpad toward the exact line, so un-hold the holding line.
                if (showDialpad && !hasActiveCall && hasHoldingCall) {
                    PhoneUtils.switchHoldingAndActive(mCM.getFirstActiveBgCall());
                }
            }
            // ...and in onResume() we'll update the onscreen dialpad state to
            // match the InCallUiState.

            return;
        }

        if (action.equals(OtaUtils.ACTION_DISPLAY_ACTIVATION_SCREEN)) {
            // Bring up the in-call UI in the OTASP-specific "activate" state;
            // see OtaUtils.startInteractiveOtasp().  Note that at this point
            // the OTASP call has not been started yet; we won't actually make
            // the call until the user presses the "Activate" button.

            if (!TelephonyCapabilities.supportsOtasp(mPhone)) {
                throw new IllegalStateException(
                    "Received ACTION_DISPLAY_ACTIVATION_SCREEN intent on non-OTASP-capable device: "
                    + intent);
            }

            setInCallScreenMode(InCallScreenMode.OTA_NORMAL);
            if ((mApp.cdmaOtaProvisionData != null)
                && (!mApp.cdmaOtaProvisionData.isOtaCallIntentProcessed)) {
                mApp.cdmaOtaProvisionData.isOtaCallIntentProcessed = true;
                mApp.cdmaOtaScreenState.otaScreenState =
                        CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION;
            }
            return;
        }

        // Various intent actions that should no longer come here directly:
        if (action.equals(OtaUtils.ACTION_PERFORM_CDMA_PROVISIONING)) {
            // This intent is now handled by the InCallScreenShowActivation
            // activity, which translates it into a call to
            // OtaUtils.startInteractiveOtasp().
            throw new IllegalStateException(
                "Unexpected ACTION_PERFORM_CDMA_PROVISIONING received by InCallScreen: "
                + intent);
        } else if (action.equals(Intent.ACTION_CALL)
                   || action.equals(Intent.ACTION_CALL_EMERGENCY)) {
            // ACTION_CALL* intents go to the OutgoingCallBroadcaster, which now
            // translates them into CallController.placeCall() calls rather than
            // launching the InCallScreen directly.
            throw new IllegalStateException("Unexpected CALL action received by InCallScreen: "
                                            + intent);
        } else if (action.equals(ACTION_UNDEFINED)) {
            // This action is only used for internal bookkeeping; we should
            // never actually get launched with it.
            Log.wtf(LOG_TAG, "internalResolveIntent: got launched with ACTION_UNDEFINED");
            return;
        } else {
            Log.wtf(LOG_TAG, "internalResolveIntent: unexpected intent action: " + action);
            // But continue the best we can (basically treating this case
            // like ACTION_MAIN...)
            return;
        }
    }

    private void stopTimer() {
        if (mCallCard != null) mCallCard.stopTimer();
    }

    private void initInCallScreen() {
        if (VDBG) log("initInCallScreen()...");

        // Have the WindowManager filter out touch events that are "too fat".
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES);

        // Initialize the CallCard.
        mCallCard = (CallCard) findViewById(R.id.callCard);
        if (VDBG) log("  - mCallCard = " + mCallCard);
        mCallCard.setInCallScreenInstance(this);

        // Initialize the onscreen UI elements.
        initInCallTouchUi();

        // Helper class to keep track of enabledness/state of UI controls
        mInCallControlState = new InCallControlState(this, mCM);

        // Helper class to run the "Manage conference" UI
        mManageConferenceUtils = new ManageConferenceUtils(this, mCM);

        // The DTMF Dialpad.
        ViewStub stub = (ViewStub) findViewById(R.id.dtmf_twelve_key_dialer_stub);
        mDialer = new DTMFTwelveKeyDialer(this, stub);
        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    }

    /**
     * Returns true if the phone is "in use", meaning that at least one line
     * is active (ie. off hook or ringing or dialing).  Conversely, a return
     * value of false means there's currently no phone activity at all.
     */
    private boolean phoneIsInUse() {
        return mCM.getState() != PhoneConstants.State.IDLE;
    }

    private boolean handleDialerKeyDown(int keyCode, KeyEvent event) {
        if (VDBG) log("handleDialerKeyDown: keyCode " + keyCode + ", event " + event + "...");

        // As soon as the user starts typing valid dialable keys on the
        // keyboard (presumably to type DTMF tones) we start passing the
        // key events to the DTMFDialer's onDialerKeyDown.  We do so
        // only if the okToDialDTMFTones() conditions pass.
        if (okToDialDTMFTones()) {
            return mDialer.onDialerKeyDown(event);

            // TODO: If the dialpad isn't currently visible, maybe
            // consider automatically bringing it up right now?
            // (Just to make sure the user sees the digits widget...)
            // But this probably isn't too critical since it's awkward to
            // use the hard keyboard while in-call in the first place,
            // especially now that the in-call UI is portrait-only...
        }

        return false;
    }

    @Override
    public void onBackPressed() {
        if (DBG) log("onBackPressed()...");

        // To consume this BACK press, the code here should just do
        // something and return.  Otherwise, call super.onBackPressed() to
        // get the default implementation (which simply finishes the
        // current activity.)

        if (mCM.hasActiveRingingCall()) {
            // The Back key, just like the Home key, is always disabled
            // while an incoming call is ringing.  (The user *must* either
            // answer or reject the call before leaving the incoming-call
            // screen.)
            if (DBG) log("BACK key while ringing: ignored");

            // And consume this event; *don't* call super.onBackPressed().
            return;
        }

        // BACK is also used to exit out of any "special modes" of the
        // in-call UI:

        if (mDialer.isOpened()) {
            closeDialpadInternal(true);  // do the "closing" animation
            return;
        }

        if (mApp.inCallUiState.inCallScreenMode == InCallScreenMode.MANAGE_CONFERENCE) {
            // Hide the Manage Conference panel, return to NORMAL mode.
            setInCallScreenMode(InCallScreenMode.NORMAL);
            requestUpdateScreen();
            return;
        }

        // Nothing special to do.  Fall back to the default behavior.
        super.onBackPressed();
    }

    /**
     * Handles the green CALL key while in-call.
     * @return true if we consumed the event.
     */
    private boolean handleCallKey() {
        // The green CALL button means either "Answer", "Unhold", or
        // "Swap calls", or can be a no-op, depending on the current state
        // of the Phone.

        final boolean hasRingingCall = mCM.hasActiveRingingCall();
        final boolean hasActiveCall = mCM.hasActiveFgCall();
        final boolean hasHoldingCall = mCM.hasActiveBgCall();

        int phoneType = mPhone.getPhoneType();
        if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
            // The green CALL button means either "Answer", "Swap calls/On Hold", or
            // "Add to 3WC", depending on the current state of the Phone.

            CdmaPhoneCallState.PhoneCallState currCallState =
                mApp.cdmaPhoneCallState.getCurrentCallState();
            if (hasRingingCall) {
                //Scenario 1: Accepting the First Incoming and Call Waiting call
                if (DBG) log("answerCall: First Incoming and Call Waiting scenario");
                internalAnswerCall();  // Automatically holds the current active call,
                                       // if there is one
            } else if ((currCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE)
                    && (hasActiveCall)) {
                //Scenario 2: Merging 3Way calls
                if (DBG) log("answerCall: Merge 3-way call scenario");
                // Merge calls
                PhoneUtils.mergeCalls(mCM);
            } else if (currCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
                //Scenario 3: Switching between two Call waiting calls or drop the latest
                // connection if in a 3Way merge scenario
                if (DBG) log("answerCall: Switch btwn 2 calls scenario");
                internalSwapCalls();
            }
        } else if ((phoneType == PhoneConstants.PHONE_TYPE_GSM)
                || (phoneType == PhoneConstants.PHONE_TYPE_SIP)) {
            if (hasRingingCall) {
                // If an incoming call is ringing, the CALL button is actually
                // handled by the PhoneWindowManager.  (We do this to make
                // sure that we'll respond to the key even if the InCallScreen
                // hasn't come to the foreground yet.)
                //
                // We'd only ever get here in the extremely rare case that the
                // incoming call started ringing *after*
                // PhoneWindowManager.interceptKeyTq() but before the event
                // got here, or else if the PhoneWindowManager had some
                // problem connecting to the ITelephony service.
                Log.w(LOG_TAG, "handleCallKey: incoming call is ringing!"
                      + " (PhoneWindowManager should have handled this key.)");
                // But go ahead and handle the key as normal, since the
                // PhoneWindowManager presumably did NOT handle it:

                // There's an incoming ringing call: CALL means "Answer".
                internalAnswerCall();
            } else if (hasActiveCall && hasHoldingCall) {
                // Two lines are in use: CALL means "Swap calls".
                if (DBG) log("handleCallKey: both lines in use ==> swap calls.");
                internalSwapCalls();
            } else if (hasHoldingCall) {
                // There's only one line in use, AND it's on hold.
                // In this case CALL is a shortcut for "unhold".
                if (DBG) log("handleCallKey: call on hold ==> unhold.");
                PhoneUtils.switchHoldingAndActive(
                    mCM.getFirstActiveBgCall());  // Really means "unhold" in this state
            } else {
                // The most common case: there's only one line in use, and
                // it's an active call (i.e. it's not on hold.)
                // In this case CALL is a no-op.
                // (This used to be a shortcut for "add call", but that was a
                // bad idea because "Add call" is so infrequently-used, and
                // because the user experience is pretty confusing if you
                // inadvertently trigger it.)
                if (VDBG) log("handleCallKey: call in foregound ==> ignoring.");
                // But note we still consume this key event; see below.
            }
        } else {
            throw new IllegalStateException("Unexpected phone type: " + phoneType);
        }

        // We *always* consume the CALL key, since the system-wide default
        // action ("go to the in-call screen") is useless here.
        return true;
    }

    boolean isKeyEventAcceptableDTMF (KeyEvent event) {
        return (mDialer != null && mDialer.isKeyEventAcceptable(event));
    }

    /**
     * Overriden to track relevant focus changes.
     *
     * If a key is down and some time later the focus changes, we may
     * NOT recieve the keyup event; logically the keyup event has not
     * occured in this window.  This issue is fixed by treating a focus
     * changed event as an interruption to the keydown, making sure
     * that any code that needs to be run in onKeyUp is ALSO run here.
     */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        // the dtmf tones should no longer be played
        if (VDBG) log("onWindowFocusChanged(" + hasFocus + ")...");
        if (!hasFocus && mDialer != null) {
            if (VDBG) log("- onWindowFocusChanged: faking onDialerKeyUp()...");
            mDialer.onDialerKeyUp(null);
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        // if (DBG) log("onKeyUp(keycode " + keyCode + ")...");

        // push input to the dialer.
        if ((mDialer != null) && (mDialer.onDialerKeyUp(event))){
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_CALL) {
            // Always consume CALL to be sure the PhoneWindow won't do anything with it
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // if (DBG) log("onKeyDown(keycode " + keyCode + ")...");

        switch (keyCode) {
            case KeyEvent.KEYCODE_CALL:
                boolean handled = handleCallKey();
                if (!handled) {
                    Log.w(LOG_TAG, "InCallScreen should always handle KEYCODE_CALL in onKeyDown");
                }
                // Always consume CALL to be sure the PhoneWindow won't do anything with it
                return true;

            // Note there's no KeyEvent.KEYCODE_ENDCALL case here.
            // The standard system-wide handling of the ENDCALL key
            // (see PhoneWindowManager's handling of KEYCODE_ENDCALL)
            // already implements exactly what the UI spec wants,
            // namely (1) "hang up" if there's a current active call,
            // or (2) "don't answer" if there's a current ringing call.

            case KeyEvent.KEYCODE_CAMERA:
                // Disable the CAMERA button while in-call since it's too
                // easy to press accidentally.
                return true;

            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_MUTE:
                if (mCM.getState() == PhoneConstants.State.RINGING) {
                    // If an incoming call is ringing, the VOLUME buttons are
                    // actually handled by the PhoneWindowManager.  (We do
                    // this to make sure that we'll respond to them even if
                    // the InCallScreen hasn't come to the foreground yet.)
                    //
                    // We'd only ever get here in the extremely rare case that the
                    // incoming call started ringing *after*
                    // PhoneWindowManager.interceptKeyTq() but before the event
                    // got here, or else if the PhoneWindowManager had some
                    // problem connecting to the ITelephony service.
                    Log.w(LOG_TAG, "VOLUME key: incoming call is ringing!"
                          + " (PhoneWindowManager should have handled this key.)");
                    // But go ahead and handle the key as normal, since the
                    // PhoneWindowManager presumably did NOT handle it:
                    internalSilenceRinger();

                    // As long as an incoming call is ringing, we always
                    // consume the VOLUME keys.
                    return true;
                }
                break;

            case KeyEvent.KEYCODE_MUTE:
                onMuteClick();
                return true;

            // Various testing/debugging features, enabled ONLY when VDBG == true.
            case KeyEvent.KEYCODE_SLASH:
                if (VDBG) {
                    log("----------- InCallScreen View dump --------------");
                    // Dump starting from the top-level view of the entire activity:
                    Window w = this.getWindow();
                    View decorView = w.getDecorView();
                    decorView.debug();
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_EQUALS:
                if (VDBG) {
                    log("----------- InCallScreen call state dump --------------");
                    PhoneUtils.dumpCallState(mPhone);
                    PhoneUtils.dumpCallManager();
                    return true;
                }
                break;
            case KeyEvent.KEYCODE_GRAVE:
                if (VDBG) {
                    // Placeholder for other misc temp testing
                    log("------------ Temp testing -----------------");
                    return true;
                }
                break;
        }

        if (event.getRepeatCount() == 0 && handleDialerKeyDown(keyCode, event)) {
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    /**
     * Handle a failure notification for a supplementary service
     * (i.e. conference, switch, separate, transfer, etc.).
     */
    void onSuppServiceFailed(AsyncResult r) {
        Phone.SuppService service = (Phone.SuppService) r.result;
        if (DBG) log("onSuppServiceFailed: " + service);

        int errorMessageResId;
        switch (service) {
            case SWITCH:
                // Attempt to switch foreground and background/incoming calls failed
                // ("Failed to switch calls")
                errorMessageResId = R.string.incall_error_supp_service_switch;
                break;

            case SEPARATE:
                // Attempt to separate a call from a conference call
                // failed ("Failed to separate out call")
                errorMessageResId = R.string.incall_error_supp_service_separate;
                break;

            case TRANSFER:
                // Attempt to connect foreground and background calls to
                // each other (and hanging up user's line) failed ("Call
                // transfer failed")
                errorMessageResId = R.string.incall_error_supp_service_transfer;
                break;

            case CONFERENCE:
                // Attempt to add a call to conference call failed
                // ("Conference call failed")
                errorMessageResId = R.string.incall_error_supp_service_conference;
                break;

            case REJECT:
                // Attempt to reject an incoming call failed
                // ("Call rejection failed")
                errorMessageResId = R.string.incall_error_supp_service_reject;
                break;

            case HANGUP:
                // Attempt to release a call failed ("Failed to release call(s)")
                errorMessageResId = R.string.incall_error_supp_service_hangup;
                break;

            case UNKNOWN:
            default:
                // Attempt to use a service we don't recognize or support
                // ("Unsupported service" or "Selected service failed")
                errorMessageResId = R.string.incall_error_supp_service_unknown;
                break;
        }

        // mSuppServiceFailureDialog is a generic dialog used for any
        // supp service failure, and there's only ever have one
        // instance at a time.  So just in case a previous dialog is
        // still around, dismiss it.
        if (mSuppServiceFailureDialog != null) {
            if (DBG) log("- DISMISSING mSuppServiceFailureDialog.");
            mSuppServiceFailureDialog.dismiss();  // It's safe to dismiss() a dialog
                                                  // that's already dismissed.
            mSuppServiceFailureDialog = null;
        }

        mSuppServiceFailureDialog = new AlertDialog.Builder(this)
                .setMessage(errorMessageResId)
                .setPositiveButton(R.string.ok, null)
                .create();
        mSuppServiceFailureDialog.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
        mSuppServiceFailureDialog.show();
    }

    /**
     * Something has changed in the phone's state.  Update the UI.
     */
    private void onPhoneStateChanged(AsyncResult r) {
        PhoneConstants.State state = mCM.getState();
        if (DBG) log("onPhoneStateChanged: current state = " + state);

        // There's nothing to do here if we're not the foreground activity.
        // (When we *do* eventually come to the foreground, we'll do a
        // full update then.)
        if (!mIsForegroundActivity) {
            if (DBG) log("onPhoneStateChanged: Activity not in foreground! Bailing out...");
            return;
        }

        updateExpandedViewState();

        // Update the onscreen UI.
        // We use requestUpdateScreen() here (which posts a handler message)
        // instead of calling updateScreen() directly, which allows us to avoid
        // unnecessary work if multiple onPhoneStateChanged() events come in all
        // at the same time.

        requestUpdateScreen();

        // Make sure we update the poke lock and wake lock when certain
        // phone state changes occur.
        mApp.updateWakeState();
    }

    /**
     * Updates the UI after a phone connection is disconnected, as follows:
     *
     * - If this was a missed or rejected incoming call, and no other
     *   calls are active, dismiss the in-call UI immediately.  (The
     *   CallNotifier will still create a "missed call" notification if
     *   necessary.)
     *
     * - With any other disconnect cause, if the phone is now totally
     *   idle, display the "Call ended" state for a couple of seconds.
     *
     * - Or, if the phone is still in use, stay on the in-call screen
     *   (and update the UI to reflect the current state of the Phone.)
     *
     * @param r r.result contains the connection that just ended
     */
    private void onDisconnect(AsyncResult r) {
        Connection c = (Connection) r.result;
        Connection.DisconnectCause cause = c.getDisconnectCause();
        if (DBG) log("onDisconnect: connection '" + c + "', cause = " + cause
                + ", showing screen: " + mApp.isShowingCallScreen());

        boolean currentlyIdle = !phoneIsInUse();
        int autoretrySetting = AUTO_RETRY_OFF;
        boolean phoneIsCdma = (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA);
        if (phoneIsCdma) {
            // Get the Auto-retry setting only if Phone State is IDLE,
            // else let it stay as AUTO_RETRY_OFF
            if (currentlyIdle) {
                autoretrySetting = android.provider.Settings.Global.getInt(mPhone.getContext().
                        getContentResolver(), android.provider.Settings.Global.CALL_AUTO_RETRY, 0);
            }
        }

        // for OTA Call, only if in OTA NORMAL mode, handle OTA END scenario
        if ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL)
                && ((mApp.cdmaOtaProvisionData != null)
                && (!mApp.cdmaOtaProvisionData.inOtaSpcState))) {
            setInCallScreenMode(InCallScreenMode.OTA_ENDED);
            updateScreen();
            return;
        } else if ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED)
                   || ((mApp.cdmaOtaProvisionData != null)
                       && mApp.cdmaOtaProvisionData.inOtaSpcState)) {
           if (DBG) log("onDisconnect: OTA Call end already handled");
           return;
        }

        // Any time a call disconnects, clear out the "history" of DTMF
        // digits you typed (to make sure it doesn't persist from one call
        // to the next.)
        mDialer.clearDigits();

        // Under certain call disconnected states, we want to alert the user
        // with a dialog instead of going through the normal disconnect
        // routine.
        if (cause == Connection.DisconnectCause.CALL_BARRED) {
            showGenericErrorDialog(R.string.callFailed_cb_enabled, false);
            return;
        } else if (cause == Connection.DisconnectCause.FDN_BLOCKED) {
            showGenericErrorDialog(R.string.callFailed_fdn_only, false);
            return;
        } else if (cause == Connection.DisconnectCause.CS_RESTRICTED) {
            showGenericErrorDialog(R.string.callFailed_dsac_restricted, false);
            return;
        } else if (cause == Connection.DisconnectCause.CS_RESTRICTED_EMERGENCY) {
            showGenericErrorDialog(R.string.callFailed_dsac_restricted_emergency, false);
            return;
        } else if (cause == Connection.DisconnectCause.CS_RESTRICTED_NORMAL) {
            showGenericErrorDialog(R.string.callFailed_dsac_restricted_normal, false);
            return;
        }

        if (phoneIsCdma) {
            Call.State callState = mApp.notifier.getPreviousCdmaCallState();
            if ((callState == Call.State.ACTIVE)
                    && (cause != Connection.DisconnectCause.INCOMING_MISSED)
                    && (cause != Connection.DisconnectCause.NORMAL)
                    && (cause != Connection.DisconnectCause.LOCAL)
                    && (cause != Connection.DisconnectCause.INCOMING_REJECTED)) {
                showCallLostDialog();
            } else if ((callState == Call.State.DIALING || callState == Call.State.ALERTING)
                        && (cause != Connection.DisconnectCause.INCOMING_MISSED)
                        && (cause != Connection.DisconnectCause.NORMAL)
                        && (cause != Connection.DisconnectCause.LOCAL)
                        && (cause != Connection.DisconnectCause.INCOMING_REJECTED)) {

                if (mApp.inCallUiState.needToShowCallLostDialog) {
                    // Show the dialog now since the call that just failed was a retry.
                    showCallLostDialog();
                    mApp.inCallUiState.needToShowCallLostDialog = false;
                } else {
                    if (autoretrySetting == AUTO_RETRY_OFF) {
                        // Show the dialog for failed call if Auto Retry is OFF in Settings.
                        showCallLostDialog();
                        mApp.inCallUiState.needToShowCallLostDialog = false;
                    } else {
                        // Set the needToShowCallLostDialog flag now, so we'll know to show
                        // the dialog if *this* call fails.
                        mApp.inCallUiState.needToShowCallLostDialog = true;
                    }
                }
            }
        }

        // Explicitly clean up up any DISCONNECTED connections
        // in a conference call.
        // [Background: Even after a connection gets disconnected, its
        // Connection object still stays around for a few seconds, in the
        // DISCONNECTED state.  With regular calls, this state drives the
        // "call ended" UI.  But when a single person disconnects from a
        // conference call there's no "call ended" state at all; in that
        // case we blow away any DISCONNECTED connections right now to make sure
        // the UI updates instantly to reflect the current state.]
        final Call call = c.getCall();
        if (call != null) {
            // We only care about situation of a single caller
            // disconnecting from a conference call.  In that case, the
            // call will have more than one Connection (including the one
            // that just disconnected, which will be in the DISCONNECTED
            // state) *and* at least one ACTIVE connection.  (If the Call
            // has *no* ACTIVE connections, that means that the entire
            // conference call just ended, so we *do* want to show the
            // "Call ended" state.)
            List<Connection> connections = call.getConnections();
            if (connections != null && connections.size() > 1) {
                for (Connection conn : connections) {
                    if (conn.getState() == Call.State.ACTIVE) {
                        // This call still has at least one ACTIVE connection!
                        // So blow away any DISCONNECTED connections
                        // (including, presumably, the one that just
                        // disconnected from this conference call.)

                        // We also force the wake state to refresh, just in
                        // case the disconnected connections are removed
                        // before the phone state change.
                        if (VDBG) log("- Still-active conf call; clearing DISCONNECTED...");
                        mApp.updateWakeState();
                        mCM.clearDisconnected();  // This happens synchronously.
                        break;
                    }
                }
            }
        }

        // Note: see CallNotifier.onDisconnect() for some other behavior
        // that might be triggered by a disconnect event, like playing the
        // busy/congestion tone.

        // Stash away some info about the call that just disconnected.
        // (This might affect what happens after we exit the InCallScreen; see
        // delayedCleanupAfterDisconnect().)
        // TODO: rather than stashing this away now and then reading it in
        // delayedCleanupAfterDisconnect(), it would be cleaner to just pass
        // this as an argument to delayedCleanupAfterDisconnect() (if we call
        // it directly) or else pass it as a Message argument when we post the
        // DELAYED_CLEANUP_AFTER_DISCONNECT message.
        mLastDisconnectCause = cause;

        // We bail out immediately (and *don't* display the "call ended"
        // state at all) if this was an incoming call.
        boolean bailOutImmediately =
                ((cause == Connection.DisconnectCause.INCOMING_MISSED)
                 || (cause == Connection.DisconnectCause.INCOMING_REJECTED))
                && currentlyIdle;

        boolean showingQuickResponseDialog =
                mRespondViaSmsManager != null && mRespondViaSmsManager.isShowingPopup();

        // Note: we also do some special handling for the case when a call
        // disconnects with cause==OUT_OF_SERVICE while making an
        // emergency call from airplane mode.  That's handled by
        // EmergencyCallHelper.onDisconnect().

        if (bailOutImmediately && showingQuickResponseDialog) {
            if (DBG) log("- onDisconnect: Respond-via-SMS dialog is still being displayed...");

            // Do *not* exit the in-call UI yet!
            // If the call was an incoming call that was missed *and* the user is using
            // quick response screen, we keep showing the screen for a moment, assuming the
            // user wants to reply the call anyway.
            //
            // For this case, we will exit the screen when:
            // - the message is sent (RespondViaSmsManager)
            // - the message is canceled (RespondViaSmsManager), or
            // - when the whole in-call UI becomes background (onPause())
        } else if (bailOutImmediately) {
            if (DBG) log("- onDisconnect: bailOutImmediately...");

            // Exit the in-call UI!
            // (This is basically the same "delayed cleanup" we do below,
            // just with zero delay.  Since the Phone is currently idle,
            // this call is guaranteed to immediately finish this activity.)
            delayedCleanupAfterDisconnect();
        } else {
            if (DBG) log("- onDisconnect: delayed bailout...");
            // Stay on the in-call screen for now.  (Either the phone is
            // still in use, or the phone is idle but we want to display
            // the "call ended" state for a couple of seconds.)

            // Switch to the special "Call ended" state when the phone is idle
            // but there's still a call in the DISCONNECTED state:
            if (currentlyIdle
                && (mCM.hasDisconnectedFgCall() || mCM.hasDisconnectedBgCall())) {
                if (DBG) log("- onDisconnect: switching to 'Call ended' state...");
                setInCallScreenMode(InCallScreenMode.CALL_ENDED);
            }

            // Force a UI update in case we need to display anything
            // special based on this connection's DisconnectCause
            // (see CallCard.getCallFailedString()).
            updateScreen();

            // Some other misc cleanup that we do if the call that just
            // disconnected was the foreground call.
            final boolean hasActiveCall = mCM.hasActiveFgCall();
            if (!hasActiveCall) {
                if (DBG) log("- onDisconnect: cleaning up after FG call disconnect...");

                // Dismiss any dialogs which are only meaningful for an
                // active call *and* which become moot if the call ends.
                if (mWaitPromptDialog != null) {
                    if (VDBG) log("- DISMISSING mWaitPromptDialog.");
                    mWaitPromptDialog.dismiss();  // safe even if already dismissed
                    mWaitPromptDialog = null;
                }
                if (mWildPromptDialog != null) {
                    if (VDBG) log("- DISMISSING mWildPromptDialog.");
                    mWildPromptDialog.dismiss();  // safe even if already dismissed
                    mWildPromptDialog = null;
                }
                if (mPausePromptDialog != null) {
                    if (DBG) log("- DISMISSING mPausePromptDialog.");
                    mPausePromptDialog.dismiss();  // safe even if already dismissed
                    mPausePromptDialog = null;
                }
            }

            // Updating the screen wake state is done in onPhoneStateChanged().


            // CDMA: We only clean up if the Phone state is IDLE as we might receive an
            // onDisconnect for a Call Collision case (rare but possible).
            // For Call collision cases i.e. when the user makes an out going call
            // and at the same time receives an Incoming Call, the Incoming Call is given
            // higher preference. At this time framework sends a disconnect for the Out going
            // call connection hence we should *not* bring down the InCallScreen as the Phone
            // State would be RINGING
            if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
                if (!currentlyIdle) {
                    // Clean up any connections in the DISCONNECTED state.
                    // This is necessary cause in CallCollision the foreground call might have
                    // connections in DISCONNECTED state which needs to be cleared.
                    mCM.clearDisconnected();

                    // The phone is still in use.  Stay here in this activity.
                    // But we don't need to keep the screen on.
                    if (DBG) log("onDisconnect: Call Collision case - staying on InCallScreen.");
                    if (DBG) PhoneUtils.dumpCallState(mPhone);
                    return;
                }
            }

            // This is onDisconnect() request from the last phone call; no available call anymore.
            //
            // When the in-call UI is in background *because* the screen is turned off (unlike the
            // other case where the other activity is being shown), we wake up the screen and
            // show "DISCONNECTED" state once, with appropriate elapsed time. After showing that
            // we *must* bail out of the screen again, showing screen lock if needed.
            //
            // See also comments for isForegroundActivityForProximity()
            //
            // TODO: Consider moving this to CallNotifier. This code assumes the InCallScreen
            // never gets destroyed. For this exact case, it works (since InCallScreen won't be
            // destroyed), while technically this isn't right; Activity may be destroyed when
            // in background.
            if (currentlyIdle && !isForegroundActivity() && isForegroundActivityForProximity()) {
                log("Force waking up the screen to let users see \"disconnected\" state");
                if (call != null) {
                    mCallCard.updateElapsedTimeWidget(call);
                }
                // This variable will be kept true until the next InCallScreen#onPause(), which
                // forcibly turns it off regardless of the situation (for avoiding unnecessary
                // confusion around this special case).
                mApp.inCallUiState.showAlreadyDisconnectedState = true;

                // Finally request wake-up..
                mApp.wakeUpScreen();

                // InCallScreen#onResume() will set DELAYED_CLEANUP_AFTER_DISCONNECT message,
                // so skip the following section.
                return;
            }

            // Finally, arrange for delayedCleanupAfterDisconnect() to get
            // called after a short interval (during which we display the
            // "call ended" state.)  At that point, if the
            // Phone is idle, we'll finish out of this activity.
            final int callEndedDisplayDelay;
            switch (cause) {
                // When the local user hanged up the ongoing call, it is ok to dismiss the screen
                // soon. In other cases, we show the "hung up" screen longer.
                //
                // - For expected reasons we will use CALL_ENDED_LONG_DELAY.
                // -- when the peer hanged up the call
                // -- when the local user rejects the incoming call during the other ongoing call
                // (TODO: there may be other cases which should be in this category)
                //
                // - For other unexpected reasons, we will use CALL_ENDED_EXTRA_LONG_DELAY,
                //   assuming the local user wants to confirm the disconnect reason.
                case LOCAL:
                    callEndedDisplayDelay = CALL_ENDED_SHORT_DELAY;
                    break;
                case NORMAL:
                case INCOMING_REJECTED:
                    callEndedDisplayDelay = CALL_ENDED_LONG_DELAY;
                    break;
                default:
                    callEndedDisplayDelay = CALL_ENDED_EXTRA_LONG_DELAY;
                    break;
            }
            mHandler.removeMessages(DELAYED_CLEANUP_AFTER_DISCONNECT);
            mHandler.sendEmptyMessageDelayed(DELAYED_CLEANUP_AFTER_DISCONNECT,
                    callEndedDisplayDelay);
        }

        // Remove 3way timer (only meaningful for CDMA)
        // TODO: this call needs to happen in the CallController, not here.
        // (It should probably be triggered by the CallNotifier's onDisconnect method.)
        // mHandler.removeMessages(THREEWAY_CALLERINFO_DISPLAY_DONE);
    }

    /**
     * Brings up the "MMI Started" dialog.
     */
    /* TODO: sort out MMI code (probably we should remove this method entirely). See also
       MMI handling code in onResume()
    private void onMMIInitiate(AsyncResult r) {
        if (VDBG) log("onMMIInitiate()...  AsyncResult r = " + r);

        // Watch out: don't do this if we're not the foreground activity,
        // mainly since in the Dialog.show() might fail if we don't have a
        // valid window token any more...
        // (Note that this exact sequence can happen if you try to start
        // an MMI code while the radio is off or out of service.)
        if (!mIsForegroundActivity) {
            if (VDBG) log("Activity not in foreground! Bailing out...");
            return;
        }

        // Also, if any other dialog is up right now (presumably the
        // generic error dialog displaying the "Starting MMI..."  message)
        // take it down before bringing up the real "MMI Started" dialog
        // in its place.
        dismissAllDialogs();

        MmiCode mmiCode = (MmiCode) r.result;
        if (VDBG) log("  - MmiCode: " + mmiCode);

        Message message = Message.obtain(mHandler, PhoneApp.MMI_CANCEL);
        mMmiStartedDialog = PhoneUtils.displayMMIInitiate(this, mmiCode,
                                                          message, mMmiStartedDialog);
    }*/

    /**
     * Handles an MMI_CANCEL event, which is triggered by the button
     * (labeled either "OK" or "Cancel") on the "MMI Started" dialog.
     * @see PhoneUtils#cancelMmiCode(Phone)
     */
    private void onMMICancel() {
        if (VDBG) log("onMMICancel()...");

        // First of all, cancel the outstanding MMI code (if possible.)
        PhoneUtils.cancelMmiCode(mPhone);

        // Regardless of whether the current MMI code was cancelable, the
        // PhoneApp will get an MMI_COMPLETE event very soon, which will
        // take us to the MMI Complete dialog (see
        // PhoneUtils.displayMMIComplete().)
        //
        // But until that event comes in, we *don't* want to stay here on
        // the in-call screen, since we'll be visible in a
        // partially-constructed state as soon as the "MMI Started" dialog
        // gets dismissed.  So let's forcibly bail out right now.
        if (DBG) log("onMMICancel: finishing InCallScreen...");
        dismissAllDialogs();
        endInCallScreenSession();
    }

    /**
     * Handles an MMI_COMPLETE event, which is triggered by telephony,
     * implying MMI
     */
    private void onMMIComplete(MmiCode mmiCode) {
        // Check the code to see if the request is ready to
        // finish, this includes any MMI state that is not
        // PENDING.

        // if phone is a CDMA phone display feature code completed message
        int phoneType = mPhone.getPhoneType();
        if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
            PhoneUtils.displayMMIComplete(mPhone, mApp, mmiCode, null, null);
        } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
            if (mmiCode.getState() != MmiCode.State.PENDING) {
                if (DBG) log("Got MMI_COMPLETE, finishing InCallScreen...");
                dismissAllDialogs();
                endInCallScreenSession();
            }
        }
    }

    /**
     * Handles the POST_ON_DIAL_CHARS message from the Phone
     * (see our call to mPhone.setOnPostDialCharacter() above.)
     *
     * TODO: NEED TO TEST THIS SEQUENCE now that we no longer handle
     * "dialable" key events here in the InCallScreen: we do directly to the
     * Dialer UI instead.  Similarly, we may now need to go directly to the
     * Dialer to handle POST_ON_DIAL_CHARS too.
     */
    private void handlePostOnDialChars(AsyncResult r, char ch) {
        Connection c = (Connection) r.result;

        if (c != null) {
            Connection.PostDialState state =
                    (Connection.PostDialState) r.userObj;

            if (VDBG) log("handlePostOnDialChar: state = " +
                    state + ", ch = " + ch);

            switch (state) {
                case STARTED:
                    mDialer.stopLocalToneIfNeeded();
                    if (mPauseInProgress) {
                        /**
                         * Note that on some devices, this will never happen,
                         * because we will not ever enter the PAUSE state.
                         */
                        showPausePromptDialog(c, mPostDialStrAfterPause);
                    }
                    mPauseInProgress = false;
                    mDialer.startLocalToneIfNeeded(ch);

                    // TODO: is this needed, now that you can't actually
                    // type DTMF chars or dial directly from here?
                    // If so, we'd need to yank you out of the in-call screen
                    // here too (and take you to the 12-key dialer in "in-call" mode.)
                    // displayPostDialedChar(ch);
                    break;

                case WAIT:
                    // wait shows a prompt.
                    if (DBG) log("handlePostOnDialChars: show WAIT prompt...");
                    mDialer.stopLocalToneIfNeeded();
                    String postDialStr = c.getRemainingPostDialString();
                    showWaitPromptDialog(c, postDialStr);
                    break;

                case WILD:
                    if (DBG) log("handlePostOnDialChars: show WILD prompt");
                    mDialer.stopLocalToneIfNeeded();
                    showWildPromptDialog(c);
                    break;

                case COMPLETE:
                    mDialer.stopLocalToneIfNeeded();
                    break;

                case PAUSE:
                    // pauses for a brief period of time then continue dialing.
                    mDialer.stopLocalToneIfNeeded();
                    mPostDialStrAfterPause = c.getRemainingPostDialString();
                    mPauseInProgress = true;
                    break;

                default:
                    break;
            }
        }
    }

    /**
     * Pop up an alert dialog with OK and Cancel buttons to allow user to
     * Accept or Reject the WAIT inserted as part of the Dial string.
     */
    private void showWaitPromptDialog(final Connection c, String postDialStr) {
        if (DBG) log("showWaitPromptDialogChoice: '" + postDialStr + "'...");

        Resources r = getResources();
        StringBuilder buf = new StringBuilder();
        buf.append(r.getText(R.string.wait_prompt_str));
        buf.append(postDialStr);

        // if (DBG) log("- mWaitPromptDialog = " + mWaitPromptDialog);
        if (mWaitPromptDialog != null) {
            if (DBG) log("- DISMISSING mWaitPromptDialog.");
            mWaitPromptDialog.dismiss();  // safe even if already dismissed
            mWaitPromptDialog = null;
        }

        mWaitPromptDialog = new AlertDialog.Builder(this)
                .setMessage(buf.toString())
                .setPositiveButton(R.string.pause_prompt_yes,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int whichButton) {
                                if (DBG) log("handle WAIT_PROMPT_CONFIRMED, proceed...");
                                c.proceedAfterWaitChar();
                            }
                        })
                .setNegativeButton(R.string.pause_prompt_no,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int whichButton) {
                                if (DBG) log("handle POST_DIAL_CANCELED!");
                                c.cancelPostDial();
                            }
                        })
                .create();
        mWaitPromptDialog.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

        mWaitPromptDialog.show();
    }

    /**
     * Pop up an alert dialog which waits for 2 seconds for each P (Pause) Character entered
     * as part of the Dial String.
     */
    private void showPausePromptDialog(final Connection c, String postDialStrAfterPause) {
        Resources r = getResources();
        StringBuilder buf = new StringBuilder();
        buf.append(r.getText(R.string.pause_prompt_str));
        buf.append(postDialStrAfterPause);

        if (mPausePromptDialog != null) {
            if (DBG) log("- DISMISSING mPausePromptDialog.");
            mPausePromptDialog.dismiss();  // safe even if already dismissed
            mPausePromptDialog = null;
        }

        mPausePromptDialog = new AlertDialog.Builder(this)
                .setMessage(buf.toString())
                .create();
        mPausePromptDialog.show();
        // 2 second timer
        Message msg = Message.obtain(mHandler, EVENT_PAUSE_DIALOG_COMPLETE);
        mHandler.sendMessageDelayed(msg, PAUSE_PROMPT_DIALOG_TIMEOUT);
    }

    private View createWildPromptView() {
        LinearLayout result = new LinearLayout(this);
        result.setOrientation(LinearLayout.VERTICAL);
        result.setPadding(5, 5, 5, 5);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT);

        TextView promptMsg = new TextView(this);
        promptMsg.setTextSize(14);
        promptMsg.setTypeface(Typeface.DEFAULT_BOLD);
        promptMsg.setText(getResources().getText(R.string.wild_prompt_str));

        result.addView(promptMsg, lp);

        mWildPromptText = new EditText(this);
        mWildPromptText.setKeyListener(DialerKeyListener.getInstance());
        mWildPromptText.setMovementMethod(null);
        mWildPromptText.setTextSize(14);
        mWildPromptText.setMaxLines(1);
        mWildPromptText.setHorizontallyScrolling(true);
        mWildPromptText.setBackgroundResource(android.R.drawable.editbox_background);

        LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT);
        lp2.setMargins(0, 3, 0, 0);

        result.addView(mWildPromptText, lp2);

        return result;
    }

    private void showWildPromptDialog(final Connection c) {
        View v = createWildPromptView();

        if (mWildPromptDialog != null) {
            if (VDBG) log("- DISMISSING mWildPromptDialog.");
            mWildPromptDialog.dismiss();  // safe even if already dismissed
            mWildPromptDialog = null;
        }

        mWildPromptDialog = new AlertDialog.Builder(this)
                .setView(v)
                .setPositiveButton(
                        R.string.send_button,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int whichButton) {
                                if (VDBG) log("handle WILD_PROMPT_CHAR_ENTERED, proceed...");
                                String replacement = null;
                                if (mWildPromptText != null) {
                                    replacement = mWildPromptText.getText().toString();
                                    mWildPromptText = null;
                                }
                                c.proceedAfterWildChar(replacement);
                                mApp.pokeUserActivity();
                            }
                        })
                .setOnCancelListener(
                        new DialogInterface.OnCancelListener() {
                            @Override
                            public void onCancel(DialogInterface dialog) {
                                if (VDBG) log("handle POST_DIAL_CANCELED!");
                                c.cancelPostDial();
                                mApp.pokeUserActivity();
                            }
                        })
                .create();
        mWildPromptDialog.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
        mWildPromptDialog.show();

        mWildPromptText.requestFocus();
    }

    /**
     * Updates the state of the in-call UI based on the current state of
     * the Phone.  This call has no effect if we're not currently the
     * foreground activity.
     *
     * This method is only allowed to be called from the UI thread (since it
     * manipulates our View hierarchy).  If you need to update the screen from
     * some other thread, or if you just want to "post a request" for the screen
     * to be updated (rather than doing it synchronously), call
     * requestUpdateScreen() instead.
     *
     * Right now this method will update UI visibility immediately, with no animation.
     * TODO: have animate flag here and use it anywhere possible.
     */
    private void updateScreen() {
        if (DBG) log("updateScreen()...");
        final InCallScreenMode inCallScreenMode = mApp.inCallUiState.inCallScreenMode;
        if (VDBG) {
            PhoneConstants.State state = mCM.getState();
            log("  - phone state = " + state);
            log("  - inCallScreenMode = " + inCallScreenMode);
        }

        // Don't update anything if we're not in the foreground (there's
        // no point updating our UI widgets since we're not visible!)
        // Also note this check also ensures we won't update while we're
        // in the middle of pausing, which could cause a visible glitch in
        // the "activity ending" transition.
        if (!mIsForegroundActivity) {
            if (DBG) log("- updateScreen: not the foreground Activity! Bailing out...");
            return;
        }

        if (inCallScreenMode == InCallScreenMode.OTA_NORMAL) {
            if (DBG) log("- updateScreen: OTA call state NORMAL (NOT updating in-call UI)...");
            mCallCard.setVisibility(View.GONE);
            if (mApp.otaUtils != null) {
                mApp.otaUtils.otaShowProperScreen();
            } else {
                Log.w(LOG_TAG, "OtaUtils object is null, not showing any screen for that.");
            }
            return;  // Return without updating in-call UI.
        } else if (inCallScreenMode == InCallScreenMode.OTA_ENDED) {
            if (DBG) log("- updateScreen: OTA call ended state (NOT updating in-call UI)...");
            mCallCard.setVisibility(View.GONE);
            // Wake up the screen when we get notification, good or bad.
            mApp.wakeUpScreen();
            if (mApp.cdmaOtaScreenState.otaScreenState
                    == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION) {
                if (DBG) log("- updateScreen: OTA_STATUS_ACTIVATION");
                if (mApp.otaUtils != null) {
                    if (DBG) log("- updateScreen: mApp.otaUtils is not null, "
                                  + "call otaShowActivationScreen");
                    mApp.otaUtils.otaShowActivateScreen();
                }
            } else {
                if (DBG) log("- updateScreen: OTA Call end state for Dialogs");
                if (mApp.otaUtils != null) {
                    if (DBG) log("- updateScreen: Show OTA Success Failure dialog");
                    mApp.otaUtils.otaShowSuccessFailure();
                }
            }
            return;  // Return without updating in-call UI.
        } else if (inCallScreenMode == InCallScreenMode.MANAGE_CONFERENCE) {
            if (DBG) log("- updateScreen: manage conference mode (NOT updating in-call UI)...");
            mCallCard.setVisibility(View.GONE);
            updateManageConferencePanelIfNecessary();
            return;  // Return without updating in-call UI.
        } else if (inCallScreenMode == InCallScreenMode.CALL_ENDED) {
            if (DBG) log("- updateScreen: call ended state...");
            // Continue with the rest of updateScreen() as usual, since we do
            // need to update the background (to the special "call ended" color)
            // and the CallCard (to show the "Call ended" label.)
        }

        if (DBG) log("- updateScreen: updating the in-call UI...");
        // Note we update the InCallTouchUi widget before the CallCard,
        // since the CallCard adjusts its size based on how much vertical
        // space the InCallTouchUi widget needs.
        updateInCallTouchUi();
        mCallCard.updateState(mCM);

        // If an incoming call is ringing, make sure the dialpad is
        // closed.  (We do this to make sure we're not covering up the
        // "incoming call" UI.)
        if (mCM.getState() == PhoneConstants.State.RINGING) {
            if (mDialer.isOpened()) {
              Log.i(LOG_TAG, "During RINGING state we force hiding dialpad.");
              closeDialpadInternal(false);  // don't do the "closing" animation
            }

            // At this point, we are guranteed that the dialer is closed.
            // This means that it is safe to clear out the "history" of DTMF digits
            // you may have typed into the previous call (so you don't see the
            // previous call's digits if you answer this call and then bring up the
            // dialpad.)
            //
            // TODO: it would be more precise to do this when you *answer* the
            // incoming call, rather than as soon as it starts ringing, but
            // the InCallScreen doesn't keep enough state right now to notice
            // that specific transition in onPhoneStateChanged().
            // TODO: This clears out the dialpad context as well so when a second
            // call comes in while a voicemail call is happening, the voicemail
            // dialpad will no longer have the "Voice Mail" context. It's a small
            // case so not terribly bad, but we need to maintain a better
            // call-to-callstate mapping before we can fix this.
            mDialer.clearDigits();
        }


        // Now that we're sure DTMF dialpad is in an appropriate state, reflect
        // the dialpad state into CallCard
        updateCallCardVisibilityPerDialerState(false);

        updateProgressIndication();

        // Forcibly take down all dialog if an incoming call is ringing.
        if (mCM.hasActiveRingingCall()) {
            dismissAllDialogs();
        } else {
            // Wait prompt dialog is not currently up.  But it *should* be
            // up if the FG call has a connection in the WAIT state and
            // the phone isn't ringing.
            String postDialStr = null;
            List<Connection> fgConnections = mCM.getFgCallConnections();
            int phoneType = mCM.getFgPhone().getPhoneType();
            if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                Connection fgLatestConnection = mCM.getFgCallLatestConnection();
                if (mApp.cdmaPhoneCallState.getCurrentCallState() ==
                        CdmaPhoneCallState.PhoneCallState.CONF_CALL) {
                    for (Connection cn : fgConnections) {
                        if ((cn != null) && (cn.getPostDialState() ==
                                Connection.PostDialState.WAIT)) {
                            cn.cancelPostDial();
                        }
                    }
                } else if ((fgLatestConnection != null)
                     && (fgLatestConnection.getPostDialState() == Connection.PostDialState.WAIT)) {
                    if(DBG) log("show the Wait dialog for CDMA");
                    postDialStr = fgLatestConnection.getRemainingPostDialString();
                    showWaitPromptDialog(fgLatestConnection, postDialStr);
                }
            } else if ((phoneType == PhoneConstants.PHONE_TYPE_GSM)
                    || (phoneType == PhoneConstants.PHONE_TYPE_SIP)) {
                for (Connection cn : fgConnections) {
                    if ((cn != null) && (cn.getPostDialState() == Connection.PostDialState.WAIT)) {
                        postDialStr = cn.getRemainingPostDialString();
                        showWaitPromptDialog(cn, postDialStr);
                    }
                }
            } else {
                throw new IllegalStateException("Unexpected phone type: " + phoneType);
            }
        }
    }

    /**
     * (Re)synchronizes the onscreen UI with the current state of the
     * telephony framework.
     *
     * @return SyncWithPhoneStateStatus.SUCCESS if we successfully updated the UI, or
     *    SyncWithPhoneStateStatus.PHONE_NOT_IN_USE if there was no phone state to sync
     *    with (ie. the phone was completely idle).  In the latter case, we
     *    shouldn't even be in the in-call UI in the first place, and it's
     *    the caller's responsibility to bail out of this activity by
     *    calling endInCallScreenSession if appropriate.
     *
     * This method directly calls updateScreen() in the normal "phone is
     * in use" case, so there's no need for the caller to do so.
     */
    private SyncWithPhoneStateStatus syncWithPhoneState() {
        boolean updateSuccessful = false;
        if (DBG) log("syncWithPhoneState()...");
        if (DBG) PhoneUtils.dumpCallState(mPhone);
        if (VDBG) dumpBluetoothState();

        // Make sure the Phone is "in use".  (If not, we shouldn't be on
        // this screen in the first place.)

        // An active or just-ended OTA call counts as "in use".
        if (TelephonyCapabilities.supportsOtasp(mCM.getFgPhone())
                && ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL)
                    || (mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED))) {
            // Even when OTA Call ends, need to show OTA End UI,
            // so return Success to allow UI update.
            return SyncWithPhoneStateStatus.SUCCESS;
        }

        // If an MMI code is running that also counts as "in use".
        //
        // TODO: We currently only call getPendingMmiCodes() for GSM
        //   phones.  (The code's been that way all along.)  But CDMAPhone
        //   does in fact implement getPendingMmiCodes(), so should we
        //   check that here regardless of the phone type?
        boolean hasPendingMmiCodes =
                (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM)
                && !mPhone.getPendingMmiCodes().isEmpty();

        // Finally, it's also OK to stay here on the InCallScreen if we
        // need to display a progress indicator while something's
        // happening in the background.
        boolean showProgressIndication = mApp.inCallUiState.isProgressIndicationActive();

        boolean showScreenEvenAfterDisconnect = mApp.inCallUiState.showAlreadyDisconnectedState;

        if (mCM.hasActiveFgCall() || mCM.hasActiveBgCall() || mCM.hasActiveRingingCall()
                || hasPendingMmiCodes || showProgressIndication || showScreenEvenAfterDisconnect) {
            if (VDBG) log("syncWithPhoneState: it's ok to be here; update the screen...");
            updateScreen();
            return SyncWithPhoneStateStatus.SUCCESS;
        }

        Log.i(LOG_TAG, "syncWithPhoneState: phone is idle (shouldn't be here)");
        return SyncWithPhoneStateStatus.PHONE_NOT_IN_USE;
    }



    private void handleMissingVoiceMailNumber() {
        if (DBG) log("handleMissingVoiceMailNumber");

        final Message msg = Message.obtain(mHandler);
        msg.what = DONT_ADD_VOICEMAIL_NUMBER;

        final Message msg2 = Message.obtain(mHandler);
        msg2.what = ADD_VOICEMAIL_NUMBER;

        mMissingVoicemailDialog = new AlertDialog.Builder(this)
                .setTitle(R.string.no_vm_number)
                .setMessage(R.string.no_vm_number_msg)
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            if (VDBG) log("Missing voicemail AlertDialog: POSITIVE click...");
                            msg.sendToTarget();  // see dontAddVoiceMailNumber()
                            mApp.pokeUserActivity();
                        }})
                .setNegativeButton(R.string.add_vm_number_str,
                                   new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            if (VDBG) log("Missing voicemail AlertDialog: NEGATIVE click...");
                            msg2.sendToTarget();  // see addVoiceMailNumber()
                            mApp.pokeUserActivity();
                        }})
                .setOnCancelListener(new OnCancelListener() {
                        public void onCancel(DialogInterface dialog) {
                            if (VDBG) log("Missing voicemail AlertDialog: CANCEL handler...");
                            msg.sendToTarget();  // see dontAddVoiceMailNumber()
                            mApp.pokeUserActivity();
                        }})
                .create();

        // When the dialog is up, completely hide the in-call UI
        // underneath (which is in a partially-constructed state).
        mMissingVoicemailDialog.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_DIM_BEHIND);

        mMissingVoicemailDialog.show();
    }

    private void addVoiceMailNumberPanel() {
        if (mMissingVoicemailDialog != null) {
            mMissingVoicemailDialog.dismiss();
            mMissingVoicemailDialog = null;
        }
        if (DBG) log("addVoiceMailNumberPanel: finishing InCallScreen...");
        endInCallScreenSession();

        if (DBG) log("show vm setting");

        // navigate to the Voicemail setting in the Call Settings activity.
        Intent intent = new Intent(CallFeaturesSetting.ACTION_ADD_VOICEMAIL);
        intent.setClass(this, CallFeaturesSetting.class);
        startActivity(intent);
    }

    private void dontAddVoiceMailNumber() {
        if (mMissingVoicemailDialog != null) {
            mMissingVoicemailDialog.dismiss();
            mMissingVoicemailDialog = null;
        }
        if (DBG) log("dontAddVoiceMailNumber: finishing InCallScreen...");
        endInCallScreenSession();
    }

    /**
     * Do some delayed cleanup after a Phone call gets disconnected.
     *
     * This method gets called a couple of seconds after any DISCONNECT
     * event from the Phone; it's triggered by the
     * DELAYED_CLEANUP_AFTER_DISCONNECT message we send in onDisconnect().
     *
     * If the Phone is totally idle right now, that means we've already
     * shown the "call ended" state for a couple of seconds, and it's now
     * time to endInCallScreenSession this activity.
     *
     * If the Phone is *not* idle right now, that probably means that one
     * call ended but the other line is still in use.  In that case, do
     * nothing, and instead stay here on the InCallScreen.
     */
    private void delayedCleanupAfterDisconnect() {
        if (VDBG) log("delayedCleanupAfterDisconnect()...  Phone state = " + mCM.getState());

        // Clean up any connections in the DISCONNECTED state.
        //
        // [Background: Even after a connection gets disconnected, its
        // Connection object still stays around, in the special
        // DISCONNECTED state.  This is necessary because we we need the
        // caller-id information from that Connection to properly draw the
        // "Call ended" state of the CallCard.
        //   But at this point we truly don't need that connection any
        // more, so tell the Phone that it's now OK to to clean up any
        // connections still in that state.]
        mCM.clearDisconnected();

        // There are two cases where we should *not* exit the InCallScreen:
        //   (1) Phone is still in use
        // or
        //   (2) There's an active progress indication (i.e. the "Retrying..."
        //       progress dialog) that we need to continue to display.

        boolean stayHere = phoneIsInUse() || mApp.inCallUiState.isProgressIndicationActive();

        if (stayHere) {
            if (DBG) log("- delayedCleanupAfterDisconnect: staying on the InCallScreen...");
        } else {
            // Phone is idle!  We should exit the in-call UI now.
            if (DBG) log("- delayedCleanupAfterDisconnect: phone is idle...");

            // And (finally!) exit from the in-call screen
            // (but not if we're already in the process of pausing...)
            if (mIsForegroundActivity) {
                if (DBG) log("- delayedCleanupAfterDisconnect: finishing InCallScreen...");

                // In some cases we finish the call by taking the user to the
                // Call Log.  Otherwise, we simply call endInCallScreenSession,
                // which will take us back to wherever we came from.
                //
                // UI note: In eclair and earlier, we went to the Call Log
                // after outgoing calls initiated on the device, but never for
                // incoming calls.  Now we do it for incoming calls too, as
                // long as the call was answered by the user.  (We always go
                // back where you came from after a rejected or missed incoming
                // call.)
                //
                // And in any case, *never* go to the call log if we're in
                // emergency mode (i.e. if the screen is locked and a lock
                // pattern or PIN/password is set), or if we somehow got here
                // on a non-voice-capable device.

                if (VDBG) log("- Post-call behavior:");
                if (VDBG) log("  - mLastDisconnectCause = " + mLastDisconnectCause);
                if (VDBG) log("  - isPhoneStateRestricted() = " + isPhoneStateRestricted());

                // DisconnectCause values in the most common scenarios:
                // - INCOMING_MISSED: incoming ringing call times out, or the
                //                    other end hangs up while still ringing
                // - INCOMING_REJECTED: user rejects the call while ringing
                // - LOCAL: user hung up while a call was active (after
                //          answering an incoming call, or after making an
                //          outgoing call)
                // - NORMAL: the other end hung up (after answering an incoming
                //           call, or after making an outgoing call)

                if ((mLastDisconnectCause != Connection.DisconnectCause.INCOMING_MISSED)
                        && (mLastDisconnectCause != Connection.DisconnectCause.INCOMING_REJECTED)
                        && !isPhoneStateRestricted()
                        && PhoneGlobals.sVoiceCapable) {
                    final Intent intent = mApp.createPhoneEndIntentUsingCallOrigin();
                    ActivityOptions opts = ActivityOptions.makeCustomAnimation(this,
                            R.anim.activity_close_enter, R.anim.activity_close_exit);
                    if (VDBG) {
                        log("- Show Call Log (or Dialtacts) after disconnect. Current intent: "
                                + intent);
                    }
                    try {
                        startActivity(intent, opts.toBundle());
                    } catch (ActivityNotFoundException e) {
                        // Don't crash if there's somehow no "Call log" at
                        // all on this device.
                        // (This should never happen, though, since we already
                        // checked PhoneApp.sVoiceCapable above, and any
                        // voice-capable device surely *should* have a call
                        // log activity....)
                        Log.w(LOG_TAG, "delayedCleanupAfterDisconnect: "
                              + "transition to call log failed; intent = " + intent);
                        // ...so just return back where we came from....
                    }
                    // Even if we did go to the call log, note that we still
                    // call endInCallScreenSession (below) to make sure we don't
                    // stay in the activity history.
                }

            }
            endInCallScreenSession();

            // Reset the call origin when the session ends and this in-call UI is being finished.
            mApp.setLatestActiveCallOrigin(null);
        }
    }


    /**
     * View.OnClickListener implementation.
     *
     * This method handles clicks from UI elements that use the
     * InCallScreen itself as their OnClickListener.
     *
     * Note: Currently this method is used only for a few special buttons:
     * - the mButtonManageConferenceDone "Back to call" button
     * - the "dim" effect for the secondary call photo in CallCard as the second "swap" button
     * - other OTASP-specific buttons managed by OtaUtils.java.
     *
     * *Most* in-call controls are handled by the handleOnscreenButtonClick() method, via the
     * InCallTouchUi widget.
     */
    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (VDBG) log("onClick(View " + view + ", id " + id + ")...");

        switch (id) {
            case R.id.manage_done:  // mButtonManageConferenceDone
                if (VDBG) log("onClick: mButtonManageConferenceDone...");
                // Hide the Manage Conference panel, return to NORMAL mode.
                setInCallScreenMode(InCallScreenMode.NORMAL);
                requestUpdateScreen();
                break;

            case R.id.dim_effect_for_secondary_photo:
                if (mInCallControlState.canSwap) {
                    internalSwapCalls();
                }
                break;

            default:
                // Presumably one of the OTASP-specific buttons managed by
                // OtaUtils.java.
                // (TODO: It would be cleaner for the OtaUtils instance itself to
                // be the OnClickListener for its own buttons.)

                if ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL
                     || mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED)
                    && mApp.otaUtils != null) {
                    mApp.otaUtils.onClickHandler(id);
                } else {
                    // Uh oh: we *should* only receive clicks here from the
                    // buttons managed by OtaUtils.java, but if we're not in one
                    // of the special OTASP modes, those buttons shouldn't have
                    // been visible in the first place.
                    Log.w(LOG_TAG,
                          "onClick: unexpected click from ID " + id + " (View = " + view + ")");
                }
                break;
        }

        EventLog.writeEvent(EventLogTags.PHONE_UI_BUTTON_CLICK,
                (view instanceof TextView) ? ((TextView) view).getText() : "");

        // Clicking any onscreen UI element counts as explicit "user activity".
        mApp.pokeUserActivity();
    }

    private void onHoldClick() {
        final boolean hasActiveCall = mCM.hasActiveFgCall();
        final boolean hasHoldingCall = mCM.hasActiveBgCall();
        log("onHoldClick: hasActiveCall = " + hasActiveCall
            + ", hasHoldingCall = " + hasHoldingCall);
        boolean newHoldState;
        boolean holdButtonEnabled;
        if (hasActiveCall && !hasHoldingCall) {
            // There's only one line in use, and that line is active.
            PhoneUtils.switchHoldingAndActive(
                mCM.getFirstActiveBgCall());  // Really means "hold" in this state
            newHoldState = true;
            holdButtonEnabled = true;
        } else if (!hasActiveCall && hasHoldingCall) {
            // There's only one line in use, and that line is on hold.
            PhoneUtils.switchHoldingAndActive(
                mCM.getFirstActiveBgCall());  // Really means "unhold" in this state
            newHoldState = false;
            holdButtonEnabled = true;
        } else {
            // Either zero or 2 lines are in use; "hold/unhold" is meaningless.
            newHoldState = false;
            holdButtonEnabled = false;
        }
        // No need to forcibly update the onscreen UI; just wait for the
        // onPhoneStateChanged() callback.  (This seems to be responsive
        // enough.)

        // Also, any time we hold or unhold, force the DTMF dialpad to close.
        closeDialpadInternal(true);  // do the "closing" animation
    }

    /**
     * Toggles in-call audio between speaker and the built-in earpiece (or
     * wired headset.)
     */
    public void toggleSpeaker() {
        // TODO: Turning on the speaker seems to enable the mic
        //   whether or not the "mute" feature is active!
        // Not sure if this is an feature of the telephony API
        //   that I need to handle specially, or just a bug.
        boolean newSpeakerState = !PhoneUtils.isSpeakerOn(this);
        log("toggleSpeaker(): newSpeakerState = " + newSpeakerState);

        if (newSpeakerState && isBluetoothAvailable() && isBluetoothAudioConnected()) {
            disconnectBluetoothAudio();
        }
        PhoneUtils.turnOnSpeaker(this, newSpeakerState, true);

        // And update the InCallTouchUi widget (since the "audio mode"
        // button might need to change its appearance based on the new
        // audio state.)
        updateInCallTouchUi();
    }

    /*
     * onMuteClick is called only when there is a foreground call
     */
    private void onMuteClick() {
        boolean newMuteState = !PhoneUtils.getMute();
        log("onMuteClick(): newMuteState = " + newMuteState);
        PhoneUtils.setMute(newMuteState);
    }

    /**
     * Toggles whether or not to route in-call audio to the bluetooth
     * headset, or do nothing (but log a warning) if no bluetooth device
     * is actually connected.
     *
     * TODO: this method is currently unused, but the "audio mode" UI
     * design is still in flux so let's keep it around for now.
     * (But if we ultimately end up *not* providing any way for the UI to
     * simply "toggle bluetooth", we can get rid of this method.)
     */
    public void toggleBluetooth() {
        if (VDBG) log("toggleBluetooth()...");

        if (isBluetoothAvailable()) {
            // Toggle the bluetooth audio connection state:
            if (isBluetoothAudioConnected()) {
                disconnectBluetoothAudio();
            } else {
                // Manually turn the speaker phone off, instead of allowing the
                // Bluetooth audio routing to handle it, since there's other
                // important state-updating that needs to happen in the
                // PhoneUtils.turnOnSpeaker() method.
                // (Similarly, whenever the user turns *on* the speaker, we
                // manually disconnect the active bluetooth headset;
                // see toggleSpeaker() and/or switchInCallAudio().)
                if (PhoneUtils.isSpeakerOn(this)) {
                    PhoneUtils.turnOnSpeaker(this, false, true);
                }

                connectBluetoothAudio();
            }
        } else {
            // Bluetooth isn't available; the onscreen UI shouldn't have
            // allowed this request in the first place!
            Log.w(LOG_TAG, "toggleBluetooth(): bluetooth is unavailable");
        }

        // And update the InCallTouchUi widget (since the "audio mode"
        // button might need to change its appearance based on the new
        // audio state.)
        updateInCallTouchUi();
    }

    /**
     * Switches the current routing of in-call audio between speaker,
     * bluetooth, and the built-in earpiece (or wired headset.)
     *
     * This method is used on devices that provide a single 3-way switch
     * for audio routing.  For devices that provide separate toggles for
     * Speaker and Bluetooth, see toggleBluetooth() and toggleSpeaker().
     *
     * TODO: UI design is still in flux.  If we end up totally
     * eliminating the concept of Speaker and Bluetooth toggle buttons,
     * we can get rid of toggleBluetooth() and toggleSpeaker().
     */
    public void switchInCallAudio(InCallAudioMode newMode) {
        log("switchInCallAudio: new mode = " + newMode);
        switch (newMode) {
            case SPEAKER:
                if (!PhoneUtils.isSpeakerOn(this)) {
                    // Switch away from Bluetooth, if it was active.
                    if (isBluetoothAvailable() && isBluetoothAudioConnected()) {
                        disconnectBluetoothAudio();
                    }
                    PhoneUtils.turnOnSpeaker(this, true, true);
                }
                break;

            case BLUETOOTH:
                // If already connected to BT, there's nothing to do here.
                if (isBluetoothAvailable() && !isBluetoothAudioConnected()) {
                    // Manually turn the speaker phone off, instead of allowing the
                    // Bluetooth audio routing to handle it, since there's other
                    // important state-updating that needs to happen in the
                    // PhoneUtils.turnOnSpeaker() method.
                    // (Similarly, whenever the user turns *on* the speaker, we
                    // manually disconnect the active bluetooth headset;
                    // see toggleSpeaker() and/or switchInCallAudio().)
                    if (PhoneUtils.isSpeakerOn(this)) {
                        PhoneUtils.turnOnSpeaker(this, false, true);
                    }
                    connectBluetoothAudio();
                }
                break;

            case EARPIECE:
                // Switch to either the handset earpiece, or the wired headset (if connected.)
                // (Do this by simply making sure both speaker and bluetooth are off.)
                if (isBluetoothAvailable() && isBluetoothAudioConnected()) {
                    disconnectBluetoothAudio();
                }
                if (PhoneUtils.isSpeakerOn(this)) {
                    PhoneUtils.turnOnSpeaker(this, false, true);
                }
                break;

            default:
                Log.wtf(LOG_TAG, "switchInCallAudio: unexpected mode " + newMode);
                break;
        }

        // And finally, update the InCallTouchUi widget (since the "audio
        // mode" button might need to change its appearance based on the
        // new audio state.)
        updateInCallTouchUi();
    }

    /**
     * Handle a click on the "Open/Close dialpad" button.
     *
     * @see DTMFTwelveKeyDialer#openDialer(boolean)
     * @see DTMFTwelveKeyDialer#closeDialer(boolean)
     */
    private void onOpenCloseDialpad() {
        if (VDBG) log("onOpenCloseDialpad()...");
        if (mDialer.isOpened()) {
            closeDialpadInternal(true);  // do the "closing" animation
        } else {
            openDialpadInternal(true);  // do the "opening" animation
        }
        mApp.updateProximitySensorMode(mCM.getState());
    }

    /** Internal wrapper around {@link DTMFTwelveKeyDialer#openDialer(boolean)} */
    private void openDialpadInternal(boolean animate) {
        mDialer.openDialer(animate);
        // And update the InCallUiState (so that we'll restore the dialpad
        // to the correct state if we get paused/resumed).
        mApp.inCallUiState.showDialpad = true;
    }

    // Internal wrapper around DTMFTwelveKeyDialer.closeDialer()
    private void closeDialpadInternal(boolean animate) {
        mDialer.closeDialer(animate);
        // And update the InCallUiState (so that we'll restore the dialpad
        // to the correct state if we get paused/resumed).
        mApp.inCallUiState.showDialpad = false;
    }

    /**
     * Handles button clicks from the InCallTouchUi widget.
     */
    /* package */ void handleOnscreenButtonClick(int id) {
        if (DBG) log("handleOnscreenButtonClick(id " + id + ")...");

        switch (id) {
            // Actions while an incoming call is ringing:
            case R.id.incomingCallAnswer:
                internalAnswerCall();
                break;
            case R.id.incomingCallReject:
                hangupRingingCall();
                break;
            case R.id.incomingCallRespondViaSms:
                internalRespondViaSms();
                break;

            // The other regular (single-tap) buttons used while in-call:
            case R.id.holdButton:
                onHoldClick();
                break;
            case R.id.swapButton:
                internalSwapCalls();
                break;
            case R.id.endButton:
                internalHangup();
                break;
            case R.id.dialpadButton:
                onOpenCloseDialpad();
                break;
            case R.id.muteButton:
                onMuteClick();
                break;
            case R.id.addButton:
                PhoneUtils.startNewCall(mCM);  // Fires off an ACTION_DIAL intent
                break;
            case R.id.mergeButton:
            case R.id.cdmaMergeButton:
                PhoneUtils.mergeCalls(mCM);
                break;
            case R.id.manageConferenceButton:
                // Show the Manage Conference panel.
                setInCallScreenMode(InCallScreenMode.MANAGE_CONFERENCE);
                requestUpdateScreen();
                break;

            default:
                Log.w(LOG_TAG, "handleOnscreenButtonClick: unexpected ID " + id);
                break;
        }

        // Clicking any onscreen UI element counts as explicit "user activity".
        mApp.pokeUserActivity();

        // Just in case the user clicked a "stateful" UI element (like one
        // of the toggle buttons), we force the in-call buttons to update,
        // to make sure the user sees the *new* current state.
        //
        // Note that some in-call buttons will *not* immediately change the
        // state of the UI, namely those that send a request to the telephony
        // layer (like "Hold" or "End call".)  For those buttons, the
        // updateInCallTouchUi() call here won't have any visible effect.
        // Instead, the UI will be updated eventually when the next
        // onPhoneStateChanged() event comes in and triggers an updateScreen()
        // call.
        //
        // TODO: updateInCallTouchUi() is overkill here; it would be
        // more efficient to update *only* the affected button(s).
        // (But this isn't a big deal since updateInCallTouchUi() is pretty
        // cheap anyway...)
        updateInCallTouchUi();
    }

    /**
     * Display a status or error indication to the user according to the
     * specified InCallUiState.CallStatusCode value.
     */
    private void showStatusIndication(CallStatusCode status) {
        switch (status) {
            case SUCCESS:
                // The InCallScreen does not need to display any kind of error indication,
                // so we shouldn't have gotten here in the first place.
                Log.wtf(LOG_TAG, "showStatusIndication: nothing to display");
                break;

            case POWER_OFF:
                // Radio is explictly powered off, presumably because the
                // device is in airplane mode.
                //
                // TODO: For now this UI is ultra-simple: we simply display
                // a message telling the user to turn off airplane mode.
                // But it might be nicer for the dialog to offer the option
                // to turn the radio on right there (and automatically retry
                // the call once network registration is complete.)
                showGenericErrorDialog(R.string.incall_error_power_off,
                                       true /* isStartupError */);
                break;

            case EMERGENCY_ONLY:
                // Only emergency numbers are allowed, but we tried to dial
                // a non-emergency number.
                // (This state is currently unused; see comments above.)
                showGenericErrorDialog(R.string.incall_error_emergency_only,
                                       true /* isStartupError */);
                break;

            case OUT_OF_SERVICE:
                // No network connection.
                showGenericErrorDialog(R.string.incall_error_out_of_service,
                                       true /* isStartupError */);
                break;

            case NO_PHONE_NUMBER_SUPPLIED:
                // The supplied Intent didn't contain a valid phone number.
                // (This is rare and should only ever happen with broken
                // 3rd-party apps.)  For now just show a generic error.
                showGenericErrorDialog(R.string.incall_error_no_phone_number_supplied,
                                       true /* isStartupError */);
                break;

            case DIALED_MMI:
                // Our initial phone number was actually an MMI sequence.
                // There's no real "error" here, but we do bring up the
                // a Toast (as requested of the New UI paradigm).
                //
                // In-call MMIs do not trigger the normal MMI Initiate
                // Notifications, so we should notify the user here.
                // Otherwise, the code in PhoneUtils.java should handle
                // user notifications in the form of Toasts or Dialogs.
                if (mCM.getState() == PhoneConstants.State.OFFHOOK) {
                    Toast.makeText(mApp, R.string.incall_status_dialed_mmi, Toast.LENGTH_SHORT)
                            .show();
                }
                break;

            case CALL_FAILED:
                // We couldn't successfully place the call; there was some
                // failure in the telephony layer.
                // TODO: Need UI spec for this failure case; for now just
                // show a generic error.
                showGenericErrorDialog(R.string.incall_error_call_failed,
                                       true /* isStartupError */);
                break;

            case VOICEMAIL_NUMBER_MISSING:
                // We tried to call a voicemail: URI but the device has no
                // voicemail number configured.
                handleMissingVoiceMailNumber();
                break;

            case CDMA_CALL_LOST:
                // This status indicates that InCallScreen should display the
                // CDMA-specific "call lost" dialog.  (If an outgoing call fails,
                // and the CDMA "auto-retry" feature is enabled, *and* the retried
                // call fails too, we display this specific dialog.)
                //
                // TODO: currently unused; see InCallUiState.needToShowCallLostDialog
                break;

            case EXITED_ECM:
                // This status indicates that InCallScreen needs to display a
                // warning that we're exiting ECM (emergency callback mode).
                showExitingECMDialog();
                break;

            default:
                throw new IllegalStateException(
                    "showStatusIndication: unexpected status code: " + status);
        }

        // TODO: still need to make sure that pressing OK or BACK from
        // *any* of the dialogs we launch here ends up calling
        // inCallUiState.clearPendingCallStatusCode()
        //  *and*
        // make sure the Dialog handles both OK *and* cancel by calling
        // endInCallScreenSession.  (See showGenericErrorDialog() for an
        // example.)
        //
        // (showGenericErrorDialog() currently does this correctly,
        // but handleMissingVoiceMailNumber() probably needs to be fixed too.)
        //
        // Also need to make sure that bailing out of any of these dialogs by
        // pressing Home clears out the pending status code too.  (If you do
        // that, neither the dialog's clickListener *or* cancelListener seems
        // to run...)
    }

    /**
     * Utility function to bring up a generic "error" dialog, and then bail
     * out of the in-call UI when the user hits OK (or the BACK button.)
     */
    private void showGenericErrorDialog(int resid, boolean isStartupError) {
        CharSequence msg = getResources().getText(resid);
        if (DBG) log("showGenericErrorDialog('" + msg + "')...");

        // create the clicklistener and cancel listener as needed.
        DialogInterface.OnClickListener clickListener;
        OnCancelListener cancelListener;
        if (isStartupError) {
            clickListener = new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    bailOutAfterErrorDialog();
                }};
            cancelListener = new OnCancelListener() {
                public void onCancel(DialogInterface dialog) {
                    bailOutAfterErrorDialog();
                }};
        } else {
            clickListener = new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    delayedCleanupAfterDisconnect();
                }};
            cancelListener = new OnCancelListener() {
                public void onCancel(DialogInterface dialog) {
                    delayedCleanupAfterDisconnect();
                }};
        }

        // TODO: Consider adding a setTitle() call here (with some generic
        // "failure" title?)
        mGenericErrorDialog = new AlertDialog.Builder(this)
                .setMessage(msg)
                .setPositiveButton(R.string.ok, clickListener)
                .setOnCancelListener(cancelListener)
                .create();

        // When the dialog is up, completely hide the in-call UI
        // underneath (which is in a partially-constructed state).
        mGenericErrorDialog.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_DIM_BEHIND);

        mGenericErrorDialog.show();
    }

    private void showCallLostDialog() {
        if (DBG) log("showCallLostDialog()...");

        // Don't need to show the dialog if InCallScreen isn't in the forgeround
        if (!mIsForegroundActivity) {
            if (DBG) log("showCallLostDialog: not the foreground Activity! Bailing out...");
            return;
        }

        // Don't need to show the dialog again, if there is one already.
        if (mCallLostDialog != null) {
            if (DBG) log("showCallLostDialog: There is a mCallLostDialog already.");
            return;
        }

        mCallLostDialog = new AlertDialog.Builder(this)
                .setMessage(R.string.call_lost)
                .setIconAttribute(android.R.attr.alertDialogIcon)
                .create();
        mCallLostDialog.show();
    }

    /**
     * Displays the "Exiting ECM" warning dialog.
     *
     * Background: If the phone is currently in ECM (Emergency callback
     * mode) and we dial a non-emergency number, that automatically
     * *cancels* ECM.  (That behavior comes from CdmaCallTracker.dial().)
     * When that happens, we need to warn the user that they're no longer
     * in ECM (bug 4207607.)
     *
     * So bring up a dialog explaining what's happening.  There's nothing
     * for the user to do, by the way; we're simply providing an
     * indication that they're exiting ECM.  We *could* use a Toast for
     * this, but toasts are pretty easy to miss, so instead use a dialog
     * with a single "OK" button.
     *
     * TODO: it's ugly that the code here has to make assumptions about
     *   the behavior of the telephony layer (namely that dialing a
     *   non-emergency number while in ECM causes us to exit ECM.)
     *
     *   Instead, this warning dialog should really be triggered by our
     *   handler for the
     *   TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED intent in
     *   PhoneApp.java.  But that won't work until that intent also
     *   includes a *reason* why we're exiting ECM, since we need to
     *   display this dialog when exiting ECM because of an outgoing call,
     *   but NOT if we're exiting ECM because the user manually turned it
     *   off via the EmergencyCallbackModeExitDialog.
     *
     *   Or, it might be simpler to just have outgoing non-emergency calls
     *   *not* cancel ECM.  That way the UI wouldn't have to do anything
     *   special here.
     */
    private void showExitingECMDialog() {
        Log.i(LOG_TAG, "showExitingECMDialog()...");

        if (mExitingECMDialog != null) {
            if (DBG) log("- DISMISSING mExitingECMDialog.");
            mExitingECMDialog.dismiss();  // safe even if already dismissed
            mExitingECMDialog = null;
        }

        // When the user dismisses the "Exiting ECM" dialog, we clear out
        // the pending call status code field (since we're done with this
        // dialog), but do *not* bail out of the InCallScreen.

        final InCallUiState inCallUiState = mApp.inCallUiState;
        DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    inCallUiState.clearPendingCallStatusCode();
                }};
        OnCancelListener cancelListener = new OnCancelListener() {
                public void onCancel(DialogInterface dialog) {
                    inCallUiState.clearPendingCallStatusCode();
                }};

        // Ultra-simple AlertDialog with only an OK button:
        mExitingECMDialog = new AlertDialog.Builder(this)
                .setMessage(R.string.progress_dialog_exiting_ecm)
                .setPositiveButton(R.string.ok, clickListener)
                .setOnCancelListener(cancelListener)
                .create();
        mExitingECMDialog.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
        mExitingECMDialog.show();
    }

    private void bailOutAfterErrorDialog() {
        if (mGenericErrorDialog != null) {
            if (DBG) log("bailOutAfterErrorDialog: DISMISSING mGenericErrorDialog.");
            mGenericErrorDialog.dismiss();
            mGenericErrorDialog = null;
        }
        if (DBG) log("bailOutAfterErrorDialog(): end InCallScreen session...");

        // Now that the user has dismissed the error dialog (presumably by
        // either hitting the OK button or pressing Back, we can now reset
        // the pending call status code field.
        //
        // (Note that the pending call status is NOT cleared simply
        // by the InCallScreen being paused or finished, since the resulting
        // dialog is supposed to persist across orientation changes or if the
        // screen turns off.)
        //
        // See the "Error / diagnostic indications" section of
        // InCallUiState.java for more detailed info about the
        // pending call status code field.
        final InCallUiState inCallUiState = mApp.inCallUiState;
        inCallUiState.clearPendingCallStatusCode();

        // Force the InCallScreen to truly finish(), rather than just
        // moving it to the back of the activity stack (which is what
        // our finish() method usually does.)
        // This is necessary to avoid an obscure scenario where the
        // InCallScreen can get stuck in an inconsistent state, somehow
        // causing a *subsequent* outgoing call to fail (bug 4172599).
        endInCallScreenSession(true /* force a real finish() call */);
    }

    /**
     * Dismisses (and nulls out) all persistent Dialogs managed
     * by the InCallScreen.  Useful if (a) we're about to bring up
     * a dialog and want to pre-empt any currently visible dialogs,
     * or (b) as a cleanup step when the Activity is going away.
     */
    private void dismissAllDialogs() {
        if (DBG) log("dismissAllDialogs()...");

        // Note it's safe to dismiss() a dialog that's already dismissed.
        // (Even if the AlertDialog object(s) below are still around, it's
        // possible that the actual dialog(s) may have already been
        // dismissed by the user.)

        if (mMissingVoicemailDialog != null) {
            if (VDBG) log("- DISMISSING mMissingVoicemailDialog.");
            mMissingVoicemailDialog.dismiss();
            mMissingVoicemailDialog = null;
        }
        if (mMmiStartedDialog != null) {
            if (VDBG) log("- DISMISSING mMmiStartedDialog.");
            mMmiStartedDialog.dismiss();
            mMmiStartedDialog = null;
        }
        if (mGenericErrorDialog != null) {
            if (VDBG) log("- DISMISSING mGenericErrorDialog.");
            mGenericErrorDialog.dismiss();
            mGenericErrorDialog = null;
        }
        if (mSuppServiceFailureDialog != null) {
            if (VDBG) log("- DISMISSING mSuppServiceFailureDialog.");
            mSuppServiceFailureDialog.dismiss();
            mSuppServiceFailureDialog = null;
        }
        if (mWaitPromptDialog != null) {
            if (VDBG) log("- DISMISSING mWaitPromptDialog.");
            mWaitPromptDialog.dismiss();
            mWaitPromptDialog = null;
        }
        if (mWildPromptDialog != null) {
            if (VDBG) log("- DISMISSING mWildPromptDialog.");
            mWildPromptDialog.dismiss();
            mWildPromptDialog = null;
        }
        if (mCallLostDialog != null) {
            if (VDBG) log("- DISMISSING mCallLostDialog.");
            mCallLostDialog.dismiss();
            mCallLostDialog = null;
        }
        if ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL
                || mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED)
                && mApp.otaUtils != null) {
            mApp.otaUtils.dismissAllOtaDialogs();
        }
        if (mPausePromptDialog != null) {
            if (DBG) log("- DISMISSING mPausePromptDialog.");
            mPausePromptDialog.dismiss();
            mPausePromptDialog = null;
        }
        if (mExitingECMDialog != null) {
            if (DBG) log("- DISMISSING mExitingECMDialog.");
            mExitingECMDialog.dismiss();
            mExitingECMDialog = null;
        }
    }

    /**
     * Updates the state of the onscreen "progress indication" used in
     * some (relatively rare) scenarios where we need to wait for
     * something to happen before enabling the in-call UI.
     *
     * If necessary, this method will cause a ProgressDialog (i.e. a
     * spinning wait cursor) to be drawn *on top of* whatever the current
     * state of the in-call UI is.
     *
     * @see InCallUiState.ProgressIndicationType
     */
    private void updateProgressIndication() {
        // If an incoming call is ringing, that takes priority over any
        // possible value of inCallUiState.progressIndication.
        if (mCM.hasActiveRingingCall()) {
            dismissProgressIndication();
            return;
        }

        // Otherwise, put up a progress indication if indicated by the
        // inCallUiState.progressIndication field.
        final InCallUiState inCallUiState = mApp.inCallUiState;
        switch (inCallUiState.getProgressIndication()) {
            case NONE:
                // No progress indication necessary, so make sure it's dismissed.
                dismissProgressIndication();
                break;

            case TURNING_ON_RADIO:
                showProgressIndication(
                    R.string.emergency_enable_radio_dialog_title,
                    R.string.emergency_enable_radio_dialog_message);
                break;

            case RETRYING:
                showProgressIndication(
                    R.string.emergency_enable_radio_dialog_title,
                    R.string.emergency_enable_radio_dialog_retry);
                break;

            default:
                Log.wtf(LOG_TAG, "updateProgressIndication: unexpected value: "
                        + inCallUiState.getProgressIndication());
                dismissProgressIndication();
                break;
        }
    }

    /**
     * Show an onscreen "progress indication" with the specified title and message.
     */
    private void showProgressIndication(int titleResId, int messageResId) {
        if (DBG) log("showProgressIndication(message " + messageResId + ")...");

        // TODO: make this be a no-op if the progress indication is
        // already visible with the exact same title and message.

        dismissProgressIndication();  // Clean up any prior progress indication
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setTitle(getText(titleResId));
        mProgressDialog.setMessage(getText(messageResId));
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.setCancelable(false);
        mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
        mProgressDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
        mProgressDialog.show();
    }

    /**
     * Dismiss the onscreen "progress indication" (if present).
     */
    private void dismissProgressIndication() {
        if (DBG) log("dismissProgressIndication()...");
        if (mProgressDialog != null) {
            mProgressDialog.dismiss();  // safe even if already dismissed
            mProgressDialog = null;
        }
    }


    //
    // Helper functions for answering incoming calls.
    //

    /**
     * Answer a ringing call.  This method does nothing if there's no
     * ringing or waiting call.
     */
    private void internalAnswerCall() {
        if (DBG) log("internalAnswerCall()...");
        // if (DBG) PhoneUtils.dumpCallState(mPhone);

        final boolean hasRingingCall = mCM.hasActiveRingingCall();

        if (hasRingingCall) {
            Phone phone = mCM.getRingingPhone();
            Call ringing = mCM.getFirstActiveRingingCall();
            int phoneType = phone.getPhoneType();
            if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                if (DBG) log("internalAnswerCall: answering (CDMA)...");
                if (mCM.hasActiveFgCall()
                        && mCM.getFgPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_SIP) {
                    // The incoming call is CDMA call and the ongoing
                    // call is a SIP call. The CDMA network does not
                    // support holding an active call, so there's no
                    // way to swap between a CDMA call and a SIP call.
                    // So for now, we just don't allow a CDMA call and
                    // a SIP call to be active at the same time.We'll
                    // "answer incoming, end ongoing" in this case.
                    if (DBG) log("internalAnswerCall: answer "
                            + "CDMA incoming and end SIP ongoing");
                    PhoneUtils.answerAndEndActive(mCM, ringing);
                } else {
                    PhoneUtils.answerCall(ringing);
                }
            } else if (phoneType == PhoneConstants.PHONE_TYPE_SIP) {
                if (DBG) log("internalAnswerCall: answering (SIP)...");
                if (mCM.hasActiveFgCall()
                        && mCM.getFgPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
                    // Similar to the PHONE_TYPE_CDMA handling.
                    // The incoming call is SIP call and the ongoing
                    // call is a CDMA call. The CDMA network does not
                    // support holding an active call, so there's no
                    // way to swap between a CDMA call and a SIP call.
                    // So for now, we just don't allow a CDMA call and
                    // a SIP call to be active at the same time.We'll
                    // "answer incoming, end ongoing" in this case.
                    if (DBG) log("internalAnswerCall: answer "
                            + "SIP incoming and end CDMA ongoing");
                    PhoneUtils.answerAndEndActive(mCM, ringing);
                } else {
                    PhoneUtils.answerCall(ringing);
                }
            } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                if (DBG) log("internalAnswerCall: answering (GSM)...");
                // GSM: this is usually just a wrapper around
                // PhoneUtils.answerCall(), *but* we also need to do
                // something special for the "both lines in use" case.

                final boolean hasActiveCall = mCM.hasActiveFgCall();
                final boolean hasHoldingCall = mCM.hasActiveBgCall();

                if (hasActiveCall && hasHoldingCall) {
                    if (DBG) log("internalAnswerCall: answering (both lines in use!)...");
                    // The relatively rare case where both lines are
                    // already in use.  We "answer incoming, end ongoing"
                    // in this case, according to the current UI spec.
                    PhoneUtils.answerAndEndActive(mCM, ringing);

                    // Alternatively, we could use
                    // PhoneUtils.answerAndEndHolding(mPhone);
                    // here to end the on-hold call instead.
                } else {
                    if (DBG) log("internalAnswerCall: answering...");
                    PhoneUtils.answerCall(ringing);  // Automatically holds the current active call,
                                                    // if there is one
                }
            } else {
                throw new IllegalStateException("Unexpected phone type: " + phoneType);
            }

            // Call origin is valid only with outgoing calls. Disable it on incoming calls.
            mApp.setLatestActiveCallOrigin(null);
        }
    }

    /**
     * Answer the ringing call *and* hang up the ongoing call.
     */
    private void internalAnswerAndEnd() {
        if (DBG) log("internalAnswerAndEnd()...");
        if (VDBG) PhoneUtils.dumpCallManager();
        // In the rare case when multiple calls are ringing, the UI policy
        // it to always act on the first ringing call.
        PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
    }

    /**
     * Hang up the ringing call (aka "Don't answer").
     */
    /* package */ void hangupRingingCall() {
        if (DBG) log("hangupRingingCall()...");
        if (VDBG) PhoneUtils.dumpCallManager();
        // In the rare case when multiple calls are ringing, the UI policy
        // it to always act on the first ringing call.
        PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());
    }

    /**
     * Silence the ringer (if an incoming call is ringing.)
     */
    private void internalSilenceRinger() {
        if (DBG) log("internalSilenceRinger()...");
        final CallNotifier notifier = mApp.notifier;
        if (notifier.isRinging()) {
            // ringer is actually playing, so silence it.
            notifier.silenceRinger();
        }
    }

    /**
     * Respond via SMS to the ringing call.
     * @see RespondViaSmsManager
     */
    private void internalRespondViaSms() {
        log("internalRespondViaSms()...");
        if (VDBG) PhoneUtils.dumpCallManager();

        // In the rare case when multiple calls are ringing, the UI policy
        // it to always act on the first ringing call.
        Call ringingCall = mCM.getFirstActiveRingingCall();

        mRespondViaSmsManager.showRespondViaSmsPopup(ringingCall);

        // Silence the ringer, since it would be distracting while you're trying
        // to pick a response.  (Note that we'll restart the ringer if you bail
        // out of the popup, though; see RespondViaSmsCancelListener.)
        internalSilenceRinger();
    }

    /**
     * Hang up the current active call.
     */
    private void internalHangup() {
        PhoneConstants.State state = mCM.getState();
        log("internalHangup()...  phone state = " + state);

        // Regardless of the phone state, issue a hangup request.
        // (If the phone is already idle, this call will presumably have no
        // effect (but also see the note below.))
        PhoneUtils.hangup(mCM);

        // If the user just hung up the only active call, we'll eventually exit
        // the in-call UI after the following sequence:
        // - When the hangup() succeeds, we'll get a DISCONNECT event from
        //   the telephony layer (see onDisconnect()).
        // - We immediately switch to the "Call ended" state (see the "delayed
        //   bailout" code path in onDisconnect()) and also post a delayed
        //   DELAYED_CLEANUP_AFTER_DISCONNECT message.
        // - When the DELAYED_CLEANUP_AFTER_DISCONNECT message comes in (see
        //   delayedCleanupAfterDisconnect()) we do some final cleanup, and exit
        //   this activity unless the phone is still in use (i.e. if there's
        //   another call, or something else going on like an active MMI
        //   sequence.)

        if (state == PhoneConstants.State.IDLE) {
            // The user asked us to hang up, but the phone was (already) idle!
            Log.w(LOG_TAG, "internalHangup(): phone is already IDLE!");

            // This is rare, but can happen in a few cases:
            // (a) If the user quickly double-taps the "End" button.  In this case
            //   we'll see that 2nd press event during the brief "Call ended"
            //   state (where the phone is IDLE), or possibly even before the
            //   radio has been able to respond to the initial hangup request.
            // (b) More rarely, this can happen if the user presses "End" at the
            //   exact moment that the call ends on its own (like because of the
            //   other person hanging up.)
            // (c) Finally, this could also happen if we somehow get stuck here on
            //   the InCallScreen with the phone truly idle, perhaps due to a
            //   bug where we somehow *didn't* exit when the phone became idle
            //   in the first place.

            // TODO: as a "safety valve" for case (c), consider immediately
            // bailing out of the in-call UI right here.  (The user can always
            // bail out by pressing Home, of course, but they'll probably try
            // pressing End first.)
            //
            //    Log.i(LOG_TAG, "internalHangup(): phone is already IDLE!  Bailing out...");
            //    endInCallScreenSession();
        }
    }

    /**
     * InCallScreen-specific wrapper around PhoneUtils.switchHoldingAndActive().
     */
    private void internalSwapCalls() {
        if (DBG) log("internalSwapCalls()...");

        // Any time we swap calls, force the DTMF dialpad to close.
        // (We want the regular in-call UI to be visible right now, so the
        // user can clearly see which call is now in the foreground.)
        closeDialpadInternal(true);  // do the "closing" animation

        // Also, clear out the "history" of DTMF digits you typed, to make
        // sure you don't see digits from call #1 while call #2 is active.
        // (Yes, this does mean that swapping calls twice will cause you
        // to lose any previous digits from the current call; see the TODO
        // comment on DTMFTwelvKeyDialer.clearDigits() for more info.)
        mDialer.clearDigits();

        // Swap the fg and bg calls.
        // In the future we may provides some way for user to choose among
        // multiple background calls, for now, always act on the first background calll.
        PhoneUtils.switchHoldingAndActive(mCM.getFirstActiveBgCall());

        // If we have a valid BluetoothPhoneService then since CDMA network or
        // Telephony FW does not send us information on which caller got swapped
        // we need to update the second call active state in BluetoothPhoneService internally
        if (mCM.getBgPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
            IBluetoothHeadsetPhone btPhone = mApp.getBluetoothPhoneService();
            if (btPhone != null) {
                try {
                    btPhone.cdmaSwapSecondCallState();
                } catch (RemoteException e) {
                    Log.e(LOG_TAG, Log.getStackTraceString(new Throwable()));
                }
            }
        }

    }

    /**
     * Sets the current high-level "mode" of the in-call UI.
     *
     * NOTE: if newMode is CALL_ENDED, the caller is responsible for
     * posting a delayed DELAYED_CLEANUP_AFTER_DISCONNECT message, to make
     * sure the "call ended" state goes away after a couple of seconds.
     *
     * Note this method does NOT refresh of the onscreen UI; the caller is
     * responsible for calling updateScreen() or requestUpdateScreen() if
     * necessary.
     */
    private void setInCallScreenMode(InCallScreenMode newMode) {
        if (DBG) log("setInCallScreenMode: " + newMode);
        mApp.inCallUiState.inCallScreenMode = newMode;

        switch (newMode) {
            case MANAGE_CONFERENCE:
                if (!PhoneUtils.isConferenceCall(mCM.getActiveFgCall())) {
                    Log.w(LOG_TAG, "MANAGE_CONFERENCE: no active conference call!");
                    // Hide the Manage Conference panel, return to NORMAL mode.
                    setInCallScreenMode(InCallScreenMode.NORMAL);
                    return;
                }
                List<Connection> connections = mCM.getFgCallConnections();
                // There almost certainly will be > 1 connection,
                // since isConferenceCall() just returned true.
                if ((connections == null) || (connections.size() <= 1)) {
                    Log.w(LOG_TAG,
                          "MANAGE_CONFERENCE: Bogus TRUE from isConferenceCall(); connections = "
                          + connections);
                    // Hide the Manage Conference panel, return to NORMAL mode.
                    setInCallScreenMode(InCallScreenMode.NORMAL);
                    return;
                }

                // TODO: Don't do this here. The call to
                // initManageConferencePanel() should instead happen
                // automagically in ManageConferenceUtils the very first
                // time you call updateManageConferencePanel() or
                // setPanelVisible(true).
                mManageConferenceUtils.initManageConferencePanel();  // if necessary

                mManageConferenceUtils.updateManageConferencePanel(connections);

                // The "Manage conference" UI takes up the full main frame,
                // replacing the CallCard PopupWindow.
                mManageConferenceUtils.setPanelVisible(true);

                // Start the chronometer.
                // TODO: Similarly, we shouldn't expose startConferenceTime()
                // and stopConferenceTime(); the ManageConferenceUtils
                // class ought to manage the conferenceTime widget itself
                // based on setPanelVisible() calls.

                // Note: there is active Fg call since we are in conference call
                long callDuration =
                        mCM.getActiveFgCall().getEarliestConnection().getDurationMillis();
                mManageConferenceUtils.startConferenceTime(
                        SystemClock.elapsedRealtime() - callDuration);

                // No need to close the dialer here, since the Manage
                // Conference UI will just cover it up anyway.

                break;

            case CALL_ENDED:
            case NORMAL:
                mManageConferenceUtils.setPanelVisible(false);
                mManageConferenceUtils.stopConferenceTime();
                break;

            case OTA_NORMAL:
                mApp.otaUtils.setCdmaOtaInCallScreenUiState(
                        OtaUtils.CdmaOtaInCallScreenUiState.State.NORMAL);
                break;

            case OTA_ENDED:
                mApp.otaUtils.setCdmaOtaInCallScreenUiState(
                        OtaUtils.CdmaOtaInCallScreenUiState.State.ENDED);
                break;

            case UNDEFINED:
                // Set our Activities intent to ACTION_UNDEFINED so
                // that if we get resumed after we've completed a call
                // the next call will not cause checkIsOtaCall to
                // return true.
                //
                // TODO(OTASP): update these comments
                //
                // With the framework as of October 2009 the sequence below
                // causes the framework to call onResume, onPause, onNewIntent,
                // onResume. If we don't call setIntent below then when the
                // first onResume calls checkIsOtaCall via checkOtaspStateOnResume it will
                // return true and the Activity will be confused.
                //
                //  1) Power up Phone A
                //  2) Place *22899 call and activate Phone A
                //  3) Press the power key on Phone A to turn off the display
                //  4) Call Phone A from Phone B answering Phone A
                //  5) The screen will be blank (Should be normal InCallScreen)
                //  6) Hang up the Phone B
                //  7) Phone A displays the activation screen.
                //
                // Step 3 is the critical step to cause the onResume, onPause
                // onNewIntent, onResume sequence. If step 3 is skipped the
                // sequence will be onNewIntent, onResume and all will be well.
                setIntent(new Intent(ACTION_UNDEFINED));

                // Cleanup Ota Screen if necessary and set the panel
                // to VISIBLE.
                if (mCM.getState() != PhoneConstants.State.OFFHOOK) {
                    if (mApp.otaUtils != null) {
                        mApp.otaUtils.cleanOtaScreen(true);
                    }
                } else {
                    log("WARNING: Setting mode to UNDEFINED but phone is OFFHOOK,"
                            + " skip cleanOtaScreen.");
                }
                break;
        }
    }

    /**
     * @return true if the "Manage conference" UI is currently visible.
     */
    /* package */ boolean isManageConferenceMode() {
        return (mApp.inCallUiState.inCallScreenMode == InCallScreenMode.MANAGE_CONFERENCE);
    }

    /**
     * Checks if the "Manage conference" UI needs to be updated.
     * If the state of the current conference call has changed
     * since our previous call to updateManageConferencePanel()),
     * do a fresh update.  Also, if the current call is no longer a
     * conference call at all, bail out of the "Manage conference" UI and
     * return to InCallScreenMode.NORMAL mode.
     */
    private void updateManageConferencePanelIfNecessary() {
        if (VDBG) log("updateManageConferencePanelIfNecessary: " + mCM.getActiveFgCall() + "...");

        List<Connection> connections = mCM.getFgCallConnections();
        if (connections == null) {
            if (VDBG) log("==> no connections on foreground call!");
            // Hide the Manage Conference panel, return to NORMAL mode.
            setInCallScreenMode(InCallScreenMode.NORMAL);
            SyncWithPhoneStateStatus status = syncWithPhoneState();
            if (status != SyncWithPhoneStateStatus.SUCCESS) {
                Log.w(LOG_TAG, "- syncWithPhoneState failed! status = " + status);
                // We shouldn't even be in the in-call UI in the first
                // place, so bail out:
                if (DBG) log("updateManageConferencePanelIfNecessary: endInCallScreenSession... 1");
                endInCallScreenSession();
                return;
            }
            return;
        }

        int numConnections = connections.size();
        if (numConnections <= 1) {
            if (VDBG) log("==> foreground call no longer a conference!");
            // Hide the Manage Conference panel, return to NORMAL mode.
            setInCallScreenMode(InCallScreenMode.NORMAL);
            SyncWithPhoneStateStatus status = syncWithPhoneState();
            if (status != SyncWithPhoneStateStatus.SUCCESS) {
                Log.w(LOG_TAG, "- syncWithPhoneState failed! status = " + status);
                // We shouldn't even be in the in-call UI in the first
                // place, so bail out:
                if (DBG) log("updateManageConferencePanelIfNecessary: endInCallScreenSession... 2");
                endInCallScreenSession();
                return;
            }
            return;
        }

        // TODO: the test to see if numConnections has changed can go in
        // updateManageConferencePanel(), rather than here.
        if (numConnections != mManageConferenceUtils.getNumCallersInConference()) {
            if (VDBG) log("==> Conference size has changed; need to rebuild UI!");
            mManageConferenceUtils.updateManageConferencePanel(connections);
        }
    }

    /**
     * Updates {@link #mCallCard}'s visibility state per DTMF dialpad visibility. They
     * cannot be shown simultaneously and thus we should reflect DTMF dialpad visibility into
     * another.
     *
     * Note: During OTA calls or users' managing conference calls, we should *not* call this method
     * but manually manage both visibility.
     *
     * @see #updateScreen()
     */
    private void updateCallCardVisibilityPerDialerState(boolean animate) {
        // We need to hide the CallCard while the dialpad is visible.
        if (isDialerOpened()) {
            if (VDBG) {
                log("- updateCallCardVisibilityPerDialerState(animate="
                        + animate + "): dialpad open, hide mCallCard...");
            }
            if (animate) {
                AnimationUtils.Fade.hide(mCallCard, View.GONE);
            } else {
                mCallCard.setVisibility(View.GONE);
            }
        } else {
            // Dialpad is dismissed; bring back the CallCard if it's supposed to be visible.
            if ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.NORMAL)
                || (mApp.inCallUiState.inCallScreenMode == InCallScreenMode.CALL_ENDED)) {
                if (VDBG) {
                    log("- updateCallCardVisibilityPerDialerState(animate="
                            + animate + "): dialpad dismissed, show mCallCard...");
                }
                if (animate) {
                    AnimationUtils.Fade.show(mCallCard);
                } else {
                    mCallCard.setVisibility(View.VISIBLE);
                }
            }
        }
    }

    /**
     * @see DTMFTwelveKeyDialer#isOpened()
     */
    /* package */ boolean isDialerOpened() {
        return (mDialer != null && mDialer.isOpened());
    }

    /**
     * Called any time the DTMF dialpad is opened.
     * @see DTMFTwelveKeyDialer#openDialer(boolean)
     */
    /* package */ void onDialerOpen(boolean animate) {
        if (DBG) log("onDialerOpen()...");

        // Update the in-call touch UI.
        updateInCallTouchUi();

        // Update CallCard UI, which depends on the dialpad.
        updateCallCardVisibilityPerDialerState(animate);

        // This counts as explicit "user activity".
        mApp.pokeUserActivity();

        //If on OTA Call, hide OTA Screen
        // TODO: This may not be necessary, now that the dialpad is
        // always visible in OTA mode.
        if  ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL
                || mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED)
                && mApp.otaUtils != null) {
            mApp.otaUtils.hideOtaScreen();
        }
    }

    /**
     * Called any time the DTMF dialpad is closed.
     * @see DTMFTwelveKeyDialer#closeDialer(boolean)
     */
    /* package */ void onDialerClose(boolean animate) {
        if (DBG) log("onDialerClose()...");

        // OTA-specific cleanup upon closing the dialpad.
        if ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL)
            || (mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED)
            || ((mApp.cdmaOtaScreenState != null)
                && (mApp.cdmaOtaScreenState.otaScreenState ==
                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION))) {
            if (mApp.otaUtils != null) {
                mApp.otaUtils.otaShowProperScreen();
            }
        }

        // Update the in-call touch UI.
        updateInCallTouchUi();

        // Update CallCard UI, which depends on the dialpad.
        updateCallCardVisibilityPerDialerState(animate);

        // This counts as explicit "user activity".
        mApp.pokeUserActivity();
    }

    /**
     * Determines when we can dial DTMF tones.
     */
    /* package */ boolean okToDialDTMFTones() {
        final boolean hasRingingCall = mCM.hasActiveRingingCall();
        final Call.State fgCallState = mCM.getActiveFgCallState();

        // We're allowed to send DTMF tones when there's an ACTIVE
        // foreground call, and not when an incoming call is ringing
        // (since DTMF tones are useless in that state), or if the
        // Manage Conference UI is visible (since the tab interferes
        // with the "Back to call" button.)

        // We can also dial while in ALERTING state because there are
        // some connections that never update to an ACTIVE state (no
        // indication from the network).
        boolean canDial =
            (fgCallState == Call.State.ACTIVE || fgCallState == Call.State.ALERTING)
            && !hasRingingCall
            && (mApp.inCallUiState.inCallScreenMode != InCallScreenMode.MANAGE_CONFERENCE);

        if (VDBG) log ("[okToDialDTMFTones] foreground state: " + fgCallState +
                ", ringing state: " + hasRingingCall +
                ", call screen mode: " + mApp.inCallUiState.inCallScreenMode +
                ", result: " + canDial);

        return canDial;
    }

    /**
     * @return true if the in-call DTMF dialpad should be available to the
     *      user, given the current state of the phone and the in-call UI.
     *      (This is used to control the enabledness of the "Show
     *      dialpad" onscreen button; see InCallControlState.dialpadEnabled.)
     */
    /* package */ boolean okToShowDialpad() {
        // Very similar to okToDialDTMFTones(), but allow DIALING here.
        final Call.State fgCallState = mCM.getActiveFgCallState();
        return okToDialDTMFTones() || (fgCallState == Call.State.DIALING);
    }

    /**
     * Initializes the in-call touch UI on devices that need it.
     */
    private void initInCallTouchUi() {
        if (DBG) log("initInCallTouchUi()...");
        // TODO: we currently use the InCallTouchUi widget in at least
        // some states on ALL platforms.  But if some devices ultimately
        // end up not using *any* onscreen touch UI, we should make sure
        // to not even inflate the InCallTouchUi widget on those devices.
        mInCallTouchUi = (InCallTouchUi) findViewById(R.id.inCallTouchUi);
        mInCallTouchUi.setInCallScreenInstance(this);

        // RespondViaSmsManager implements the "Respond via SMS"
        // feature that's triggered from the incoming call widget.
        mRespondViaSmsManager = new RespondViaSmsManager();
        mRespondViaSmsManager.setInCallScreenInstance(this);
    }

    /**
     * Updates the state of the in-call touch UI.
     */
    private void updateInCallTouchUi() {
        if (mInCallTouchUi != null) {
            mInCallTouchUi.updateState(mCM);
        }
    }

    /**
     * @return the InCallTouchUi widget
     */
    /* package */ InCallTouchUi getInCallTouchUi() {
        return mInCallTouchUi;
    }

    /**
     * Posts a handler message telling the InCallScreen to refresh the
     * onscreen in-call UI.
     *
     * This is just a wrapper around updateScreen(), for use by the
     * rest of the phone app or from a thread other than the UI thread.
     *
     * updateScreen() is a no-op if the InCallScreen is not the foreground
     * activity, so it's safe to call this whether or not the InCallScreen
     * is currently visible.
     */
    /* package */ void requestUpdateScreen() {
        if (DBG) log("requestUpdateScreen()...");
        mHandler.removeMessages(REQUEST_UPDATE_SCREEN);
        mHandler.sendEmptyMessage(REQUEST_UPDATE_SCREEN);
    }

    /**
     * @return true if we're in restricted / emergency dialing only mode.
     */
    public boolean isPhoneStateRestricted() {
        // TODO:  This needs to work IN TANDEM with the KeyGuardViewMediator Code.
        // Right now, it looks like the mInputRestricted flag is INTERNAL to the
        // KeyGuardViewMediator and SPECIFICALLY set to be FALSE while the emergency
        // phone call is being made, to allow for input into the InCallScreen.
        // Having the InCallScreen judge the state of the device from this flag
        // becomes meaningless since it is always false for us.  The mediator should
        // have an additional API to let this app know that it should be restricted.
        int serviceState = mCM.getServiceState();
        return ((serviceState == ServiceState.STATE_EMERGENCY_ONLY) ||
                (serviceState == ServiceState.STATE_OUT_OF_SERVICE) ||
                (mApp.getKeyguardManager().inKeyguardRestrictedInputMode()));
    }


    //
    // Bluetooth helper methods.
    //
    // - BluetoothAdapter is the Bluetooth system service.  If
    //   getDefaultAdapter() returns null
    //   then the device is not BT capable.  Use BluetoothDevice.isEnabled()
    //   to see if BT is enabled on the device.
    //
    // - BluetoothHeadset is the API for the control connection to a
    //   Bluetooth Headset.  This lets you completely connect/disconnect a
    //   headset (which we don't do from the Phone UI!) but also lets you
    //   get the address of the currently active headset and see whether
    //   it's currently connected.

    /**
     * @return true if the Bluetooth on/off switch in the UI should be
     *         available to the user (i.e. if the device is BT-capable
     *         and a headset is connected.)
     */
    /* package */ boolean isBluetoothAvailable() {
        if (VDBG) log("isBluetoothAvailable()...");

        // There's no need to ask the Bluetooth system service if BT is enabled:
        //
        //    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        //    if ((adapter == null) || !adapter.isEnabled()) {
        //        if (DBG) log("  ==> FALSE (BT not enabled)");
        //        return false;
        //    }
        //    if (DBG) log("  - BT enabled!  device name " + adapter.getName()
        //                 + ", address " + adapter.getAddress());
        //
        // ...since we already have a BluetoothHeadset instance.  We can just
        // call isConnected() on that, and assume it'll be false if BT isn't
        // enabled at all.

        // Check if there's a connected headset, using the BluetoothHeadset API.
        boolean isConnected = false;
        if (mBluetoothHeadset != null) {
            List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();

            if (deviceList.size() > 0) {
                BluetoothDevice device = deviceList.get(0);
                isConnected = true;

                if (VDBG) log("  - headset state = " +
                              mBluetoothHeadset.getConnectionState(device));
                if (VDBG) log("  - headset address: " + device);
                if (VDBG) log("  - isConnected: " + isConnected);
            }
        }

        if (VDBG) log("  ==> " + isConnected);
        return isConnected;
    }

    /**
     * @return true if a BT Headset is available, and its audio is currently connected.
     */
    /* package */ boolean isBluetoothAudioConnected() {
        if (mBluetoothHeadset == null) {
            if (VDBG) log("isBluetoothAudioConnected: ==> FALSE (null mBluetoothHeadset)");
            return false;
        }
        List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();

        if (deviceList.isEmpty()) {
            return false;
        }
        BluetoothDevice device = deviceList.get(0);
        boolean isAudioOn = mBluetoothHeadset.isAudioConnected(device);
        if (VDBG) log("isBluetoothAudioConnected: ==> isAudioOn = " + isAudioOn);
        return isAudioOn;
    }

    /**
     * Helper method used to control the onscreen "Bluetooth" indication;
     * see InCallControlState.bluetoothIndicatorOn.
     *
     * @return true if a BT device is available and its audio is currently connected,
     *              <b>or</b> if we issued a BluetoothHeadset.connectAudio()
     *              call within the last 5 seconds (which presumably means
     *              that the BT audio connection is currently being set
     *              up, and will be connected soon.)
     */
    /* package */ boolean isBluetoothAudioConnectedOrPending() {
        if (isBluetoothAudioConnected()) {
            if (VDBG) log("isBluetoothAudioConnectedOrPending: ==> TRUE (really connected)");
            return true;
        }

        // If we issued a connectAudio() call "recently enough", even
        // if BT isn't actually connected yet, let's still pretend BT is
        // on.  This makes the onscreen indication more responsive.
        if (mBluetoothConnectionPending) {
            long timeSinceRequest =
                    SystemClock.elapsedRealtime() - mBluetoothConnectionRequestTime;
            if (timeSinceRequest < 5000 /* 5 seconds */) {
                if (VDBG) log("isBluetoothAudioConnectedOrPending: ==> TRUE (requested "
                             + timeSinceRequest + " msec ago)");
                return true;
            } else {
                if (VDBG) log("isBluetoothAudioConnectedOrPending: ==> FALSE (request too old: "
                             + timeSinceRequest + " msec ago)");
                mBluetoothConnectionPending = false;
                return false;
            }
        }

        if (VDBG) log("isBluetoothAudioConnectedOrPending: ==> FALSE");
        return false;
    }

    /**
     * Posts a message to our handler saying to update the onscreen UI
     * based on a bluetooth headset state change.
     */
    /* package */ void requestUpdateBluetoothIndication() {
        if (VDBG) log("requestUpdateBluetoothIndication()...");
        // No need to look at the current state here; any UI elements that
        // care about the bluetooth state (i.e. the CallCard) get
        // the necessary state directly from PhoneApp.showBluetoothIndication().
        mHandler.removeMessages(REQUEST_UPDATE_BLUETOOTH_INDICATION);
        mHandler.sendEmptyMessage(REQUEST_UPDATE_BLUETOOTH_INDICATION);
    }

    private void dumpBluetoothState() {
        log("============== dumpBluetoothState() =============");
        log("= isBluetoothAvailable: " + isBluetoothAvailable());
        log("= isBluetoothAudioConnected: " + isBluetoothAudioConnected());
        log("= isBluetoothAudioConnectedOrPending: " + isBluetoothAudioConnectedOrPending());
        log("= PhoneApp.showBluetoothIndication: "
            + mApp.showBluetoothIndication());
        log("=");
        if (mBluetoothAdapter != null) {
            if (mBluetoothHeadset != null) {
                List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();

                if (deviceList.size() > 0) {
                    BluetoothDevice device = deviceList.get(0);
                    log("= BluetoothHeadset.getCurrentDevice: " + device);
                    log("= BluetoothHeadset.State: "
                        + mBluetoothHeadset.getConnectionState(device));
                    log("= BluetoothHeadset audio connected: " +
                        mBluetoothHeadset.isAudioConnected(device));
                }
            } else {
                log("= mBluetoothHeadset is null");
            }
        } else {
            log("= mBluetoothAdapter is null; device is not BT capable");
        }
    }

    /* package */ void connectBluetoothAudio() {
        if (VDBG) log("connectBluetoothAudio()...");
        if (mBluetoothHeadset != null) {
            // TODO(BT) check return
            mBluetoothHeadset.connectAudio();
        }

        // Watch out: The bluetooth connection doesn't happen instantly;
        // the connectAudio() call returns instantly but does its real
        // work in another thread.  The mBluetoothConnectionPending flag
        // is just a little trickery to ensure that the onscreen UI updates
        // instantly. (See isBluetoothAudioConnectedOrPending() above.)
        mBluetoothConnectionPending = true;
        mBluetoothConnectionRequestTime = SystemClock.elapsedRealtime();
    }

    /* package */ void disconnectBluetoothAudio() {
        if (VDBG) log("disconnectBluetoothAudio()...");
        if (mBluetoothHeadset != null) {
            mBluetoothHeadset.disconnectAudio();
        }
        mBluetoothConnectionPending = false;
    }

    /**
     * Posts a handler message telling the InCallScreen to close
     * the OTA failure notice after the specified delay.
     * @see OtaUtils.otaShowProgramFailureNotice
     */
    /* package */ void requestCloseOtaFailureNotice(long timeout) {
        if (DBG) log("requestCloseOtaFailureNotice() with timeout: " + timeout);
        mHandler.sendEmptyMessageDelayed(REQUEST_CLOSE_OTA_FAILURE_NOTICE, timeout);

        // TODO: we probably ought to call removeMessages() for this
        // message code in either onPause or onResume, just to be 100%
        // sure that the message we just posted has no way to affect a
        // *different* call if the user quickly backs out and restarts.
        // (This is also true for requestCloseSpcErrorNotice() below, and
        // probably anywhere else we use mHandler.sendEmptyMessageDelayed().)
    }

    /**
     * Posts a handler message telling the InCallScreen to close
     * the SPC error notice after the specified delay.
     * @see OtaUtils.otaShowSpcErrorNotice
     */
    /* package */ void requestCloseSpcErrorNotice(long timeout) {
        if (DBG) log("requestCloseSpcErrorNotice() with timeout: " + timeout);
        mHandler.sendEmptyMessageDelayed(REQUEST_CLOSE_SPC_ERROR_NOTICE, timeout);
    }

    public boolean isOtaCallInActiveState() {
        if ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL)
                || ((mApp.cdmaOtaScreenState != null)
                    && (mApp.cdmaOtaScreenState.otaScreenState ==
                        CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Handle OTA Call End scenario when display becomes dark during OTA Call
     * and InCallScreen is in pause mode.  CallNotifier will listen for call
     * end indication and call this api to handle OTA Call end scenario
     */
    public void handleOtaCallEnd() {
        if (DBG) log("handleOtaCallEnd entering");
        if (((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL)
                || ((mApp.cdmaOtaScreenState != null)
                && (mApp.cdmaOtaScreenState.otaScreenState !=
                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED)))
                && ((mApp.cdmaOtaProvisionData != null)
                && (!mApp.cdmaOtaProvisionData.inOtaSpcState))) {
            if (DBG) log("handleOtaCallEnd - Set OTA Call End stater");
            setInCallScreenMode(InCallScreenMode.OTA_ENDED);
            updateScreen();
        }
    }

    public boolean isOtaCallInEndState() {
        return (mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED);
    }


    /**
     * Upon resuming the in-call UI, check to see if an OTASP call is in
     * progress, and if so enable the special OTASP-specific UI.
     *
     * TODO: have a simple single flag in InCallUiState for this rather than
     * needing to know about all those mApp.cdma*State objects.
     *
     * @return true if any OTASP-related UI is active
     */
    private boolean checkOtaspStateOnResume() {
        // If there's no OtaUtils instance, that means we haven't even tried
        // to start an OTASP call (yet), so there's definitely nothing to do here.
        if (mApp.otaUtils == null) {
            if (DBG) log("checkOtaspStateOnResume: no OtaUtils instance; nothing to do.");
            return false;
        }

        if ((mApp.cdmaOtaScreenState == null) || (mApp.cdmaOtaProvisionData == null)) {
            // Uh oh -- something wrong with our internal OTASP state.
            // (Since this is an OTASP-capable device, these objects
            // *should* have already been created by PhoneApp.onCreate().)
            throw new IllegalStateException("checkOtaspStateOnResume: "
                                            + "app.cdmaOta* objects(s) not initialized");
        }

        // The PhoneApp.cdmaOtaInCallScreenUiState instance is the
        // authoritative source saying whether or not the in-call UI should
        // show its OTASP-related UI.

        OtaUtils.CdmaOtaInCallScreenUiState.State cdmaOtaInCallScreenState =
                mApp.otaUtils.getCdmaOtaInCallScreenUiState();
        // These states are:
        // - UNDEFINED: no OTASP-related UI is visible
        // - NORMAL: OTASP call in progress, so show in-progress OTASP UI
        // - ENDED: OTASP call just ended, so show success/failure indication

        boolean otaspUiActive =
                (cdmaOtaInCallScreenState == OtaUtils.CdmaOtaInCallScreenUiState.State.NORMAL)
                || (cdmaOtaInCallScreenState == OtaUtils.CdmaOtaInCallScreenUiState.State.ENDED);

        if (otaspUiActive) {
            // Make sure the OtaUtils instance knows about the InCallScreen's
            // OTASP-related UI widgets.
            //
            // (This call has no effect if the UI widgets have already been set up.
            // It only really matters  the very first time that the InCallScreen instance
            // is onResume()d after starting an OTASP call.)
            mApp.otaUtils.updateUiWidgets(this, mInCallTouchUi, mCallCard);

            // Also update the InCallScreenMode based on the cdmaOtaInCallScreenState.

            if (cdmaOtaInCallScreenState == OtaUtils.CdmaOtaInCallScreenUiState.State.NORMAL) {
                if (DBG) log("checkOtaspStateOnResume - in OTA Normal mode");
                setInCallScreenMode(InCallScreenMode.OTA_NORMAL);
            } else if (cdmaOtaInCallScreenState ==
                       OtaUtils.CdmaOtaInCallScreenUiState.State.ENDED) {
                if (DBG) log("checkOtaspStateOnResume - in OTA END mode");
                setInCallScreenMode(InCallScreenMode.OTA_ENDED);
            }

            // TODO(OTASP): we might also need to go into OTA_ENDED mode
            // in one extra case:
            //
            // else if (mApp.cdmaOtaScreenState.otaScreenState ==
            //            CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG) {
            //     if (DBG) log("checkOtaspStateOnResume - set OTA END Mode");
            //     setInCallScreenMode(InCallScreenMode.OTA_ENDED);
            // }

        } else {
            // OTASP is not active; reset to regular in-call UI.

            if (DBG) log("checkOtaspStateOnResume - Set OTA NORMAL Mode");
            setInCallScreenMode(InCallScreenMode.OTA_NORMAL);

            if (mApp.otaUtils != null) {
                mApp.otaUtils.cleanOtaScreen(false);
            }
        }

        // TODO(OTASP):
        // The original check from checkIsOtaCall() when handling ACTION_MAIN was this:
        //
        //        [ . . . ]
        //        else if (action.equals(intent.ACTION_MAIN)) {
        //            if (DBG) log("checkIsOtaCall action ACTION_MAIN");
        //            boolean isRingingCall = mCM.hasActiveRingingCall();
        //            if (isRingingCall) {
        //                if (DBG) log("checkIsOtaCall isRingingCall: " + isRingingCall);
        //                return false;
        //            } else if ((mApp.cdmaOtaInCallScreenUiState.state
        //                            == CdmaOtaInCallScreenUiState.State.NORMAL)
        //                    || (mApp.cdmaOtaInCallScreenUiState.state
        //                            == CdmaOtaInCallScreenUiState.State.ENDED)) {
        //                if (DBG) log("action ACTION_MAIN, OTA call already in progress");
        //                isOtaCall = true;
        //            } else {
        //                if (mApp.cdmaOtaScreenState.otaScreenState !=
        //                        CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED) {
        //                    if (DBG) log("checkIsOtaCall action ACTION_MAIN, "
        //                                 + "OTA call in progress with UNDEFINED");
        //                    isOtaCall = true;
        //                }
        //            }
        //        }
        //
        // Also, in internalResolveIntent() we used to do this:
        //
        //        if ((mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_NORMAL)
        //                || (mApp.inCallUiState.inCallScreenMode == InCallScreenMode.OTA_ENDED)) {
        //            // If in OTA Call, update the OTA UI
        //            updateScreen();
        //            return;
        //        }
        //
        // We still need more cleanup to simplify the mApp.cdma*State objects.

        return otaspUiActive;
    }

    /**
     * Updates and returns the InCallControlState instance.
     */
    public InCallControlState getUpdatedInCallControlState() {
        if (VDBG) log("getUpdatedInCallControlState()...");
        mInCallControlState.update();
        return mInCallControlState;
    }

    public void resetInCallScreenMode() {
        if (DBG) log("resetInCallScreenMode: setting mode to UNDEFINED...");
        setInCallScreenMode(InCallScreenMode.UNDEFINED);
    }

    /**
     * Updates the onscreen hint displayed while the user is dragging one
     * of the handles of the RotarySelector widget used for incoming
     * calls.
     *
     * @param hintTextResId resource ID of the hint text to display,
     *        or 0 if no hint should be visible.
     * @param hintColorResId resource ID for the color of the hint text
     */
    /* package */ void updateIncomingCallWidgetHint(int hintTextResId, int hintColorResId) {
        if (VDBG) log("updateIncomingCallWidgetHint(" + hintTextResId + ")...");
        if (mCallCard != null) {
            mCallCard.setIncomingCallWidgetHint(hintTextResId, hintColorResId);
            mCallCard.updateState(mCM);
            // TODO: if hintTextResId == 0, consider NOT clearing the onscreen
            // hint right away, but instead post a delayed handler message to
            // keep it onscreen for an extra second or two.  (This might make
            // the hint more helpful if the user quickly taps one of the
            // handles without dragging at all...)
            // (Or, maybe this should happen completely within the RotarySelector
            // widget, since the widget itself probably wants to keep the colored
            // arrow visible for some extra time also...)
        }
    }


    /**
     * Used when we need to update buttons outside InCallTouchUi's updateInCallControls() along
     * with that method being called. CallCard may call this too because it doesn't have
     * enough information to update buttons inside itself (more specifically, the class cannot
     * obtain mInCallControllState without some side effect. See also
     * {@link #getUpdatedInCallControlState()}. We probably don't want a method like
     * getRawCallControlState() which returns raw intance with no side effect just for this
     * corner case scenario)
     *
     * TODO: need better design for buttons outside InCallTouchUi.
     */
    /* package */ void updateButtonStateOutsideInCallTouchUi() {
        if (mCallCard != null) {
            mCallCard.setSecondaryCallClickable(mInCallControlState.canSwap);
        }
    }

    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        super.dispatchPopulateAccessibilityEvent(event);
        mCallCard.dispatchPopulateAccessibilityEvent(event);
        return true;
    }

    /**
     * Manually handle configuration changes.
     *
     * Originally android:configChanges was set to "orientation|keyboardHidden|uiMode"
     * in order "to make sure the system doesn't destroy and re-create us due to the
     * above config changes". However it is currently set to "keyboardHidden" since
     * the system needs to handle rotation when inserted into a compatible cardock.
     * Even without explicitly handling orientation and uiMode, the app still runs
     * and does not drop the call when rotated.
     *
     */
    public void onConfigurationChanged(Configuration newConfig) {
        if (DBG) log("onConfigurationChanged: newConfig = " + newConfig);

        // Note: At the time this function is called, our Resources object
        // will have already been updated to return resource values matching
        // the new configuration.

        // Watch out: we *can* still get destroyed and recreated if a
        // configuration change occurs that is *not* listed in the
        // android:configChanges attribute.  TODO: Any others we need to list?

        super.onConfigurationChanged(newConfig);

        // Nothing else to do here, since (currently) the InCallScreen looks
        // exactly the same regardless of configuration.
        // (Specifically, we'll never be in landscape mode because we set
        // android:screenOrientation="portrait" in our manifest, and we don't
        // change our UI at all based on newConfig.keyboardHidden or
        // newConfig.uiMode.)

        // TODO: we do eventually want to handle at least some config changes, such as:
        boolean isKeyboardOpen = (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO);
        if (DBG) log("  - isKeyboardOpen = " + isKeyboardOpen);
        boolean isLandscape = (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE);
        if (DBG) log("  - isLandscape = " + isLandscape);
        if (DBG) log("  - uiMode = " + newConfig.uiMode);
        // See bug 2089513.
    }

    /**
     * Handles an incoming RING event from the telephony layer.
     */
    private void onIncomingRing() {
        if (DBG) log("onIncomingRing()...");
        // IFF we're visible, forward this event to the InCallTouchUi
        // instance (which uses this event to drive the animation of the
        // incoming-call UI.)
        if (mIsForegroundActivity && (mInCallTouchUi != null)) {
            mInCallTouchUi.onIncomingRing();
        }
    }

    /**
     * Handles a "new ringing connection" event from the telephony layer.
     *
     * This event comes in right at the start of the incoming-call sequence,
     * exactly once per incoming call.
     *
     * Watch out: this won't be called if InCallScreen isn't ready yet,
     * which typically happens for the first incoming phone call (even before
     * the possible first outgoing call).
     */
    private void onNewRingingConnection() {
        if (DBG) log("onNewRingingConnection()...");

        // We use this event to reset any incoming-call-related UI elements
        // that might have been left in an inconsistent state after a prior
        // incoming call.
        // (Note we do this whether or not we're the foreground activity,
        // since this event comes in *before* we actually get launched to
        // display the incoming-call UI.)

        // If there's a "Respond via SMS" popup still around since the
        // last time we were the foreground activity, make sure it's not
        // still active(!) since that would interfere with *this* incoming
        // call.
        // (Note that we also do this same check in onResume().  But we
        // need it here too, to make sure the popup gets reset in the case
        // where a call-waiting call comes in while the InCallScreen is
        // already in the foreground.)
        mRespondViaSmsManager.dismissPopup();  // safe even if already dismissed
    }

    /**
     * Enables or disables the status bar "window shade" based on the current situation.
     */
    private void updateExpandedViewState() {
        if (mIsForegroundActivity) {
            if (mApp.proximitySensorModeEnabled()) {
                // We should not enable notification's expanded view on RINGING state.
                mApp.notificationMgr.statusBarHelper.enableExpandedView(
                        mCM.getState() != PhoneConstants.State.RINGING);
            } else {
                // If proximity sensor is unavailable on the device, disable it to avoid false
                // touches toward notifications.
                mApp.notificationMgr.statusBarHelper.enableExpandedView(false);
            }
        } else {
            mApp.notificationMgr.statusBarHelper.enableExpandedView(true);
        }
    }

    private void log(String msg) {
        Log.d(LOG_TAG, msg);
    }

    /**
     * Requests to remove provider info frame after having
     * {@link #PROVIDER_INFO_TIMEOUT}) msec delay.
     */
    /* package */ void requestRemoveProviderInfoWithDelay() {
        // Remove any zombie messages and then send a message to
        // self to remove the provider info after some time.
        mHandler.removeMessages(EVENT_HIDE_PROVIDER_INFO);
        Message msg = Message.obtain(mHandler, EVENT_HIDE_PROVIDER_INFO);
        mHandler.sendMessageDelayed(msg, PROVIDER_INFO_TIMEOUT);
        if (DBG) {
            log("Requested to remove provider info after " + PROVIDER_INFO_TIMEOUT + " msec.");
        }
    }

    /**
     * Indicates whether or not the QuickResponseDialog is currently showing in the call screen
     */
    public boolean isQuickResponseDialogShowing() {
        return mRespondViaSmsManager != null && mRespondViaSmsManager.isShowingPopup();
    }
}
