/*
 * Copyright (C) 2009 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 com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyCapabilities;
import com.android.internal.telephony.TelephonyProperties;
import com.android.phone.OtaUtils.CdmaOtaInCallScreenUiState.State;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.ToggleButton;

/**
 * Handles all OTASP Call related logic and UI functionality.
 * The InCallScreen interacts with this class to perform an OTASP Call.
 *
 * OTASP is a CDMA-specific feature:
 *   OTA or OTASP == Over The Air service provisioning
 *   SPC == Service Programming Code
 *   TODO: Include pointer to more detailed documentation.
 *
 * TODO: This is Over The Air Service Provisioning (OTASP)
 *       A better name would be OtaspUtils.java.
 */
public class OtaUtils {
    private static final String LOG_TAG = "OtaUtils";
    private static final boolean DBG = false;

    public static final int OTA_SHOW_ACTIVATION_SCREEN_OFF = 0;
    public static final int OTA_SHOW_ACTIVATION_SCREEN_ON = 1;
    public static final int OTA_SHOW_LISTENING_SCREEN_OFF =0;
    public static final int OTA_SHOW_LISTENING_SCREEN_ON =1;
    public static final int OTA_SHOW_ACTIVATE_FAIL_COUNT_OFF = 0;
    public static final int OTA_SHOW_ACTIVATE_FAIL_COUNT_THREE = 3;
    public static final int OTA_PLAY_SUCCESS_FAILURE_TONE_OFF = 0;
    public static final int OTA_PLAY_SUCCESS_FAILURE_TONE_ON = 1;

    // SPC Timeout is 60 seconds
    public final int OTA_SPC_TIMEOUT = 60;
    public final int OTA_FAILURE_DIALOG_TIMEOUT = 2;

    // Constants for OTASP-related Intents and intent extras.
    // Watch out: these must agree with the corresponding constants in
    // apps/SetupWizard!

    // Intent action to launch an OTASP call.
    public static final String ACTION_PERFORM_CDMA_PROVISIONING =
           "com.android.phone.PERFORM_CDMA_PROVISIONING";

    // Intent action to launch activation on a non-voice capable device
    public static final String ACTION_PERFORM_VOICELESS_CDMA_PROVISIONING =
            "com.android.phone.PERFORM_VOICELESS_CDMA_PROVISIONING";

    // Intent action to display the InCallScreen in the OTASP "activation" state.
    public static final String ACTION_DISPLAY_ACTIVATION_SCREEN =
            "com.android.phone.DISPLAY_ACTIVATION_SCREEN";

    // boolean voiceless provisioning extra that enables a "don't show this again" checkbox
    // the user can check to never see the activity upon bootup again
    public static final String EXTRA_VOICELESS_PROVISIONING_OFFER_DONTSHOW =
            "com.android.phone.VOICELESS_PROVISIONING_OFFER_DONTSHOW";

    // Activity result codes for the ACTION_PERFORM_CDMA_PROVISIONING intent
    // (see the InCallScreenShowActivation activity.)
    //
    // Note: currently, our caller won't ever actually receive the
    // RESULT_INTERACTIVE_OTASP_STARTED result code; see comments in
    // InCallScreenShowActivation.onCreate() for details.

    public static final int RESULT_INTERACTIVE_OTASP_STARTED = Activity.RESULT_FIRST_USER;
    public static final int RESULT_NONINTERACTIVE_OTASP_STARTED = Activity.RESULT_FIRST_USER + 1;
    public static final int RESULT_NONINTERACTIVE_OTASP_FAILED = Activity.RESULT_FIRST_USER + 2;

    // Testing: Extra for the ACTION_PERFORM_CDMA_PROVISIONING intent that
    // allows the caller to manually enable/disable "interactive mode" for
    // the OTASP call.   Only available in userdebug or eng builds.
    public static final String EXTRA_OVERRIDE_INTERACTIVE_MODE =
            "ota_override_interactive_mode";

    // Extra for the ACTION_PERFORM_CDMA_PROVISIONING intent, holding a
    // PendingIntent which the phone app can use to send a result code
    // back to the caller.
    public static final String EXTRA_OTASP_RESULT_CODE_PENDING_INTENT =
            "otasp_result_code_pending_intent";

    // Extra attached to the above PendingIntent that indicates
    // success or failure.
    public static final String EXTRA_OTASP_RESULT_CODE =
            "otasp_result_code";
    public static final int OTASP_UNKNOWN = 0;
    public static final int OTASP_USER_SKIPPED = 1;  // Only meaningful with interactive OTASP
    public static final int OTASP_SUCCESS = 2;
    public static final int OTASP_FAILURE = 3;
    // failed due to CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED
    public static final int OTASP_FAILURE_SPC_RETRIES = 4;
    // TODO: Distinguish between interactive and non-interactive success
    // and failure.  Then, have the PendingIntent be sent after
    // interactive OTASP as well (so the caller can find out definitively
    // when interactive OTASP completes.)

    private static final String OTASP_NUMBER = "*228";
    private static final String OTASP_NUMBER_NON_INTERACTIVE = "*22899";

    private InCallScreen mInCallScreen;
    private Context mContext;
    private PhoneGlobals mApplication;
    private OtaWidgetData mOtaWidgetData;
    private ViewGroup mInCallTouchUi;  // UI controls for regular calls
    private CallCard mCallCard;

    // The DTMFTwelveKeyDialer instance.   We create this in
    // initOtaInCallScreen(), and attach it to the DTMFTwelveKeyDialerView
    // ("otaDtmfDialerView") that comes from otacall_card.xml.
    private DTMFTwelveKeyDialer mOtaCallCardDtmfDialer;

    private static boolean sIsWizardMode = true;

    // How many times do we retry maybeDoOtaCall() if the LTE state is not known yet,
    // and how long do we wait between retries
    private static final int OTA_CALL_LTE_RETRIES_MAX = 5;
    private static final int OTA_CALL_LTE_RETRY_PERIOD = 3000;
    private static int sOtaCallLteRetries = 0;

    // In "interactive mode", the OtaUtils object is tied to an
    // InCallScreen instance, where we display a bunch of UI specific to
    // the OTASP call.  But on devices that are not "voice capable", the
    // OTASP call runs in a non-interactive mode, and we don't have
    // an InCallScreen or CallCard or any OTASP UI elements at all.
    private boolean mInteractive = true;


    /**
     * OtaWidgetData class represent all OTA UI elements
     *
     * TODO(OTASP): It's really ugly for the OtaUtils object to reach into the
     *     InCallScreen like this and directly manipulate its widgets.
     *
     *     Instead, the model/view separation should be more clear: OtaUtils
     *     should only know about a higher-level abstraction of the
     *     OTASP-specific UI state (just like how the CallController uses the
     *     InCallUiState object), and the InCallScreen itself should translate
     *     that higher-level abstraction into actual onscreen views and widgets.
     */
    private class OtaWidgetData {
        public Button otaEndButton;
        public Button otaActivateButton;
        public Button otaSkipButton;
        public Button otaNextButton;
        public ToggleButton otaSpeakerButton;
        public ViewGroup otaUpperWidgets;
        public View callCardOtaButtonsFailSuccess;
        public ProgressBar otaTextProgressBar;
        public TextView otaTextSuccessFail;
        public View callCardOtaButtonsActivate;
        public View callCardOtaButtonsListenProgress;
        public TextView otaTextActivate;
        public TextView otaTextListenProgress;
        public AlertDialog spcErrorDialog;
        public AlertDialog otaFailureDialog;
        public AlertDialog otaSkipConfirmationDialog;
        public TextView otaTitle;
        public DTMFTwelveKeyDialerView otaDtmfDialerView;
        public Button otaTryAgainButton;
    }

    /**
     * OtaUtils constructor.
     *
     * @param context the Context of the calling Activity or Application
     * @param interactive if true, use the InCallScreen to display the progress
     *                    and result of the OTASP call.  In practice this is
     *                    true IFF the current device is a voice-capable phone.
     *
     * Note if interactive is true, you must also call updateUiWidgets() as soon
     * as the InCallScreen instance is ready.
     */
    public OtaUtils(Context context, boolean interactive) {
        if (DBG) log("OtaUtils constructor...");
        mApplication = PhoneGlobals.getInstance();
        mContext = context;
        mInteractive = interactive;
    }

    /**
     * Updates the OtaUtils object's references to some UI elements belonging to
     * the InCallScreen.  This is used only in interactive mode.
     *
     * Use clearUiWidgets() to clear out these references.  (The InCallScreen
     * is responsible for doing this from its onDestroy() method.)
     *
     * This method has no effect if the UI widgets have already been set up.
     * (In other words, it's safe to call this every time through
     * InCallScreen.onResume().)
     */
    public void updateUiWidgets(InCallScreen inCallScreen,
            ViewGroup inCallTouchUi, CallCard callCard) {
        if (DBG) log("updateUiWidgets()...  mInCallScreen = " + mInCallScreen);

        if (!mInteractive) {
            throw new IllegalStateException("updateUiWidgets() called in non-interactive mode");
        }

        if (mInCallScreen != null) {
            if (DBG) log("updateUiWidgets(): widgets already set up, nothing to do...");
            return;
        }

        mInCallScreen = inCallScreen;
        mInCallTouchUi = inCallTouchUi;
        mCallCard = callCard;
        mOtaWidgetData = new OtaWidgetData();

        // Inflate OTASP-specific UI elements:
        ViewStub otaCallCardStub = (ViewStub) mInCallScreen.findViewById(R.id.otaCallCardStub);
        if (otaCallCardStub != null) {
            // If otaCallCardStub is null here, that means it's already been
            // inflated (which could have happened in the current InCallScreen
            // instance for a *prior* OTASP call.)
            otaCallCardStub.inflate();
        }

        readXmlSettings();
        initOtaInCallScreen();
    }

    /**
     * Clear out the OtaUtils object's references to any InCallScreen UI
     * elements.  This is the opposite of updateUiWidgets().
     */
    public void clearUiWidgets() {
        mInCallScreen = null;
        mInCallTouchUi = null;
        mCallCard = null;
        mOtaWidgetData = null;
    }

    /**
     * Starts the OTA provisioning call.  If the MIN isn't available yet, it returns false and adds
     * an event to return the request to the calling app when it becomes available.
     *
     * @param context
     * @param handler
     * @param request
     * @return true if we were able to launch Ota activity or it's not required; false otherwise
     */
    public static boolean maybeDoOtaCall(Context context, Handler handler, int request) {
        PhoneGlobals app = PhoneGlobals.getInstance();
        Phone phone = app.phone;

        if (ActivityManager.isRunningInTestHarness()) {
            Log.i(LOG_TAG, "Don't run provisioning when in test harness");
            return true;
        }

        if (!TelephonyCapabilities.supportsOtasp(phone)) {
            // Presumably not a CDMA phone.
            if (DBG) log("maybeDoOtaCall: OTASP not supported on this device");
            return true;  // Nothing to do here.
        }

        if (!phone.isMinInfoReady()) {
            if (DBG) log("MIN is not ready. Registering to receive notification.");
            phone.registerForSubscriptionInfoReady(handler, request, null);
            return false;
        }
        phone.unregisterForSubscriptionInfoReady(handler);

        if (getLteOnCdmaMode(context) == PhoneConstants.LTE_ON_CDMA_UNKNOWN) {
            if (sOtaCallLteRetries < OTA_CALL_LTE_RETRIES_MAX) {
                if (DBG) log("maybeDoOtaCall: LTE state still unknown: retrying");
                handler.sendEmptyMessageDelayed(request, OTA_CALL_LTE_RETRY_PERIOD);
                sOtaCallLteRetries++;
                return false;
            } else {
                Log.w(LOG_TAG, "maybeDoOtaCall: LTE state still unknown: giving up");
                return true;
            }
        }

        boolean phoneNeedsActivation = phone.needsOtaServiceProvisioning();
        if (DBG) log("phoneNeedsActivation is set to " + phoneNeedsActivation);

        int otaShowActivationScreen = context.getResources().getInteger(
                R.integer.OtaShowActivationScreen);
        if (DBG) log("otaShowActivationScreen: " + otaShowActivationScreen);

        // Run the OTASP call in "interactive" mode only if
        // this is a non-LTE "voice capable" device.
        if (PhoneGlobals.sVoiceCapable && getLteOnCdmaMode(context) == PhoneConstants.LTE_ON_CDMA_FALSE) {
            if (phoneNeedsActivation
                    && (otaShowActivationScreen == OTA_SHOW_ACTIVATION_SCREEN_ON)) {
                app.cdmaOtaProvisionData.isOtaCallIntentProcessed = false;
                sIsWizardMode = false;

                if (DBG) Log.d(LOG_TAG, "==> Starting interactive CDMA provisioning...");
                OtaUtils.startInteractiveOtasp(context);

                if (DBG) log("maybeDoOtaCall: voice capable; activation started.");
            } else {
                if (DBG) log("maybeDoOtaCall: voice capable; activation NOT started.");
            }
        } else {
            if (phoneNeedsActivation) {
                app.cdmaOtaProvisionData.isOtaCallIntentProcessed = false;
                Intent newIntent = new Intent(ACTION_PERFORM_VOICELESS_CDMA_PROVISIONING);
                newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                newIntent.putExtra(EXTRA_VOICELESS_PROVISIONING_OFFER_DONTSHOW, true);
                try {
                    context.startActivity(newIntent);
                } catch (ActivityNotFoundException e) {
                    loge("No activity Handling PERFORM_VOICELESS_CDMA_PROVISIONING!");
                    return false;
                }
                if (DBG) log("maybeDoOtaCall: non-interactive; activation intent sent.");
            } else {
                if (DBG) log("maybeDoOtaCall: non-interactive, no need for OTASP.");
            }
        }
        return true;
    }

    /**
     * Starts a normal "interactive" OTASP call (i.e. CDMA activation
     * for regular voice-capable phone devices.)
     *
     * This method is called from the InCallScreenShowActivation activity when
     * handling the ACTION_PERFORM_CDMA_PROVISIONING intent.
     */
    public static void startInteractiveOtasp(Context context) {
        if (DBG) log("startInteractiveOtasp()...");
        PhoneGlobals app = PhoneGlobals.getInstance();

        // There are two ways to start OTASP on voice-capable devices:
        //
        // (1) via the PERFORM_CDMA_PROVISIONING intent
        //     - this is triggered by the "Activate device" button in settings,
        //       or can be launched automatically upon boot if the device
        //       thinks it needs to be provisioned.
        //     - the intent is handled by InCallScreenShowActivation.onCreate(),
        //       which calls this method
        //     - we prepare for OTASP by initializing the OtaUtils object
        //     - we bring up the InCallScreen in the ready-to-activate state
        //     - when the user presses the "Activate" button we launch the
        //       call by calling CallController.placeCall() via the
        //       otaPerformActivation() method.
        //
        // (2) by manually making an outgoing call to a special OTASP number
        //     like "*228" or "*22899".
        //     - That sequence does NOT involve this method (OtaUtils.startInteractiveOtasp()).
        //       Instead, the outgoing call request goes straight to CallController.placeCall().
        //     - CallController.placeCall() notices that it's an OTASP
        //       call, and initializes the OtaUtils object.
        //     - The InCallScreen is launched (as the last step of
        //       CallController.placeCall()).  The InCallScreen notices that
        //       OTASP is active and shows the correct UI.

        // Here, we start sequence (1):
        // Do NOT immediately start the call.  Instead, bring up the InCallScreen
        // in the special "activate" state (see OtaUtils.otaShowActivateScreen()).
        // We won't actually make the call until the user presses the "Activate"
        // button.

        Intent activationScreenIntent = new Intent().setClass(context, InCallScreen.class)
                .setAction(ACTION_DISPLAY_ACTIVATION_SCREEN);

        // Watch out: in the scenario where OTASP gets triggered from the
        // BOOT_COMPLETED broadcast (see OtaStartupReceiver.java), we might be
        // running in the PhoneApp's context right now.
        // So the FLAG_ACTIVITY_NEW_TASK flag is required here.
        activationScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        // We're about to start the OTASP sequence, so create and initialize the
        // OtaUtils instance.  (This needs to happen before bringing up the
        // InCallScreen.)
        OtaUtils.setupOtaspCall(activationScreenIntent);

        // And bring up the InCallScreen...
        Log.i(LOG_TAG, "startInteractiveOtasp: launching InCallScreen in 'activate' state: "
              + activationScreenIntent);
        context.startActivity(activationScreenIntent);
    }

    /**
     * Starts the OTASP call *without* involving the InCallScreen or
     * displaying any UI.
     *
     * This is used on data-only devices, which don't support any kind of
     * in-call phone UI.
     *
     * @return PhoneUtils.CALL_STATUS_DIALED if we successfully
     *         dialed the OTASP number, or one of the other
     *         CALL_STATUS_* constants if there was a failure.
     */
    public static int startNonInteractiveOtasp(Context context) {
        if (DBG) log("startNonInteractiveOtasp()...");
        PhoneGlobals app = PhoneGlobals.getInstance();

        if (app.otaUtils != null) {
            // An OtaUtils instance already exists, presumably from a previous OTASP call.
            Log.i(LOG_TAG, "startNonInteractiveOtasp: "
                  + "OtaUtils already exists; nuking the old one and starting again...");
        }

        // Create the OtaUtils instance.
        app.otaUtils = new OtaUtils(context, false /* non-interactive mode */);
        if (DBG) log("- created OtaUtils: " + app.otaUtils);

        // ... and kick off the OTASP call.
        // TODO(InCallScreen redesign): This should probably go through
        // the CallController, rather than directly calling
        // PhoneUtils.placeCall().
        Phone phone = PhoneGlobals.getPhone();
        String number = OTASP_NUMBER_NON_INTERACTIVE;
        Log.i(LOG_TAG, "startNonInteractiveOtasp: placing call to '" + number + "'...");
        int callStatus = PhoneUtils.placeCall(context,
                                              phone,
                                              number,
                                              null,  // contactRef
                                              false,  //isEmergencyCall
                                              null);  // gatewayUri

        if (callStatus == PhoneUtils.CALL_STATUS_DIALED) {
            if (DBG) log("  ==> successful return from placeCall(): callStatus = " + callStatus);
        } else {
            Log.w(LOG_TAG, "Failure from placeCall() for OTA number '"
                  + number + "': code " + callStatus);
            return callStatus;
        }

        // TODO: Any other special work to do here?
        // Such as:
        //
        // - manually kick off progress updates, either using TelephonyRegistry
        //   or else by sending PendingIntents directly to our caller?
        //
        // - manually silence the in-call audio?  (Probably unnecessary
        //   if Stingray truly has no audio path from phone baseband
        //   to the device's speakers.)
        //

        return callStatus;
    }

    /**
     * @return true if the specified Intent is a CALL action that's an attempt
     * to initate an OTASP call.
     *
     * OTASP is a CDMA-specific concept, so this method will always return false
     * on GSM phones.
     *
     * This code was originally part of the InCallScreen.checkIsOtaCall() method.
     */
    public static boolean isOtaspCallIntent(Intent intent) {
        if (DBG) log("isOtaspCallIntent(" + intent + ")...");
        PhoneGlobals app = PhoneGlobals.getInstance();
        Phone phone = app.mCM.getDefaultPhone();

        if (intent == null) {
            return false;
        }
        if (!TelephonyCapabilities.supportsOtasp(phone)) {
            return false;
        }

        String action = intent.getAction();
        if (action == null) {
            return false;
        }
        if (!action.equals(Intent.ACTION_CALL)) {
            if (DBG) log("isOtaspCallIntent: not a CALL action: '" + action + "' ==> not OTASP");
            return false;
        }

        if ((app.cdmaOtaScreenState == null) || (app.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("isOtaspCallIntent: "
                                            + "app.cdmaOta* objects(s) not initialized");
        }

        // This is an OTASP call iff the number we're trying to dial is one of
        // the magic OTASP numbers.
        String number;
        try {
            number = PhoneUtils.getInitialNumber(intent);
        } catch (PhoneUtils.VoiceMailNumberMissingException ex) {
            // This was presumably a "voicemail:" intent, so it's
            // obviously not an OTASP number.
            if (DBG) log("isOtaspCallIntent: VoiceMailNumberMissingException => not OTASP");
            return false;
        }
        if (phone.isOtaSpNumber(number)) {
            if (DBG) log("isOtaSpNumber: ACTION_CALL to '" + number + "' ==> OTASP call!");
            return true;
        }
        return false;
    }

    /**
     * Set up for an OTASP call.
     *
     * This method is called as part of the CallController placeCall() sequence
     * before initiating an outgoing OTASP call.
     *
     * The purpose of this method is mainly to create and initialize the
     * OtaUtils instance, along with some other misc pre-OTASP cleanup.
     */
    public static void setupOtaspCall(Intent intent) {
        if (DBG) log("setupOtaspCall(): preparing for OTASP call to " + intent);
        PhoneGlobals app = PhoneGlobals.getInstance();

        if (app.otaUtils != null) {
            // An OtaUtils instance already exists, presumably from a prior OTASP call.
            // Nuke the old one and start this call with a fresh instance.
            Log.i(LOG_TAG, "setupOtaspCall: "
                  + "OtaUtils already exists; replacing with new instance...");
        }

        // Create the OtaUtils instance.
        app.otaUtils = new OtaUtils(app.getApplicationContext(), true /* interactive */);
        if (DBG) log("- created OtaUtils: " + app.otaUtils);

        // NOTE we still need to call OtaUtils.updateUiWidgets() once the
        // InCallScreen instance is ready; see InCallScreen.checkOtaspStateOnResume()

        // Make sure the InCallScreen knows that it needs to switch into OTASP mode.
        //
        // NOTE in gingerbread and earlier, we used to do
        //     setInCallScreenMode(InCallScreenMode.OTA_NORMAL);
        // directly in the InCallScreen, back when this check happened inside the InCallScreen.
        //
        // But now, set the global CdmaOtaInCallScreenUiState object into
        // NORMAL mode, which will then cause the InCallScreen (when it
        // comes up) to realize that an OTA call is active.

        app.otaUtils.setCdmaOtaInCallScreenUiState(
            OtaUtils.CdmaOtaInCallScreenUiState.State.NORMAL);

        // TODO(OTASP): note app.inCallUiState.inCallScreenMode and
        // app.cdmaOtaInCallScreenUiState.state are mostly redundant.  Combine them.
        app.inCallUiState.inCallScreenMode = InCallUiState.InCallScreenMode.OTA_NORMAL;

        // TODO(OTASP / bug 5092031): we ideally should call
        // otaShowListeningScreen() here to make sure that the DTMF dialpad
        // becomes visible at the start of the "*228" call:
        //
        //  // ...and get the OTASP-specific UI into the right state.
        //  app.otaUtils.otaShowListeningScreen();
        //  if (app.otaUtils.mInCallScreen != null) {
        //      app.otaUtils.mInCallScreen.requestUpdateScreen();
        //  }
        //
        // But this doesn't actually work; the call to otaShowListeningScreen()
        // *doesn't* actually bring up the listening screen, since the
        // cdmaOtaConfigData.otaShowListeningScreen config parameter hasn't been
        // initialized (we haven't run readXmlSettings() yet at this point!)

        // Also, since the OTA call is now just starting, clear out
        // the "committed" flag in app.cdmaOtaProvisionData.
        if (app.cdmaOtaProvisionData != null) {
            app.cdmaOtaProvisionData.isOtaCallCommitted = false;
        }
    }

    private void setSpeaker(boolean state) {
        if (DBG) log("setSpeaker : " + state );

        if (!mInteractive) {
            if (DBG) log("non-interactive mode, ignoring setSpeaker.");
            return;
        }

        if (state == PhoneUtils.isSpeakerOn(mContext)) {
            if (DBG) log("no change. returning");
            return;
        }

        if (state && mInCallScreen.isBluetoothAvailable()
                && mInCallScreen.isBluetoothAudioConnected()) {
            mInCallScreen.disconnectBluetoothAudio();
        }
        PhoneUtils.turnOnSpeaker(mContext, state, true);
    }

    /**
     * Handles OTA Provision events from the telephony layer.
     * These events come in to this method whether or not
     * the InCallScreen is visible.
     *
     * Possible events are:
     * OTA Commit Event - OTA provisioning was successful
     * SPC retries exceeded - SPC failure retries has exceeded, and Phone needs to
     *    power down.
     */
    public void onOtaProvisionStatusChanged(AsyncResult r) {
        int OtaStatus[] = (int[]) r.result;
        if (DBG) log("Provision status event!");
        if (DBG) log("onOtaProvisionStatusChanged(): status = "
                     + OtaStatus[0] + " ==> " + otaProvisionStatusToString(OtaStatus[0]));

        // In practice, in a normal successful OTASP call, events come in as follows:
        //   - SPL_UNLOCKED within a couple of seconds after the call starts
        //   - then a delay of around 45 seconds
        //   - then PRL_DOWNLOADED and MDN_DOWNLOADED and COMMITTED within a span of 2 seconds

        switch(OtaStatus[0]) {
            case Phone.CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED:
                if (DBG) log("onOtaProvisionStatusChanged(): RETRIES EXCEEDED");
                updateOtaspProgress();
                mApplication.cdmaOtaProvisionData.otaSpcUptime = SystemClock.elapsedRealtime();
                if (mInteractive) {
                    otaShowSpcErrorNotice(OTA_SPC_TIMEOUT);
                } else {
                    sendOtaspResult(OTASP_FAILURE_SPC_RETRIES);
                }
                // Power.shutdown();
                break;

            case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
                if (DBG) {
                    log("onOtaProvisionStatusChanged(): DONE, isOtaCallCommitted set to true");
                }
                mApplication.cdmaOtaProvisionData.isOtaCallCommitted = true;
                if (mApplication.cdmaOtaScreenState.otaScreenState !=
                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED) {
                    updateOtaspProgress();
                }

                break;

            case Phone.CDMA_OTA_PROVISION_STATUS_SPL_UNLOCKED:
            case Phone.CDMA_OTA_PROVISION_STATUS_A_KEY_EXCHANGED:
            case Phone.CDMA_OTA_PROVISION_STATUS_SSD_UPDATED:
            case Phone.CDMA_OTA_PROVISION_STATUS_NAM_DOWNLOADED:
            case Phone.CDMA_OTA_PROVISION_STATUS_MDN_DOWNLOADED:
            case Phone.CDMA_OTA_PROVISION_STATUS_IMSI_DOWNLOADED:
            case Phone.CDMA_OTA_PROVISION_STATUS_PRL_DOWNLOADED:
            case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STARTED:
            case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED:
            case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_ABORTED:
                // Only update progress when OTA call is in normal state
                if (getCdmaOtaInCallScreenUiState() == CdmaOtaInCallScreenUiState.State.NORMAL) {
                    if (DBG) log("onOtaProvisionStatusChanged(): change to ProgressScreen");
                    updateOtaspProgress();
                }
                break;

            default:
                if (DBG) log("onOtaProvisionStatusChanged(): Ignoring OtaStatus " + OtaStatus[0]);
                break;
        }
    }

    /**
     * Handle a disconnect event from the OTASP call.
     */
    public void onOtaspDisconnect() {
        if (DBG) log("onOtaspDisconnect()...");
        // We only handle this event explicitly in non-interactive mode.
        // (In interactive mode, the InCallScreen does any post-disconnect
        // cleanup.)
        if (!mInteractive) {
            // Send a success or failure indication back to our caller.
            updateNonInteractiveOtaSuccessFailure();
        }
    }

    private void otaShowHome() {
        if (DBG) log("otaShowHome()...");
        mApplication.cdmaOtaScreenState.otaScreenState =
                CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
        mInCallScreen.endInCallScreenSession();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory (Intent.CATEGORY_HOME);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
        return;
    }

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

        sendOtaspResult(OTASP_USER_SKIPPED);

        if (mInteractive) mInCallScreen.finish();
        return;
    }

    /**
     * Actually initiate the OTASP call.  This method is triggered by the
     * onscreen "Activate" button, and is only used in interactive mode.
     */
    private void otaPerformActivation() {
        if (DBG) log("otaPerformActivation()...");
        if (!mInteractive) {
            // We shouldn't ever get here in non-interactive mode!
            Log.w(LOG_TAG, "otaPerformActivation: not interactive!");
            return;
        }

        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
            // Place an outgoing call to the special OTASP number:
            Intent newIntent = new Intent(Intent.ACTION_CALL);
            newIntent.setData(Uri.fromParts(Constants.SCHEME_TEL, OTASP_NUMBER, null));

            // Initiate the outgoing call:
            mApplication.callController.placeCall(newIntent);

            // ...and get the OTASP-specific UI into the right state.
            otaShowListeningScreen();
            mInCallScreen.requestUpdateScreen();
        }
        return;
    }

    /**
     * Show Activation Screen when phone powers up and OTA provision is
     * required. Also shown when activation fails and user needs
     * to re-attempt it. Contains ACTIVATE and SKIP buttons
     * which allow user to start OTA activation or skip the activation process.
     */
    public void otaShowActivateScreen() {
        if (DBG) log("otaShowActivateScreen()...");
        if (mApplication.cdmaOtaConfigData.otaShowActivationScreen
                == OTA_SHOW_ACTIVATION_SCREEN_ON) {
            if (DBG) log("otaShowActivateScreen(): show activation screen");
            if (!isDialerOpened()) {
                otaScreenInitialize();
                mOtaWidgetData.otaSkipButton.setVisibility(sIsWizardMode ?
                        View.VISIBLE : View.INVISIBLE);
                mOtaWidgetData.otaTextActivate.setVisibility(View.VISIBLE);
                mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.VISIBLE);
            }
            mApplication.cdmaOtaScreenState.otaScreenState =
                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION;
        } else {
            if (DBG) log("otaShowActivateScreen(): show home screen");
            otaShowHome();
        }
     }

    /**
     * Show "Listen for Instruction" screen during OTA call. Shown when OTA Call
     * is initiated and user needs to listen for network instructions and press
     * appropriate DTMF digits to proceed to the "Programming in Progress" phase.
     */
    private void otaShowListeningScreen() {
        if (DBG) log("otaShowListeningScreen()...");
        if (!mInteractive) {
            // We shouldn't ever get here in non-interactive mode!
            Log.w(LOG_TAG, "otaShowListeningScreen: not interactive!");
            return;
        }

        if (mApplication.cdmaOtaConfigData.otaShowListeningScreen
                == OTA_SHOW_LISTENING_SCREEN_ON) {
            if (DBG) log("otaShowListeningScreen(): show listening screen");
            if (!isDialerOpened()) {
                otaScreenInitialize();
                mOtaWidgetData.otaTextListenProgress.setVisibility(View.VISIBLE);
                mOtaWidgetData.otaTextListenProgress.setText(R.string.ota_listen);
                mOtaWidgetData.otaDtmfDialerView.setVisibility(View.VISIBLE);
                mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.VISIBLE);
                mOtaWidgetData.otaSpeakerButton.setVisibility(View.VISIBLE);
                boolean speakerOn = PhoneUtils.isSpeakerOn(mContext);
                mOtaWidgetData.otaSpeakerButton.setChecked(speakerOn);
            }
            mApplication.cdmaOtaScreenState.otaScreenState =
                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING;
        } else {
            if (DBG) log("otaShowListeningScreen(): show progress screen");
            otaShowInProgressScreen();
        }
    }

    /**
     * Do any necessary updates (of onscreen UI, for example)
     * based on the latest status of the OTASP call.
     */
    private void updateOtaspProgress() {
        if (DBG) log("updateOtaspProgress()...  mInteractive = " + mInteractive);
        if (mInteractive) {
            // On regular phones we just call through to
            // otaShowInProgressScreen(), which updates the
            // InCallScreen's onscreen UI.
            otaShowInProgressScreen();
        } else {
            // We're not using the InCallScreen to show OTA progress.

            // For now, at least, there's nothing to do here.
            // The overall "success" or "failure" indication we send back
            // (to our caller) is triggered by the DISCONNECT event;
            // see updateNonInteractiveOtaSuccessFailure().

            // But if we ever need to send *intermediate* progress updates back
            // to our caller, we'd do that here, possbily using the same
            // PendingIntent that we already use to indicate success or failure.
        }
    }

    /**
     * When a non-interactive OTASP call completes, send a success or
     * failure indication back to our caller.
     *
     * This is basically the non-interactive equivalent of
     * otaShowSuccessFailure().
     */
    private void updateNonInteractiveOtaSuccessFailure() {
        // This is basically the same logic as otaShowSuccessFailure(): we
        // check the isOtaCallCommitted bit, and if that's true it means
        // that activation was successful.

        if (DBG) log("updateNonInteractiveOtaSuccessFailure(): isOtaCallCommitted = "
                     + mApplication.cdmaOtaProvisionData.isOtaCallCommitted);
        int resultCode =
                mApplication.cdmaOtaProvisionData.isOtaCallCommitted
                ? OTASP_SUCCESS : OTASP_FAILURE;
        sendOtaspResult(resultCode);
    }

    /**
     * Sends the specified OTASP result code back to our caller (presumably
     * SetupWizard) via the PendingIntent that they originally sent along with
     * the ACTION_PERFORM_CDMA_PROVISIONING intent.
     */
    private void sendOtaspResult(int resultCode) {
        if (DBG) log("sendOtaspResult: resultCode = " + resultCode);

        // Pass the success or failure indication back to our caller by
        // adding an additional extra to the PendingIntent we already
        // have.
        // (NB: there's a PendingIntent send() method that takes a resultCode
        // directly, but we can't use that here since that call is only
        // meaningful for pending intents that are actually used as activity
        // results.)

        Intent extraStuff = new Intent();
        extraStuff.putExtra(EXTRA_OTASP_RESULT_CODE, resultCode);
        // When we call PendingIntent.send() below, the extras from this
        // intent will get merged with any extras already present in
        // cdmaOtaScreenState.otaspResultCodePendingIntent.

        if (mApplication.cdmaOtaScreenState == null) {
            Log.e(LOG_TAG, "updateNonInteractiveOtaSuccessFailure: no cdmaOtaScreenState object!");
            return;
        }
        if (mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent == null) {
            Log.w(LOG_TAG, "updateNonInteractiveOtaSuccessFailure: "
                  + "null otaspResultCodePendingIntent!");
            return;
        }

        try {
            if (DBG) log("- sendOtaspResult:  SENDING PENDING INTENT: " +
                         mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent);
            mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent.send(
                    mContext,
                    0, /* resultCode (unused) */
                    extraStuff);
        } catch (CanceledException e) {
            // should never happen because no code cancels the pending intent right now,
            Log.e(LOG_TAG, "PendingIntent send() failed: " + e);
        }
    }

    /**
     * Show "Programming In Progress" screen during OTA call. Shown when OTA
     * provisioning is in progress after user has selected an option.
     */
    private void otaShowInProgressScreen() {
        if (DBG) log("otaShowInProgressScreen()...");
        if (!mInteractive) {
            // We shouldn't ever get here in non-interactive mode!
            Log.w(LOG_TAG, "otaShowInProgressScreen: not interactive!");
            return;
        }

        mApplication.cdmaOtaScreenState.otaScreenState =
            CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS;

        if ((mOtaWidgetData == null) || (mInCallScreen == null)) {
            Log.w(LOG_TAG, "otaShowInProgressScreen: UI widgets not set up yet!");

            // TODO(OTASP): our CdmaOtaScreenState is now correct; we just set
            // it to OTA_STATUS_PROGRESS.  But we still need to make sure that
            // when the InCallScreen eventually comes to the foreground, it
            // notices that state and does all the same UI updating we do below.
            return;
        }

        if (!isDialerOpened()) {
            otaScreenInitialize();
            mOtaWidgetData.otaTextListenProgress.setVisibility(View.VISIBLE);
            mOtaWidgetData.otaTextListenProgress.setText(R.string.ota_progress);
            mOtaWidgetData.otaTextProgressBar.setVisibility(View.VISIBLE);
            mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.VISIBLE);
            mOtaWidgetData.otaSpeakerButton.setVisibility(View.VISIBLE);
            boolean speakerOn = PhoneUtils.isSpeakerOn(mContext);
            mOtaWidgetData.otaSpeakerButton.setChecked(speakerOn);
        }
    }

    /**
     * Show programming failure dialog when OTA provisioning fails.
     * If OTA provisioning attempts fail more than 3 times, then unsuccessful
     * dialog is shown. Otherwise a two-second notice is shown with unsuccessful
     * information. When notice expires, phone returns to activation screen.
     */
    private void otaShowProgramFailure(int length) {
        if (DBG) log("otaShowProgramFailure()...");
        mApplication.cdmaOtaProvisionData.activationCount++;
        if ((mApplication.cdmaOtaProvisionData.activationCount <
                mApplication.cdmaOtaConfigData.otaShowActivateFailTimes)
                && (mApplication.cdmaOtaConfigData.otaShowActivationScreen ==
                OTA_SHOW_ACTIVATION_SCREEN_ON)) {
            if (DBG) log("otaShowProgramFailure(): activationCount"
                    + mApplication.cdmaOtaProvisionData.activationCount);
            if (DBG) log("otaShowProgramFailure(): show failure notice");
            otaShowProgramFailureNotice(length);
        } else {
            if (DBG) log("otaShowProgramFailure(): show failure dialog");
            otaShowProgramFailureDialog();
        }
    }

    /**
     * Show either programming success dialog when OTA provisioning succeeds, or
     * programming failure dialog when it fails. See {@link #otaShowProgramFailure}
     * for more details.
     */
    public void otaShowSuccessFailure() {
        if (DBG) log("otaShowSuccessFailure()...");
        if (!mInteractive) {
            // We shouldn't ever get here in non-interactive mode!
            Log.w(LOG_TAG, "otaShowSuccessFailure: not interactive!");
            return;
        }

        otaScreenInitialize();
        if (DBG) log("otaShowSuccessFailure(): isOtaCallCommitted"
                + mApplication.cdmaOtaProvisionData.isOtaCallCommitted);
        if (mApplication.cdmaOtaProvisionData.isOtaCallCommitted) {
            if (DBG) log("otaShowSuccessFailure(), show success dialog");
            otaShowProgramSuccessDialog();
        } else {
            if (DBG) log("otaShowSuccessFailure(), show failure dialog");
            otaShowProgramFailure(OTA_FAILURE_DIALOG_TIMEOUT);
        }
        return;
    }

    /**
     * Show programming failure dialog when OTA provisioning fails more than 3
     * times.
     */
    private void otaShowProgramFailureDialog() {
        if (DBG) log("otaShowProgramFailureDialog()...");
        mApplication.cdmaOtaScreenState.otaScreenState =
                CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG;
        mOtaWidgetData.otaTitle.setText(R.string.ota_title_problem_with_activation);
        mOtaWidgetData.otaTextSuccessFail.setVisibility(View.VISIBLE);
        mOtaWidgetData.otaTextSuccessFail.setText(R.string.ota_unsuccessful);
        mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.VISIBLE);
        mOtaWidgetData.otaTryAgainButton.setVisibility(View.VISIBLE);
        //close the dialer if open
        if (isDialerOpened()) {
            mOtaCallCardDtmfDialer.closeDialer(false);
        }
    }

    /**
     * Show programming success dialog when OTA provisioning succeeds.
     */
    private void otaShowProgramSuccessDialog() {
        if (DBG) log("otaShowProgramSuccessDialog()...");
        mApplication.cdmaOtaScreenState.otaScreenState =
                CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG;
        mOtaWidgetData.otaTitle.setText(R.string.ota_title_activate_success);
        mOtaWidgetData.otaTextSuccessFail.setVisibility(View.VISIBLE);
        mOtaWidgetData.otaTextSuccessFail.setText(R.string.ota_successful);
        mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.VISIBLE);
        mOtaWidgetData.otaNextButton.setVisibility(View.VISIBLE);
        //close the dialer if open
        if (isDialerOpened()) {
            mOtaCallCardDtmfDialer.closeDialer(false);
        }
    }

    /**
     * Show SPC failure notice when SPC attempts exceed 15 times.
     * During OTA provisioning, if SPC code is incorrect OTA provisioning will
     * fail. When SPC attempts are over 15, it shows SPC failure notice for one minute and
     * then phone will power down.
     */
    private void otaShowSpcErrorNotice(int length) {
        if (DBG) log("otaShowSpcErrorNotice()...");
        if (mOtaWidgetData.spcErrorDialog == null) {
            mApplication.cdmaOtaProvisionData.inOtaSpcState = true;
            DialogInterface.OnKeyListener keyListener;
            keyListener = new DialogInterface.OnKeyListener() {
                public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                    log("Ignoring key events...");
                    return true;
                }};
            mOtaWidgetData.spcErrorDialog = new AlertDialog.Builder(mInCallScreen)
                    .setMessage(R.string.ota_spc_failure)
                    .setOnKeyListener(keyListener)
                    .create();
            mOtaWidgetData.spcErrorDialog.getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            mOtaWidgetData.spcErrorDialog.show();
            //close the dialer if open
            if (isDialerOpened()) {
                mOtaCallCardDtmfDialer.closeDialer(false);
            }
            long noticeTime = length*1000;
            if (DBG) log("otaShowSpcErrorNotice(), remaining SPC noticeTime" + noticeTime);
            mInCallScreen.requestCloseSpcErrorNotice(noticeTime);
        }
    }

    /**
     * When SPC notice times out, force phone to power down.
     */
    public void onOtaCloseSpcNotice() {
        if (DBG) log("onOtaCloseSpcNotice(), send shutdown intent");
        Intent shutdown = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
        shutdown.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
        shutdown.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivity(shutdown);
    }

    /**
     * Show two-second notice when OTA provisioning fails and number of failed attempts
     * is less then 3.
     */
    private void otaShowProgramFailureNotice(int length) {
        if (DBG) log("otaShowProgramFailureNotice()...");
        if (mOtaWidgetData.otaFailureDialog == null) {
            mOtaWidgetData.otaFailureDialog = new AlertDialog.Builder(mInCallScreen)
                    .setMessage(R.string.ota_failure)
                    .create();
            mOtaWidgetData.otaFailureDialog.getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            mOtaWidgetData.otaFailureDialog.show();

            long noticeTime = length*1000;
            mInCallScreen.requestCloseOtaFailureNotice(noticeTime);
        }
    }

    /**
     * Handle OTA unsuccessful notice expiry. Dismisses the
     * two-second notice and shows the activation screen.
     */
    public void onOtaCloseFailureNotice() {
        if (DBG) log("onOtaCloseFailureNotice()...");
        if (mOtaWidgetData.otaFailureDialog != null) {
            mOtaWidgetData.otaFailureDialog.dismiss();
            mOtaWidgetData.otaFailureDialog = null;
        }
        otaShowActivateScreen();
    }

    /**
     * Initialize all OTA UI elements to be gone. Also set inCallPanel,
     * callCard and the dialpad handle to be gone. This is called before any OTA screen
     * gets drawn.
     */
    private void otaScreenInitialize() {
        if (DBG) log("otaScreenInitialize()...");

        if (!mInteractive) {
            // We should never be doing anything with UI elements in
            // non-interactive mode.
            Log.w(LOG_TAG, "otaScreenInitialize: not interactive!");
            return;
        }

        if (mInCallTouchUi != null) mInCallTouchUi.setVisibility(View.GONE);
        if (mCallCard != null) {
            mCallCard.setVisibility(View.GONE);
            // TODO: try removing this.
            mCallCard.hideCallCardElements();
        }

        mOtaWidgetData.otaTitle.setText(R.string.ota_title_activate);
        mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
        mOtaWidgetData.otaTextListenProgress.setVisibility(View.GONE);
        mOtaWidgetData.otaTextProgressBar.setVisibility(View.GONE);
        mOtaWidgetData.otaTextSuccessFail.setVisibility(View.GONE);
        mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
        mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
        mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
        mOtaWidgetData.otaDtmfDialerView.setVisibility(View.GONE);
        mOtaWidgetData.otaSpeakerButton.setVisibility(View.GONE);
        mOtaWidgetData.otaTryAgainButton.setVisibility(View.GONE);
        mOtaWidgetData.otaNextButton.setVisibility(View.GONE);
        mOtaWidgetData.otaUpperWidgets.setVisibility(View.VISIBLE);
        mOtaWidgetData.otaSkipButton.setVisibility(View.VISIBLE);
    }

    public void hideOtaScreen() {
        if (DBG) log("hideOtaScreen()...");

        mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
        mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
        mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
        mOtaWidgetData.otaUpperWidgets.setVisibility(View.GONE);
    }

    public boolean isDialerOpened() {
        boolean retval = (mOtaCallCardDtmfDialer != null && mOtaCallCardDtmfDialer.isOpened());
        if (DBG) log("- isDialerOpened() ==> " + retval);
        return retval;
    }

    /**
     * Show the appropriate OTA screen based on the current state of OTA call.
     *
     * This is called from the InCallScreen when the screen needs to be
     * refreshed (and thus is only ever used in interactive mode.)
     *
     * Since this is called as part of the InCallScreen.updateScreen() sequence,
     * this method does *not* post an mInCallScreen.requestUpdateScreen()
     * request.
     */
    public void otaShowProperScreen() {
        if (DBG) log("otaShowProperScreen()...");
        if (!mInteractive) {
            // We shouldn't ever get here in non-interactive mode!
            Log.w(LOG_TAG, "otaShowProperScreen: not interactive!");
            return;
        }

        if ((mInCallScreen != null) && mInCallScreen.isForegroundActivity()) {
            if (DBG) log("otaShowProperScreen(): InCallScreen in foreground, currentstate = "
                    + mApplication.cdmaOtaScreenState.otaScreenState);
            if (mInCallTouchUi != null) {
                mInCallTouchUi.setVisibility(View.GONE);
            }
            if (mCallCard != null) {
                mCallCard.setVisibility(View.GONE);
            }
            if (mApplication.cdmaOtaScreenState.otaScreenState
                    == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION) {
                otaShowActivateScreen();
            } else if (mApplication.cdmaOtaScreenState.otaScreenState
                    == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING) {
                otaShowListeningScreen();
            } else if (mApplication.cdmaOtaScreenState.otaScreenState
                    == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS) {
                otaShowInProgressScreen();
            }

            if (mApplication.cdmaOtaProvisionData.inOtaSpcState) {
                otaShowSpcErrorNotice(getOtaSpcDisplayTime());
            }
        }
    }

    /**
     * Read configuration values for each OTA screen from config.xml.
     * These configuration values control visibility of each screen.
     */
    private void readXmlSettings() {
        if (DBG) log("readXmlSettings()...");
        if (mApplication.cdmaOtaConfigData.configComplete) {
            return;
        }

        mApplication.cdmaOtaConfigData.configComplete = true;
        int tmpOtaShowActivationScreen =
                mContext.getResources().getInteger(R.integer.OtaShowActivationScreen);
        mApplication.cdmaOtaConfigData.otaShowActivationScreen = tmpOtaShowActivationScreen;
        if (DBG) log("readXmlSettings(), otaShowActivationScreen = "
                + mApplication.cdmaOtaConfigData.otaShowActivationScreen);

        int tmpOtaShowListeningScreen =
                mContext.getResources().getInteger(R.integer.OtaShowListeningScreen);
        mApplication.cdmaOtaConfigData.otaShowListeningScreen = tmpOtaShowListeningScreen;
        if (DBG) log("readXmlSettings(), otaShowListeningScreen = "
                + mApplication.cdmaOtaConfigData.otaShowListeningScreen);

        int tmpOtaShowActivateFailTimes =
                mContext.getResources().getInteger(R.integer.OtaShowActivateFailTimes);
        mApplication.cdmaOtaConfigData.otaShowActivateFailTimes = tmpOtaShowActivateFailTimes;
        if (DBG) log("readXmlSettings(), otaShowActivateFailTimes = "
                + mApplication.cdmaOtaConfigData.otaShowActivateFailTimes);

        int tmpOtaPlaySuccessFailureTone =
                mContext.getResources().getInteger(R.integer.OtaPlaySuccessFailureTone);
        mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone = tmpOtaPlaySuccessFailureTone;
        if (DBG) log("readXmlSettings(), otaPlaySuccessFailureTone = "
                + mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone);
    }

    /**
     * Handle the click events for OTA buttons.
     */
    public void onClickHandler(int id) {
        switch (id) {
            case R.id.otaEndButton:
                onClickOtaEndButton();
                break;

            case R.id.otaSpeakerButton:
                onClickOtaSpeakerButton();
                break;

            case R.id.otaActivateButton:
                onClickOtaActivateButton();
                break;

            case R.id.otaSkipButton:
                onClickOtaActivateSkipButton();
                break;

            case R.id.otaNextButton:
                onClickOtaActivateNextButton();
                break;

            case R.id.otaTryAgainButton:
                onClickOtaTryAgainButton();
                break;

            default:
                if (DBG) log ("onClickHandler: received a click event for unrecognized id");
                break;
        }
    }

    private void onClickOtaTryAgainButton() {
        if (DBG) log("Activation Try Again Clicked!");
        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
            otaShowActivateScreen();
        }
    }

    private void onClickOtaEndButton() {
        if (DBG) log("Activation End Call Button Clicked!");
        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
            if (PhoneUtils.hangup(mApplication.mCM) == false) {
                // If something went wrong when placing the OTA call,
                // the screen is not updated by the call disconnect
                // handler and we have to do it here
                setSpeaker(false);
                mInCallScreen.handleOtaCallEnd();
            }
        }
    }

    private void onClickOtaSpeakerButton() {
        if (DBG) log("OTA Speaker button Clicked!");
        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
            boolean isChecked = !PhoneUtils.isSpeakerOn(mContext);
            setSpeaker(isChecked);
        }
    }

    private void onClickOtaActivateButton() {
        if (DBG) log("Call Activation Clicked!");
        otaPerformActivation();
    }

    private void onClickOtaActivateSkipButton() {
        if (DBG) log("Activation Skip Clicked!");
        DialogInterface.OnKeyListener keyListener;
        keyListener = new DialogInterface.OnKeyListener() {
            public boolean onKey(DialogInterface dialog, int keyCode,
                    KeyEvent event) {
                if (DBG) log("Ignoring key events...");
                return true;
            }
        };
        mOtaWidgetData.otaSkipConfirmationDialog = new AlertDialog.Builder(mInCallScreen)
                .setTitle(R.string.ota_skip_activation_dialog_title)
                .setMessage(R.string.ota_skip_activation_dialog_message)
                .setPositiveButton(
                    android.R.string.ok,
                    // "OK" means "skip activation".
                    new AlertDialog.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            otaSkipActivation();
                        }
                    })
                .setNegativeButton(
                    android.R.string.cancel,
                    // "Cancel" means just dismiss the dialog.
                    // Don't actually start an activation call.
                    null)
                .setOnKeyListener(keyListener)
                .create();
        mOtaWidgetData.otaSkipConfirmationDialog.show();
    }

    private void onClickOtaActivateNextButton() {
        if (DBG) log("Dialog Next Clicked!");
        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
            mApplication.cdmaOtaScreenState.otaScreenState =
                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
            otaShowHome();
        }
    }

    public void dismissAllOtaDialogs() {
        if (mOtaWidgetData != null) {
            if (mOtaWidgetData.spcErrorDialog != null) {
                if (DBG) log("- DISMISSING mSpcErrorDialog.");
                mOtaWidgetData.spcErrorDialog.dismiss();
                mOtaWidgetData.spcErrorDialog = null;
            }
            if (mOtaWidgetData.otaFailureDialog != null) {
                if (DBG) log("- DISMISSING mOtaFailureDialog.");
                mOtaWidgetData.otaFailureDialog.dismiss();
                mOtaWidgetData.otaFailureDialog = null;
            }
        }
    }

    private int getOtaSpcDisplayTime() {
        if (DBG) log("getOtaSpcDisplayTime()...");
        int tmpSpcTime = 1;
        if (mApplication.cdmaOtaProvisionData.inOtaSpcState) {
            long tmpOtaSpcRunningTime = 0;
            long tmpOtaSpcLeftTime = 0;
            tmpOtaSpcRunningTime = SystemClock.elapsedRealtime();
            tmpOtaSpcLeftTime =
                tmpOtaSpcRunningTime - mApplication.cdmaOtaProvisionData.otaSpcUptime;
            if (tmpOtaSpcLeftTime >= OTA_SPC_TIMEOUT*1000) {
                tmpSpcTime = 1;
            } else {
                tmpSpcTime = OTA_SPC_TIMEOUT - (int)tmpOtaSpcLeftTime/1000;
            }
        }
        if (DBG) log("getOtaSpcDisplayTime(), time for SPC error notice: " + tmpSpcTime);
        return tmpSpcTime;
    }

    /**
     * Initialize the OTA widgets for all OTA screens.
     */
    private void initOtaInCallScreen() {
        if (DBG) log("initOtaInCallScreen()...");
        mOtaWidgetData.otaTitle = (TextView) mInCallScreen.findViewById(R.id.otaTitle);
        mOtaWidgetData.otaTextActivate = (TextView) mInCallScreen.findViewById(R.id.otaActivate);
        mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
        mOtaWidgetData.otaTextListenProgress =
                (TextView) mInCallScreen.findViewById(R.id.otaListenProgress);
        mOtaWidgetData.otaTextProgressBar =
                (ProgressBar) mInCallScreen.findViewById(R.id.progress_large);
        mOtaWidgetData.otaTextProgressBar.setIndeterminate(true);
        mOtaWidgetData.otaTextSuccessFail =
                (TextView) mInCallScreen.findViewById(R.id.otaSuccessFailStatus);

        mOtaWidgetData.otaUpperWidgets =
                (ViewGroup) mInCallScreen.findViewById(R.id.otaUpperWidgets);
        mOtaWidgetData.callCardOtaButtonsListenProgress =
                (View) mInCallScreen.findViewById(R.id.callCardOtaListenProgress);
        mOtaWidgetData.callCardOtaButtonsActivate =
                (View) mInCallScreen.findViewById(R.id.callCardOtaActivate);
        mOtaWidgetData.callCardOtaButtonsFailSuccess =
                (View) mInCallScreen.findViewById(R.id.callCardOtaFailOrSuccessful);

        mOtaWidgetData.otaEndButton = (Button) mInCallScreen.findViewById(R.id.otaEndButton);
        mOtaWidgetData.otaEndButton.setOnClickListener(mInCallScreen);
        mOtaWidgetData.otaSpeakerButton =
                (ToggleButton) mInCallScreen.findViewById(R.id.otaSpeakerButton);
        mOtaWidgetData.otaSpeakerButton.setOnClickListener(mInCallScreen);
        mOtaWidgetData.otaActivateButton =
                (Button) mInCallScreen.findViewById(R.id.otaActivateButton);
        mOtaWidgetData.otaActivateButton.setOnClickListener(mInCallScreen);
        mOtaWidgetData.otaSkipButton = (Button) mInCallScreen.findViewById(R.id.otaSkipButton);
        mOtaWidgetData.otaSkipButton.setOnClickListener(mInCallScreen);
        mOtaWidgetData.otaNextButton = (Button) mInCallScreen.findViewById(R.id.otaNextButton);
        mOtaWidgetData.otaNextButton.setOnClickListener(mInCallScreen);
        mOtaWidgetData.otaTryAgainButton =
                (Button) mInCallScreen.findViewById(R.id.otaTryAgainButton);
        mOtaWidgetData.otaTryAgainButton.setOnClickListener(mInCallScreen);

        mOtaWidgetData.otaDtmfDialerView =
                (DTMFTwelveKeyDialerView) mInCallScreen.findViewById(R.id.otaDtmfDialerView);
        // Sanity-check: the otaDtmfDialerView widget should *always* be present.
        if (mOtaWidgetData.otaDtmfDialerView == null) {
            throw new IllegalStateException("initOtaInCallScreen: couldn't find otaDtmfDialerView");
        }

        // Create a new DTMFTwelveKeyDialer instance purely for use by the
        // DTMFTwelveKeyDialerView ("otaDtmfDialerView") that comes from
        // otacall_card.xml.
        mOtaCallCardDtmfDialer = new DTMFTwelveKeyDialer(mInCallScreen,
                                                         mOtaWidgetData.otaDtmfDialerView);

        // Initialize the new DTMFTwelveKeyDialer instance.  This is
        // needed to play local DTMF tones.
        mOtaCallCardDtmfDialer.startDialerSession();

        mOtaWidgetData.otaDtmfDialerView.setDialer(mOtaCallCardDtmfDialer);
    }

    /**
     * Clear out all OTA UI widget elements. Needs to get called
     * when OTA call ends or InCallScreen is destroyed.
     * @param disableSpeaker parameter control whether Speaker should be turned off.
     */
    public void cleanOtaScreen(boolean disableSpeaker) {
        if (DBG) log("OTA ends, cleanOtaScreen!");

        mApplication.cdmaOtaScreenState.otaScreenState =
                CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
        mApplication.cdmaOtaProvisionData.isOtaCallCommitted = false;
        mApplication.cdmaOtaProvisionData.isOtaCallIntentProcessed = false;
        mApplication.cdmaOtaProvisionData.inOtaSpcState = false;
        mApplication.cdmaOtaProvisionData.activationCount = 0;
        mApplication.cdmaOtaProvisionData.otaSpcUptime = 0;
        mApplication.cdmaOtaInCallScreenUiState.state = State.UNDEFINED;

        if (mInteractive && (mOtaWidgetData != null)) {
            if (mInCallTouchUi != null) mInCallTouchUi.setVisibility(View.VISIBLE);
            if (mCallCard != null) {
                mCallCard.setVisibility(View.VISIBLE);
                mCallCard.hideCallCardElements();
            }

            // Free resources from the DTMFTwelveKeyDialer instance we created
            // in initOtaInCallScreen().
            if (mOtaCallCardDtmfDialer != null) {
                mOtaCallCardDtmfDialer.stopDialerSession();
            }

            mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
            mOtaWidgetData.otaTextListenProgress.setVisibility(View.GONE);
            mOtaWidgetData.otaTextProgressBar.setVisibility(View.GONE);
            mOtaWidgetData.otaTextSuccessFail.setVisibility(View.GONE);
            mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
            mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
            mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
            mOtaWidgetData.otaUpperWidgets.setVisibility(View.GONE);
            mOtaWidgetData.otaDtmfDialerView.setVisibility(View.GONE);
            mOtaWidgetData.otaNextButton.setVisibility(View.GONE);
            mOtaWidgetData.otaTryAgainButton.setVisibility(View.GONE);
        }

        // turn off the speaker in case it was turned on
        // but the OTA call could not be completed
        if (disableSpeaker) {
            setSpeaker(false);
        }
    }

    /**
     * Defines OTA information that needs to be maintained during
     * an OTA call when display orientation changes.
     */
    public static class CdmaOtaProvisionData {
        public boolean isOtaCallCommitted;
        public boolean isOtaCallIntentProcessed;
        public boolean inOtaSpcState;
        public int activationCount;
        public long otaSpcUptime;
    }

    /**
     * Defines OTA screen configuration items read from config.xml
     * and used to control OTA display.
     */
    public static class CdmaOtaConfigData {
        public int otaShowActivationScreen;
        public int otaShowListeningScreen;
        public int otaShowActivateFailTimes;
        public int otaPlaySuccessFailureTone;
        public boolean configComplete;
        public CdmaOtaConfigData() {
            if (DBG) log("CdmaOtaConfigData constructor!");
            otaShowActivationScreen = OTA_SHOW_ACTIVATION_SCREEN_OFF;
            otaShowListeningScreen = OTA_SHOW_LISTENING_SCREEN_OFF;
            otaShowActivateFailTimes = OTA_SHOW_ACTIVATE_FAIL_COUNT_OFF;
            otaPlaySuccessFailureTone = OTA_PLAY_SUCCESS_FAILURE_TONE_OFF;
        }
    }

    /**
     * The state of the OTA InCallScreen UI.
     */
    public static class CdmaOtaInCallScreenUiState {
        public enum State {
            UNDEFINED,
            NORMAL,
            ENDED
        }

        public State state;

        public CdmaOtaInCallScreenUiState() {
            if (DBG) log("CdmaOtaInCallScreenState: constructor init to UNDEFINED");
            state = CdmaOtaInCallScreenUiState.State.UNDEFINED;
        }
    }

    /**
     * Save the Ota InCallScreen UI state
     */
    public void setCdmaOtaInCallScreenUiState(CdmaOtaInCallScreenUiState.State state) {
        if (DBG) log("setCdmaOtaInCallScreenState: " + state);
        mApplication.cdmaOtaInCallScreenUiState.state = state;
    }

    /**
     * Get the Ota InCallScreen UI state
     */
    public CdmaOtaInCallScreenUiState.State getCdmaOtaInCallScreenUiState() {
        if (DBG) log("getCdmaOtaInCallScreenState: "
                     + mApplication.cdmaOtaInCallScreenUiState.state);
        return mApplication.cdmaOtaInCallScreenUiState.state;
    }

    /**
     * The OTA screen state machine.
     */
    public static class CdmaOtaScreenState {
        public enum OtaScreenState {
            OTA_STATUS_UNDEFINED,
            OTA_STATUS_ACTIVATION,
            OTA_STATUS_LISTENING,
            OTA_STATUS_PROGRESS,
            OTA_STATUS_SUCCESS_FAILURE_DLG
        }

        public OtaScreenState otaScreenState;

        public CdmaOtaScreenState() {
            otaScreenState = OtaScreenState.OTA_STATUS_UNDEFINED;
        }

        /**
         * {@link PendingIntent} used to report an OTASP result status code
         * back to our caller. Can be null.
         *
         * Our caller (presumably SetupWizard) may create this PendingIntent,
         * pointing back at itself, and passes it along as an extra with the
         * ACTION_PERFORM_CDMA_PROVISIONING intent.  Then, when there's an
         * OTASP result to report, we send that PendingIntent back, adding an
         * extra called EXTRA_OTASP_RESULT_CODE to indicate the result.
         *
         * Possible result values are the OTASP_RESULT_* constants.
         */
        public PendingIntent otaspResultCodePendingIntent;
    }

    /** @see com.android.internal.telephony.Phone */
    private static String otaProvisionStatusToString(int status) {
        switch (status) {
            case Phone.CDMA_OTA_PROVISION_STATUS_SPL_UNLOCKED:
                return "SPL_UNLOCKED";
            case Phone.CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED:
                return "SPC_RETRIES_EXCEEDED";
            case Phone.CDMA_OTA_PROVISION_STATUS_A_KEY_EXCHANGED:
                return "A_KEY_EXCHANGED";
            case Phone.CDMA_OTA_PROVISION_STATUS_SSD_UPDATED:
                return "SSD_UPDATED";
            case Phone.CDMA_OTA_PROVISION_STATUS_NAM_DOWNLOADED:
                return "NAM_DOWNLOADED";
            case Phone.CDMA_OTA_PROVISION_STATUS_MDN_DOWNLOADED:
                return "MDN_DOWNLOADED";
            case Phone.CDMA_OTA_PROVISION_STATUS_IMSI_DOWNLOADED:
                return "IMSI_DOWNLOADED";
            case Phone.CDMA_OTA_PROVISION_STATUS_PRL_DOWNLOADED:
                return "PRL_DOWNLOADED";
            case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
                return "COMMITTED";
            case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STARTED:
                return "OTAPA_STARTED";
            case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED:
                return "OTAPA_STOPPED";
            case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_ABORTED:
                return "OTAPA_ABORTED";
            default:
                return "<unknown status" + status + ">";
        }
    }

    private static int getLteOnCdmaMode(Context context) {
        final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
                Context.TELEPHONY_SERVICE);
        // If the telephony manager is not available yet, or if it doesn't know the answer yet,
        // try falling back on the system property that may or may not be there
        if (telephonyManager == null
                || telephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_UNKNOWN) {
            return SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE,
                    PhoneConstants.LTE_ON_CDMA_UNKNOWN);
        }
        return telephonyManager.getLteOnCdmaMode();
    }

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

    private static void loge(String msg) {
        Log.e(LOG_TAG, msg);
    }
}
