/*
 * 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.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.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 PhoneApp 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 = PhoneApp.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) {
        PhoneApp app = PhoneApp.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 (PhoneApp.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);
                context.startActivity(newIntent);
                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()...");
        PhoneApp app = PhoneApp.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()...");
        PhoneApp app = PhoneApp.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 = PhoneApp.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 + ")...");
        PhoneApp app = PhoneApp.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);
        PhoneApp app = PhoneApp.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.startActivity(intent);
        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);
    }
}
