Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.phone;
     18 
     19 import com.android.internal.telephony.Phone;
     20 import com.android.internal.telephony.PhoneConstants;
     21 import com.android.internal.telephony.TelephonyCapabilities;
     22 import com.android.internal.telephony.TelephonyProperties;
     23 import com.android.phone.OtaUtils.CdmaOtaInCallScreenUiState.State;
     24 
     25 import android.app.Activity;
     26 import android.app.ActivityManager;
     27 import android.app.AlertDialog;
     28 import android.app.PendingIntent;
     29 import android.app.PendingIntent.CanceledException;
     30 import android.content.ActivityNotFoundException;
     31 import android.content.Context;
     32 import android.content.DialogInterface;
     33 import android.content.Intent;
     34 import android.net.Uri;
     35 import android.os.AsyncResult;
     36 import android.os.Handler;
     37 import android.os.SystemClock;
     38 import android.os.SystemProperties;
     39 import android.os.UserHandle;
     40 import android.telecom.PhoneAccount;
     41 import android.telephony.TelephonyManager;
     42 import android.util.Log;
     43 import android.view.KeyEvent;
     44 import android.view.View;
     45 import android.view.ViewGroup;
     46 import android.view.WindowManager;
     47 import android.widget.Button;
     48 import android.widget.ProgressBar;
     49 import android.widget.TextView;
     50 import android.widget.ToggleButton;
     51 
     52 /**
     53  * Handles all OTASP Call related logic and UI functionality.
     54  * The InCallScreen interacts with this class to perform an OTASP Call.
     55  *
     56  * OTASP is a CDMA-specific feature:
     57  *   OTA or OTASP == Over The Air service provisioning
     58  *   SPC == Service Programming Code
     59  *   TODO: Include pointer to more detailed documentation.
     60  *
     61  * TODO: This is Over The Air Service Provisioning (OTASP)
     62  *       A better name would be OtaspUtils.java.
     63  */
     64 public class OtaUtils {
     65     private static final String LOG_TAG = "OtaUtils";
     66     private static final boolean DBG = false;
     67 
     68     public static final int OTA_SHOW_ACTIVATION_SCREEN_OFF = 0;
     69     public static final int OTA_SHOW_ACTIVATION_SCREEN_ON = 1;
     70     public static final int OTA_SHOW_LISTENING_SCREEN_OFF =0;
     71     public static final int OTA_SHOW_LISTENING_SCREEN_ON =1;
     72     public static final int OTA_SHOW_ACTIVATE_FAIL_COUNT_OFF = 0;
     73     public static final int OTA_SHOW_ACTIVATE_FAIL_COUNT_THREE = 3;
     74     public static final int OTA_PLAY_SUCCESS_FAILURE_TONE_OFF = 0;
     75     public static final int OTA_PLAY_SUCCESS_FAILURE_TONE_ON = 1;
     76 
     77     // SPC Timeout is 60 seconds
     78     public final int OTA_SPC_TIMEOUT = 60;
     79     public final int OTA_FAILURE_DIALOG_TIMEOUT = 2;
     80 
     81     // Constants for OTASP-related Intents and intent extras.
     82     // Watch out: these must agree with the corresponding constants in
     83     // apps/SetupWizard!
     84 
     85     // Intent action to launch an OTASP call.
     86     public static final String ACTION_PERFORM_CDMA_PROVISIONING =
     87            "com.android.phone.PERFORM_CDMA_PROVISIONING";
     88 
     89     // Intent action to launch activation on a non-voice capable device
     90     public static final String ACTION_PERFORM_VOICELESS_CDMA_PROVISIONING =
     91             "com.android.phone.PERFORM_VOICELESS_CDMA_PROVISIONING";
     92 
     93     // Intent action to display the InCallScreen in the OTASP "activation" state.
     94     public static final String ACTION_DISPLAY_ACTIVATION_SCREEN =
     95             "com.android.phone.DISPLAY_ACTIVATION_SCREEN";
     96 
     97     // boolean voiceless provisioning extra that enables a "don't show this again" checkbox
     98     // the user can check to never see the activity upon bootup again
     99     public static final String EXTRA_VOICELESS_PROVISIONING_OFFER_DONTSHOW =
    100             "com.android.phone.VOICELESS_PROVISIONING_OFFER_DONTSHOW";
    101 
    102     // Activity result codes for the ACTION_PERFORM_CDMA_PROVISIONING intent
    103     // (see the InCallScreenShowActivation activity.)
    104     //
    105     // Note: currently, our caller won't ever actually receive the
    106     // RESULT_INTERACTIVE_OTASP_STARTED result code; see comments in
    107     // InCallScreenShowActivation.onCreate() for details.
    108 
    109     public static final int RESULT_INTERACTIVE_OTASP_STARTED = Activity.RESULT_FIRST_USER;
    110     public static final int RESULT_NONINTERACTIVE_OTASP_STARTED = Activity.RESULT_FIRST_USER + 1;
    111     public static final int RESULT_NONINTERACTIVE_OTASP_FAILED = Activity.RESULT_FIRST_USER + 2;
    112 
    113     // Testing: Extra for the ACTION_PERFORM_CDMA_PROVISIONING intent that
    114     // allows the caller to manually enable/disable "interactive mode" for
    115     // the OTASP call.   Only available in userdebug or eng builds.
    116     public static final String EXTRA_OVERRIDE_INTERACTIVE_MODE =
    117             "ota_override_interactive_mode";
    118 
    119     // Extra for the ACTION_PERFORM_CDMA_PROVISIONING intent, holding a
    120     // PendingIntent which the phone app can use to send a result code
    121     // back to the caller.
    122     public static final String EXTRA_OTASP_RESULT_CODE_PENDING_INTENT =
    123             "otasp_result_code_pending_intent";
    124 
    125     // Extra attached to the above PendingIntent that indicates
    126     // success or failure.
    127     public static final String EXTRA_OTASP_RESULT_CODE = "otasp_result_code";
    128 
    129     // Extra attached to the above PendingIntent that contains an error code.
    130     public static final String EXTRA_OTASP_ERROR_CODE = "otasp_error_code";
    131 
    132     public static final int OTASP_UNKNOWN = 0;
    133     public static final int OTASP_USER_SKIPPED = 1;  // Only meaningful with interactive OTASP
    134     public static final int OTASP_SUCCESS = 2;
    135     public static final int OTASP_FAILURE = 3;
    136     // failed due to CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED
    137     public static final int OTASP_FAILURE_SPC_RETRIES = 4;
    138     // TODO: Distinguish between interactive and non-interactive success
    139     // and failure.  Then, have the PendingIntent be sent after
    140     // interactive OTASP as well (so the caller can find out definitively
    141     // when interactive OTASP completes.)
    142 
    143     private static final String OTASP_NUMBER = "*228";
    144     private static final String OTASP_NUMBER_NON_INTERACTIVE = "*22899";
    145 
    146     private Context mContext;
    147     private PhoneGlobals mApplication;
    148     private OtaWidgetData mOtaWidgetData;
    149 
    150     private static boolean sIsWizardMode = true;
    151 
    152     // How many times do we retry maybeDoOtaCall() if the LTE state is not known yet,
    153     // and how long do we wait between retries
    154     private static final int OTA_CALL_LTE_RETRIES_MAX = 5;
    155     private static final int OTA_CALL_LTE_RETRY_PERIOD = 3000;
    156     private static int sOtaCallLteRetries = 0;
    157 
    158     // In "interactive mode", the OtaUtils object is tied to an
    159     // InCallScreen instance, where we display a bunch of UI specific to
    160     // the OTASP call.  But on devices that are not "voice capable", the
    161     // OTASP call runs in a non-interactive mode, and we don't have
    162     // an InCallScreen or CallCard or any OTASP UI elements at all.
    163     private boolean mInteractive = true;
    164 
    165     /**
    166      * OtaWidgetData class represent all OTA UI elements
    167      *
    168      * TODO(OTASP): It's really ugly for the OtaUtils object to reach into the
    169      *     InCallScreen like this and directly manipulate its widgets.
    170      *
    171      *     Instead, the model/view separation should be more clear: OtaUtils
    172      *     should only know about a higher-level abstraction of the
    173      *     OTASP-specific UI state (just like how the CallController uses the
    174      *     InCallUiState object), and the InCallScreen itself should translate
    175      *     that higher-level abstraction into actual onscreen views and widgets.
    176      */
    177     private class OtaWidgetData {
    178         public Button otaEndButton;
    179         public Button otaActivateButton;
    180         public Button otaSkipButton;
    181         public Button otaNextButton;
    182         public ToggleButton otaSpeakerButton;
    183         public ViewGroup otaUpperWidgets;
    184         public View callCardOtaButtonsFailSuccess;
    185         public ProgressBar otaTextProgressBar;
    186         public TextView otaTextSuccessFail;
    187         public View callCardOtaButtonsActivate;
    188         public View callCardOtaButtonsListenProgress;
    189         public TextView otaTextActivate;
    190         public TextView otaTextListenProgress;
    191         public AlertDialog spcErrorDialog;
    192         public AlertDialog otaFailureDialog;
    193         public AlertDialog otaSkipConfirmationDialog;
    194         public TextView otaTitle;
    195         public Button otaTryAgainButton;
    196     }
    197 
    198     /**
    199      * OtaUtils constructor.
    200      *
    201      * @param context the Context of the calling Activity or Application
    202      * @param interactive if true, use the InCallScreen to display the progress
    203      *                    and result of the OTASP call.  In practice this is
    204      *                    true IFF the current device is a voice-capable phone.
    205      *
    206      * Note if interactive is true, you must also call updateUiWidgets() as soon
    207      * as the InCallScreen instance is ready.
    208      */
    209     public OtaUtils(Context context, boolean interactive) {
    210         if (DBG) log("OtaUtils constructor...");
    211         mApplication = PhoneGlobals.getInstance();
    212         mContext = context;
    213         mInteractive = interactive;
    214     }
    215 
    216     /**
    217      * Starts the OTA provisioning call.  If the MIN isn't available yet, it returns false and adds
    218      * an event to return the request to the calling app when it becomes available.
    219      *
    220      * @param context
    221      * @param handler
    222      * @param request
    223      * @return true if we were able to launch Ota activity or it's not required; false otherwise
    224      */
    225     public static boolean maybeDoOtaCall(Context context, Handler handler, int request) {
    226         PhoneGlobals app = PhoneGlobals.getInstance();
    227         Phone phone = PhoneGlobals.getPhone();
    228 
    229         if (ActivityManager.isRunningInTestHarness()) {
    230             Log.i(LOG_TAG, "Don't run provisioning when in test harness");
    231             return true;
    232         }
    233 
    234         if (!TelephonyCapabilities.supportsOtasp(phone)) {
    235             // Presumably not a CDMA phone.
    236             if (DBG) log("maybeDoOtaCall: OTASP not supported on this device");
    237             return true;  // Nothing to do here.
    238         }
    239 
    240         if (!phone.isMinInfoReady()) {
    241             if (DBG) log("MIN is not ready. Registering to receive notification.");
    242             phone.registerForSubscriptionInfoReady(handler, request, null);
    243             return false;
    244         }
    245         phone.unregisterForSubscriptionInfoReady(handler);
    246 
    247         if (getLteOnCdmaMode(context) == PhoneConstants.LTE_ON_CDMA_UNKNOWN) {
    248             if (sOtaCallLteRetries < OTA_CALL_LTE_RETRIES_MAX) {
    249                 if (DBG) log("maybeDoOtaCall: LTE state still unknown: retrying");
    250                 handler.sendEmptyMessageDelayed(request, OTA_CALL_LTE_RETRY_PERIOD);
    251                 sOtaCallLteRetries++;
    252                 return false;
    253             } else {
    254                 Log.w(LOG_TAG, "maybeDoOtaCall: LTE state still unknown: giving up");
    255                 return true;
    256             }
    257         }
    258 
    259         boolean phoneNeedsActivation = phone.needsOtaServiceProvisioning();
    260         if (DBG) log("phoneNeedsActivation is set to " + phoneNeedsActivation);
    261 
    262         int otaShowActivationScreen = context.getResources().getInteger(
    263                 R.integer.OtaShowActivationScreen);
    264         if (DBG) log("otaShowActivationScreen: " + otaShowActivationScreen);
    265 
    266         // Run the OTASP call in "interactive" mode only if
    267         // this is a non-LTE "voice capable" device.
    268         if (PhoneGlobals.sVoiceCapable && getLteOnCdmaMode(context) == PhoneConstants.LTE_ON_CDMA_FALSE) {
    269             if (phoneNeedsActivation
    270                     && (otaShowActivationScreen == OTA_SHOW_ACTIVATION_SCREEN_ON)) {
    271                 app.cdmaOtaProvisionData.isOtaCallIntentProcessed = false;
    272                 sIsWizardMode = false;
    273 
    274                 if (DBG) Log.d(LOG_TAG, "==> Starting interactive CDMA provisioning...");
    275                 OtaUtils.startInteractiveOtasp(context);
    276 
    277                 if (DBG) log("maybeDoOtaCall: voice capable; activation started.");
    278             } else {
    279                 if (DBG) log("maybeDoOtaCall: voice capable; activation NOT started.");
    280             }
    281         } else {
    282             if (phoneNeedsActivation) {
    283                 app.cdmaOtaProvisionData.isOtaCallIntentProcessed = false;
    284                 Intent newIntent = new Intent(ACTION_PERFORM_VOICELESS_CDMA_PROVISIONING);
    285                 newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    286                 newIntent.putExtra(EXTRA_VOICELESS_PROVISIONING_OFFER_DONTSHOW, true);
    287                 try {
    288                     context.startActivity(newIntent);
    289                 } catch (ActivityNotFoundException e) {
    290                     loge("No activity Handling PERFORM_VOICELESS_CDMA_PROVISIONING!");
    291                     return false;
    292                 }
    293                 if (DBG) log("maybeDoOtaCall: non-interactive; activation intent sent.");
    294             } else {
    295                 if (DBG) log("maybeDoOtaCall: non-interactive, no need for OTASP.");
    296             }
    297         }
    298         return true;
    299     }
    300 
    301     /**
    302      * Starts a normal "interactive" OTASP call (i.e. CDMA activation
    303      * for regular voice-capable phone devices.)
    304      *
    305      * This method is called from the InCallScreenShowActivation activity when
    306      * handling the ACTION_PERFORM_CDMA_PROVISIONING intent.
    307      */
    308     public static void startInteractiveOtasp(Context context) {
    309         if (DBG) log("startInteractiveOtasp()...");
    310         PhoneGlobals app = PhoneGlobals.getInstance();
    311 
    312         // There are two ways to start OTASP on voice-capable devices:
    313         //
    314         // (1) via the PERFORM_CDMA_PROVISIONING intent
    315         //     - this is triggered by the "Activate device" button in settings,
    316         //       or can be launched automatically upon boot if the device
    317         //       thinks it needs to be provisioned.
    318         //     - the intent is handled by InCallScreenShowActivation.onCreate(),
    319         //       which calls this method
    320         //     - we prepare for OTASP by initializing the OtaUtils object
    321         //     - we bring up the InCallScreen in the ready-to-activate state
    322         //     - when the user presses the "Activate" button we launch the
    323         //       call by calling CallController.placeCall() via the
    324         //       otaPerformActivation() method.
    325         //
    326         // (2) by manually making an outgoing call to a special OTASP number
    327         //     like "*228" or "*22899".
    328         //     - That sequence does NOT involve this method (OtaUtils.startInteractiveOtasp()).
    329         //       Instead, the outgoing call request goes straight to CallController.placeCall().
    330         //     - CallController.placeCall() notices that it's an OTASP
    331         //       call, and initializes the OtaUtils object.
    332         //     - The InCallScreen is launched (as the last step of
    333         //       CallController.placeCall()).  The InCallScreen notices that
    334         //       OTASP is active and shows the correct UI.
    335 
    336         // Here, we start sequence (1):
    337         // Do NOT immediately start the call.  Instead, bring up the InCallScreen
    338         // in the special "activate" state (see OtaUtils.otaShowActivateScreen()).
    339         // We won't actually make the call until the user presses the "Activate"
    340         // button.
    341 
    342         Intent activationScreenIntent = new Intent().setClass(context, InCallScreen.class)
    343                 .setAction(ACTION_DISPLAY_ACTIVATION_SCREEN);
    344 
    345         // Watch out: in the scenario where OTASP gets triggered from the
    346         // BOOT_COMPLETED broadcast (see OtaStartupReceiver.java), we might be
    347         // running in the PhoneApp's context right now.
    348         // So the FLAG_ACTIVITY_NEW_TASK flag is required here.
    349         activationScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    350 
    351         // We're about to start the OTASP sequence, so create and initialize the
    352         // OtaUtils instance.  (This needs to happen before bringing up the
    353         // InCallScreen.)
    354         OtaUtils.setupOtaspCall(activationScreenIntent);
    355 
    356         // And bring up the InCallScreen...
    357         Log.i(LOG_TAG, "startInteractiveOtasp: launching InCallScreen in 'activate' state: "
    358               + activationScreenIntent);
    359         context.startActivity(activationScreenIntent);
    360     }
    361 
    362     /**
    363      * Starts the OTASP call *without* involving the InCallScreen or
    364      * displaying any UI.
    365      *
    366      * This is used on data-only devices, which don't support any kind of
    367      * in-call phone UI.
    368      *
    369      * @return PhoneUtils.CALL_STATUS_DIALED if we successfully
    370      *         dialed the OTASP number, or one of the other
    371      *         CALL_STATUS_* constants if there was a failure.
    372      */
    373     public static int startNonInteractiveOtasp(Context context) {
    374         if (DBG) log("startNonInteractiveOtasp()...");
    375         PhoneGlobals app = PhoneGlobals.getInstance();
    376 
    377         if (app.otaUtils != null) {
    378             // An OtaUtils instance already exists, presumably from a previous OTASP call.
    379             Log.i(LOG_TAG, "startNonInteractiveOtasp: "
    380                   + "OtaUtils already exists; nuking the old one and starting again...");
    381         }
    382 
    383         // Create the OtaUtils instance.
    384         app.otaUtils = new OtaUtils(context, false /* non-interactive mode */);
    385         if (DBG) log("- created OtaUtils: " + app.otaUtils);
    386 
    387         // ... and kick off the OTASP call.
    388         // TODO(InCallScreen redesign): This should probably go through
    389         // the CallController, rather than directly calling
    390         // PhoneUtils.placeCall().
    391         Phone phone = PhoneGlobals.getPhone();
    392         String number = OTASP_NUMBER_NON_INTERACTIVE;
    393         Log.i(LOG_TAG, "startNonInteractiveOtasp: placing call to '" + number + "'...");
    394         int callStatus = PhoneUtils.placeCall(context,
    395                                               phone,
    396                                               number,
    397                                               null,   // contactRef
    398                                               false); //isEmergencyCall
    399 
    400         if (callStatus == PhoneUtils.CALL_STATUS_DIALED) {
    401             if (DBG) log("  ==> successful return from placeCall(): callStatus = " + callStatus);
    402         } else {
    403             Log.w(LOG_TAG, "Failure from placeCall() for OTA number '"
    404                   + number + "': code " + callStatus);
    405             return callStatus;
    406         }
    407 
    408         // TODO: Any other special work to do here?
    409         // Such as:
    410         //
    411         // - manually kick off progress updates, either using TelephonyRegistry
    412         //   or else by sending PendingIntents directly to our caller?
    413         //
    414         // - manually silence the in-call audio?  (Probably unnecessary
    415         //   if Stingray truly has no audio path from phone baseband
    416         //   to the device's speakers.)
    417         //
    418 
    419         return callStatus;
    420     }
    421 
    422     /**
    423      * @return true if the specified Intent is a CALL action that's an attempt
    424      * to initate an OTASP call.
    425      *
    426      * OTASP is a CDMA-specific concept, so this method will always return false
    427      * on GSM phones.
    428      *
    429      * This code was originally part of the InCallScreen.checkIsOtaCall() method.
    430      */
    431     public static boolean isOtaspCallIntent(Intent intent) {
    432         if (DBG) log("isOtaspCallIntent(" + intent + ")...");
    433         PhoneGlobals app = PhoneGlobals.getInstance();
    434         Phone phone = app.mCM.getDefaultPhone();
    435 
    436         if (intent == null) {
    437             return false;
    438         }
    439         if (!TelephonyCapabilities.supportsOtasp(phone)) {
    440             return false;
    441         }
    442 
    443         String action = intent.getAction();
    444         if (action == null) {
    445             return false;
    446         }
    447         if (!action.equals(Intent.ACTION_CALL)) {
    448             if (DBG) log("isOtaspCallIntent: not a CALL action: '" + action + "' ==> not OTASP");
    449             return false;
    450         }
    451 
    452         if ((app.cdmaOtaScreenState == null) || (app.cdmaOtaProvisionData == null)) {
    453             // Uh oh -- something wrong with our internal OTASP state.
    454             // (Since this is an OTASP-capable device, these objects
    455             // *should* have already been created by PhoneApp.onCreate().)
    456             throw new IllegalStateException("isOtaspCallIntent: "
    457                                             + "app.cdmaOta* objects(s) not initialized");
    458         }
    459 
    460         // This is an OTASP call iff the number we're trying to dial is one of
    461         // the magic OTASP numbers.
    462         String number;
    463         try {
    464             number = PhoneUtils.getInitialNumber(intent);
    465         } catch (PhoneUtils.VoiceMailNumberMissingException ex) {
    466             // This was presumably a "voicemail:" intent, so it's
    467             // obviously not an OTASP number.
    468             if (DBG) log("isOtaspCallIntent: VoiceMailNumberMissingException => not OTASP");
    469             return false;
    470         }
    471         if (phone.isOtaSpNumber(number)) {
    472             if (DBG) log("isOtaSpNumber: ACTION_CALL to '" + number + "' ==> OTASP call!");
    473             return true;
    474         }
    475         return false;
    476     }
    477 
    478     /**
    479      * Set up for an OTASP call.
    480      *
    481      * This method is called as part of the CallController placeCall() sequence
    482      * before initiating an outgoing OTASP call.
    483      *
    484      * The purpose of this method is mainly to create and initialize the
    485      * OtaUtils instance, along with some other misc pre-OTASP cleanup.
    486      */
    487     public static void setupOtaspCall(Intent intent) {
    488         if (DBG) log("setupOtaspCall(): preparing for OTASP call to " + intent);
    489         PhoneGlobals app = PhoneGlobals.getInstance();
    490 
    491         if (app.otaUtils != null) {
    492             // An OtaUtils instance already exists, presumably from a prior OTASP call.
    493             // Nuke the old one and start this call with a fresh instance.
    494             Log.i(LOG_TAG, "setupOtaspCall: "
    495                   + "OtaUtils already exists; replacing with new instance...");
    496         }
    497 
    498         // Create the OtaUtils instance.
    499         app.otaUtils = new OtaUtils(app.getApplicationContext(), true /* interactive */);
    500         if (DBG) log("- created OtaUtils: " + app.otaUtils);
    501 
    502         // NOTE we still need to call OtaUtils.updateUiWidgets() once the
    503         // InCallScreen instance is ready; see InCallScreen.checkOtaspStateOnResume()
    504 
    505         // Make sure the InCallScreen knows that it needs to switch into OTASP mode.
    506         //
    507         // NOTE in gingerbread and earlier, we used to do
    508         //     setInCallScreenMode(InCallScreenMode.OTA_NORMAL);
    509         // directly in the InCallScreen, back when this check happened inside the InCallScreen.
    510         //
    511         // But now, set the global CdmaOtaInCallScreenUiState object into
    512         // NORMAL mode, which will then cause the InCallScreen (when it
    513         // comes up) to realize that an OTA call is active.
    514 
    515         app.otaUtils.setCdmaOtaInCallScreenUiState(
    516             OtaUtils.CdmaOtaInCallScreenUiState.State.NORMAL);
    517 
    518         // TODO(OTASP): note app.inCallUiState.inCallScreenMode and
    519         // app.cdmaOtaInCallScreenUiState.state are mostly redundant.  Combine them.
    520         // app.inCallUiState.inCallScreenMode = InCallUiState.InCallScreenMode.OTA_NORMAL;
    521 
    522         // TODO(OTASP / bug 5092031): we ideally should call
    523         // otaShowListeningScreen() here to make sure that the DTMF dialpad
    524         // becomes visible at the start of the "*228" call:
    525         //
    526         //  // ...and get the OTASP-specific UI into the right state.
    527         //  app.otaUtils.otaShowListeningScreen();
    528         //  if (app.otaUtils.mInCallScreen != null) {
    529         //      app.otaUtils.mInCallScreen.requestUpdateScreen();
    530         //  }
    531         //
    532         // But this doesn't actually work; the call to otaShowListeningScreen()
    533         // *doesn't* actually bring up the listening screen, since the
    534         // cdmaOtaConfigData.otaShowListeningScreen config parameter hasn't been
    535         // initialized (we haven't run readXmlSettings() yet at this point!)
    536 
    537         // Also, since the OTA call is now just starting, clear out
    538         // the "committed" flag in app.cdmaOtaProvisionData.
    539         if (app.cdmaOtaProvisionData != null) {
    540             app.cdmaOtaProvisionData.isOtaCallCommitted = false;
    541         }
    542     }
    543 
    544     private void setSpeaker(boolean state) {
    545         if (DBG) log("setSpeaker : " + state );
    546 
    547         if (!mInteractive) {
    548             if (DBG) log("non-interactive mode, ignoring setSpeaker.");
    549             return;
    550         }
    551 
    552         if (state == PhoneUtils.isSpeakerOn(mContext)) {
    553             if (DBG) log("no change. returning");
    554             return;
    555         }
    556 
    557         PhoneUtils.turnOnSpeaker(mContext, state, true);
    558     }
    559 
    560     /**
    561      * Handles OTA Provision events from the telephony layer.
    562      * These events come in to this method whether or not
    563      * the InCallScreen is visible.
    564      *
    565      * Possible events are:
    566      * OTA Commit Event - OTA provisioning was successful
    567      * SPC retries exceeded - SPC failure retries has exceeded, and Phone needs to
    568      *    power down.
    569      */
    570     public void onOtaProvisionStatusChanged(AsyncResult r) {
    571         int OtaStatus[] = (int[]) r.result;
    572         if (DBG) log("Provision status event!");
    573         if (DBG) log("onOtaProvisionStatusChanged(): status = "
    574                      + OtaStatus[0] + " ==> " + otaProvisionStatusToString(OtaStatus[0]));
    575 
    576         // In practice, in a normal successful OTASP call, events come in as follows:
    577         //   - SPL_UNLOCKED within a couple of seconds after the call starts
    578         //   - then a delay of around 45 seconds
    579         //   - then PRL_DOWNLOADED and MDN_DOWNLOADED and COMMITTED within a span of 2 seconds
    580 
    581         switch(OtaStatus[0]) {
    582             case Phone.CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED:
    583                 if (DBG) log("onOtaProvisionStatusChanged(): RETRIES EXCEEDED");
    584                 updateOtaspProgress();
    585                 mApplication.cdmaOtaProvisionData.otaSpcUptime = SystemClock.elapsedRealtime();
    586                 if (mInteractive) {
    587                     otaShowSpcErrorNotice(OTA_SPC_TIMEOUT);
    588                 } else {
    589                     sendOtaspResult(OTASP_FAILURE_SPC_RETRIES);
    590                 }
    591                 // Power.shutdown();
    592                 break;
    593 
    594             case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
    595                 if (DBG) {
    596                     log("onOtaProvisionStatusChanged(): DONE, isOtaCallCommitted set to true");
    597                 }
    598                 mApplication.cdmaOtaProvisionData.isOtaCallCommitted = true;
    599                 if (mApplication.cdmaOtaScreenState.otaScreenState !=
    600                     CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED) {
    601                     updateOtaspProgress();
    602                 }
    603 
    604                 break;
    605 
    606             case Phone.CDMA_OTA_PROVISION_STATUS_SPL_UNLOCKED:
    607             case Phone.CDMA_OTA_PROVISION_STATUS_A_KEY_EXCHANGED:
    608             case Phone.CDMA_OTA_PROVISION_STATUS_SSD_UPDATED:
    609             case Phone.CDMA_OTA_PROVISION_STATUS_NAM_DOWNLOADED:
    610             case Phone.CDMA_OTA_PROVISION_STATUS_MDN_DOWNLOADED:
    611             case Phone.CDMA_OTA_PROVISION_STATUS_IMSI_DOWNLOADED:
    612             case Phone.CDMA_OTA_PROVISION_STATUS_PRL_DOWNLOADED:
    613             case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STARTED:
    614             case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED:
    615             case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_ABORTED:
    616                 // Only update progress when OTA call is in normal state
    617                 if (getCdmaOtaInCallScreenUiState() == CdmaOtaInCallScreenUiState.State.NORMAL) {
    618                     if (DBG) log("onOtaProvisionStatusChanged(): change to ProgressScreen");
    619                     updateOtaspProgress();
    620                 }
    621                 break;
    622 
    623             default:
    624                 if (DBG) log("onOtaProvisionStatusChanged(): Ignoring OtaStatus " + OtaStatus[0]);
    625                 break;
    626         }
    627     }
    628 
    629     /**
    630      * Handle a disconnect event from the OTASP call.
    631      */
    632     public void onOtaspDisconnect() {
    633         if (DBG) log("onOtaspDisconnect()...");
    634         // We only handle this event explicitly in non-interactive mode.
    635         // (In interactive mode, the InCallScreen does any post-disconnect
    636         // cleanup.)
    637         if (!mInteractive) {
    638             // Send a success or failure indication back to our caller.
    639             updateNonInteractiveOtaSuccessFailure();
    640         }
    641         cleanOtaScreen(true);
    642     }
    643 
    644     private void otaShowHome() {
    645         if (DBG) log("otaShowHome()...");
    646         mApplication.cdmaOtaScreenState.otaScreenState =
    647                 CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
    648         // mInCallScreen.endInCallScreenSession();
    649         Intent intent = new Intent(Intent.ACTION_MAIN);
    650         intent.addCategory (Intent.CATEGORY_HOME);
    651         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    652         mContext.startActivityAsUser(intent, UserHandle.CURRENT);
    653         return;
    654     }
    655 
    656     private void otaSkipActivation() {
    657         if (DBG) log("otaSkipActivation()...");
    658 
    659         sendOtaspResult(OTASP_USER_SKIPPED);
    660 
    661         // if (mInteractive) mInCallScreen.finish();
    662         return;
    663     }
    664 
    665     /**
    666      * Actually initiate the OTASP call.  This method is triggered by the
    667      * onscreen "Activate" button, and is only used in interactive mode.
    668      */
    669     private void otaPerformActivation() {
    670         if (DBG) log("otaPerformActivation()...");
    671         if (!mInteractive) {
    672             // We shouldn't ever get here in non-interactive mode!
    673             Log.w(LOG_TAG, "otaPerformActivation: not interactive!");
    674             return;
    675         }
    676 
    677         if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
    678             // Place an outgoing call to the special OTASP number:
    679             Intent newIntent = new Intent(Intent.ACTION_CALL);
    680             newIntent.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, OTASP_NUMBER, null));
    681 
    682             // Initiate the outgoing call:
    683             mApplication.callController.placeCall(newIntent);
    684 
    685             // ...and get the OTASP-specific UI into the right state.
    686             otaShowListeningScreen();
    687             // mInCallScreen.requestUpdateScreen();
    688         }
    689         return;
    690     }
    691 
    692     /**
    693      * Show Activation Screen when phone powers up and OTA provision is
    694      * required. Also shown when activation fails and user needs
    695      * to re-attempt it. Contains ACTIVATE and SKIP buttons
    696      * which allow user to start OTA activation or skip the activation process.
    697      */
    698     public void otaShowActivateScreen() {
    699         if (DBG) log("otaShowActivateScreen()...");
    700         if (mApplication.cdmaOtaConfigData.otaShowActivationScreen
    701                 == OTA_SHOW_ACTIVATION_SCREEN_ON) {
    702             if (DBG) log("otaShowActivateScreen(): show activation screen");
    703             if (!isDialerOpened()) {
    704                 otaScreenInitialize();
    705                 mOtaWidgetData.otaSkipButton.setVisibility(sIsWizardMode ?
    706                         View.VISIBLE : View.INVISIBLE);
    707                 mOtaWidgetData.otaTextActivate.setVisibility(View.VISIBLE);
    708                 mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.VISIBLE);
    709             }
    710             mApplication.cdmaOtaScreenState.otaScreenState =
    711                     CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION;
    712         } else {
    713             if (DBG) log("otaShowActivateScreen(): show home screen");
    714             otaShowHome();
    715         }
    716      }
    717 
    718     /**
    719      * Show "Listen for Instruction" screen during OTA call. Shown when OTA Call
    720      * is initiated and user needs to listen for network instructions and press
    721      * appropriate DTMF digits to proceed to the "Programming in Progress" phase.
    722      */
    723     private void otaShowListeningScreen() {
    724         if (DBG) log("otaShowListeningScreen()...");
    725         if (!mInteractive) {
    726             // We shouldn't ever get here in non-interactive mode!
    727             Log.w(LOG_TAG, "otaShowListeningScreen: not interactive!");
    728             return;
    729         }
    730 
    731         if (mApplication.cdmaOtaConfigData.otaShowListeningScreen
    732                 == OTA_SHOW_LISTENING_SCREEN_ON) {
    733             if (DBG) log("otaShowListeningScreen(): show listening screen");
    734             if (!isDialerOpened()) {
    735                 otaScreenInitialize();
    736                 mOtaWidgetData.otaTextListenProgress.setVisibility(View.VISIBLE);
    737                 mOtaWidgetData.otaTextListenProgress.setText(R.string.ota_listen);
    738                 // mOtaWidgetData.otaDtmfDialerView.setVisibility(View.VISIBLE);
    739                 mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.VISIBLE);
    740                 mOtaWidgetData.otaSpeakerButton.setVisibility(View.VISIBLE);
    741                 boolean speakerOn = PhoneUtils.isSpeakerOn(mContext);
    742                 mOtaWidgetData.otaSpeakerButton.setChecked(speakerOn);
    743             }
    744             mApplication.cdmaOtaScreenState.otaScreenState =
    745                     CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING;
    746         } else {
    747             if (DBG) log("otaShowListeningScreen(): show progress screen");
    748             otaShowInProgressScreen();
    749         }
    750     }
    751 
    752     /**
    753      * Do any necessary updates (of onscreen UI, for example)
    754      * based on the latest status of the OTASP call.
    755      */
    756     private void updateOtaspProgress() {
    757         if (DBG) log("updateOtaspProgress()...  mInteractive = " + mInteractive);
    758         if (mInteractive) {
    759             // On regular phones we just call through to
    760             // otaShowInProgressScreen(), which updates the
    761             // InCallScreen's onscreen UI.
    762             otaShowInProgressScreen();
    763         } else {
    764             // We're not using the InCallScreen to show OTA progress.
    765 
    766             // For now, at least, there's nothing to do here.
    767             // The overall "success" or "failure" indication we send back
    768             // (to our caller) is triggered by the DISCONNECT event;
    769             // see updateNonInteractiveOtaSuccessFailure().
    770 
    771             // But if we ever need to send *intermediate* progress updates back
    772             // to our caller, we'd do that here, possbily using the same
    773             // PendingIntent that we already use to indicate success or failure.
    774         }
    775     }
    776 
    777     /**
    778      * When a non-interactive OTASP call completes, send a success or
    779      * failure indication back to our caller.
    780      *
    781      * This is basically the non-interactive equivalent of
    782      * otaShowSuccessFailure().
    783      */
    784     private void updateNonInteractiveOtaSuccessFailure() {
    785         // This is basically the same logic as otaShowSuccessFailure(): we
    786         // check the isOtaCallCommitted bit, and if that's true it means
    787         // that activation was successful.
    788 
    789         if (DBG) log("updateNonInteractiveOtaSuccessFailure(): isOtaCallCommitted = "
    790                      + mApplication.cdmaOtaProvisionData.isOtaCallCommitted);
    791         int resultCode =
    792                 mApplication.cdmaOtaProvisionData.isOtaCallCommitted
    793                 ? OTASP_SUCCESS : OTASP_FAILURE;
    794         sendOtaspResult(resultCode);
    795     }
    796 
    797     /**
    798      * Sends the specified OTASP result code back to our caller (presumably
    799      * SetupWizard) via the PendingIntent that they originally sent along with
    800      * the ACTION_PERFORM_CDMA_PROVISIONING intent.
    801      */
    802     private void sendOtaspResult(int resultCode) {
    803         if (DBG) log("sendOtaspResult: resultCode = " + resultCode);
    804 
    805         // Pass the success or failure indication back to our caller by
    806         // adding an additional extra to the PendingIntent we already
    807         // have.
    808         // (NB: there's a PendingIntent send() method that takes a resultCode
    809         // directly, but we can't use that here since that call is only
    810         // meaningful for pending intents that are actually used as activity
    811         // results.)
    812 
    813         Intent extraStuff = new Intent();
    814         extraStuff.putExtra(EXTRA_OTASP_RESULT_CODE, resultCode);
    815         // When we call PendingIntent.send() below, the extras from this
    816         // intent will get merged with any extras already present in
    817         // cdmaOtaScreenState.otaspResultCodePendingIntent.
    818 
    819         if (mApplication.cdmaOtaScreenState == null) {
    820             Log.e(LOG_TAG, "updateNonInteractiveOtaSuccessFailure: no cdmaOtaScreenState object!");
    821             return;
    822         }
    823         if (mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent == null) {
    824             Log.w(LOG_TAG, "updateNonInteractiveOtaSuccessFailure: "
    825                   + "null otaspResultCodePendingIntent!");
    826             return;
    827         }
    828 
    829         try {
    830             if (DBG) log("- sendOtaspResult:  SENDING PENDING INTENT: " +
    831                          mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent);
    832             mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent.send(
    833                     mContext,
    834                     0, /* resultCode (unused) */
    835                     extraStuff);
    836         } catch (CanceledException e) {
    837             // should never happen because no code cancels the pending intent right now,
    838             Log.e(LOG_TAG, "PendingIntent send() failed: " + e);
    839         }
    840     }
    841 
    842     /**
    843      * Show "Programming In Progress" screen during OTA call. Shown when OTA
    844      * provisioning is in progress after user has selected an option.
    845      */
    846     private void otaShowInProgressScreen() {
    847         if (DBG) log("otaShowInProgressScreen()...");
    848         if (!mInteractive) {
    849             // We shouldn't ever get here in non-interactive mode!
    850             Log.w(LOG_TAG, "otaShowInProgressScreen: not interactive!");
    851             return;
    852         }
    853 
    854         mApplication.cdmaOtaScreenState.otaScreenState =
    855             CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS;
    856 
    857         if ((mOtaWidgetData == null) /* || (mInCallScreen == null) */) {
    858             Log.w(LOG_TAG, "otaShowInProgressScreen: UI widgets not set up yet!");
    859 
    860             // TODO(OTASP): our CdmaOtaScreenState is now correct; we just set
    861             // it to OTA_STATUS_PROGRESS.  But we still need to make sure that
    862             // when the InCallScreen eventually comes to the foreground, it
    863             // notices that state and does all the same UI updating we do below.
    864             return;
    865         }
    866 
    867         if (!isDialerOpened()) {
    868             otaScreenInitialize();
    869             mOtaWidgetData.otaTextListenProgress.setVisibility(View.VISIBLE);
    870             mOtaWidgetData.otaTextListenProgress.setText(R.string.ota_progress);
    871             mOtaWidgetData.otaTextProgressBar.setVisibility(View.VISIBLE);
    872             mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.VISIBLE);
    873             mOtaWidgetData.otaSpeakerButton.setVisibility(View.VISIBLE);
    874             boolean speakerOn = PhoneUtils.isSpeakerOn(mContext);
    875             mOtaWidgetData.otaSpeakerButton.setChecked(speakerOn);
    876         }
    877     }
    878 
    879     /**
    880      * Show programming failure dialog when OTA provisioning fails.
    881      * If OTA provisioning attempts fail more than 3 times, then unsuccessful
    882      * dialog is shown. Otherwise a two-second notice is shown with unsuccessful
    883      * information. When notice expires, phone returns to activation screen.
    884      */
    885     private void otaShowProgramFailure(int length) {
    886         if (DBG) log("otaShowProgramFailure()...");
    887         mApplication.cdmaOtaProvisionData.activationCount++;
    888         if ((mApplication.cdmaOtaProvisionData.activationCount <
    889                 mApplication.cdmaOtaConfigData.otaShowActivateFailTimes)
    890                 && (mApplication.cdmaOtaConfigData.otaShowActivationScreen ==
    891                 OTA_SHOW_ACTIVATION_SCREEN_ON)) {
    892             if (DBG) log("otaShowProgramFailure(): activationCount"
    893                     + mApplication.cdmaOtaProvisionData.activationCount);
    894             if (DBG) log("otaShowProgramFailure(): show failure notice");
    895             otaShowProgramFailureNotice(length);
    896         } else {
    897             if (DBG) log("otaShowProgramFailure(): show failure dialog");
    898             otaShowProgramFailureDialog();
    899         }
    900     }
    901 
    902     /**
    903      * Show either programming success dialog when OTA provisioning succeeds, or
    904      * programming failure dialog when it fails. See {@link #otaShowProgramFailure}
    905      * for more details.
    906      */
    907     public void otaShowSuccessFailure() {
    908         if (DBG) log("otaShowSuccessFailure()...");
    909         if (!mInteractive) {
    910             // We shouldn't ever get here in non-interactive mode!
    911             Log.w(LOG_TAG, "otaShowSuccessFailure: not interactive!");
    912             return;
    913         }
    914 
    915         otaScreenInitialize();
    916         if (DBG) log("otaShowSuccessFailure(): isOtaCallCommitted"
    917                 + mApplication.cdmaOtaProvisionData.isOtaCallCommitted);
    918         if (mApplication.cdmaOtaProvisionData.isOtaCallCommitted) {
    919             if (DBG) log("otaShowSuccessFailure(), show success dialog");
    920             otaShowProgramSuccessDialog();
    921         } else {
    922             if (DBG) log("otaShowSuccessFailure(), show failure dialog");
    923             otaShowProgramFailure(OTA_FAILURE_DIALOG_TIMEOUT);
    924         }
    925         return;
    926     }
    927 
    928     /**
    929      * Show programming failure dialog when OTA provisioning fails more than 3
    930      * times.
    931      */
    932     private void otaShowProgramFailureDialog() {
    933         if (DBG) log("otaShowProgramFailureDialog()...");
    934         mApplication.cdmaOtaScreenState.otaScreenState =
    935                 CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG;
    936         mOtaWidgetData.otaTitle.setText(R.string.ota_title_problem_with_activation);
    937         mOtaWidgetData.otaTextSuccessFail.setVisibility(View.VISIBLE);
    938         mOtaWidgetData.otaTextSuccessFail.setText(R.string.ota_unsuccessful);
    939         mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.VISIBLE);
    940         mOtaWidgetData.otaTryAgainButton.setVisibility(View.VISIBLE);
    941         //close the dialer if open
    942         // if (isDialerOpened()) {
    943         //     mOtaCallCardDtmfDialer.closeDialer(false);
    944         // }
    945     }
    946 
    947     /**
    948      * Show programming success dialog when OTA provisioning succeeds.
    949      */
    950     private void otaShowProgramSuccessDialog() {
    951         if (DBG) log("otaShowProgramSuccessDialog()...");
    952         mApplication.cdmaOtaScreenState.otaScreenState =
    953                 CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG;
    954         mOtaWidgetData.otaTitle.setText(R.string.ota_title_activate_success);
    955         mOtaWidgetData.otaTextSuccessFail.setVisibility(View.VISIBLE);
    956         mOtaWidgetData.otaTextSuccessFail.setText(R.string.ota_successful);
    957         mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.VISIBLE);
    958         mOtaWidgetData.otaNextButton.setVisibility(View.VISIBLE);
    959         //close the dialer if open
    960         // if (isDialerOpened()) {
    961         //     mOtaCallCardDtmfDialer.closeDialer(false);
    962         // }
    963     }
    964 
    965     /**
    966      * Show SPC failure notice when SPC attempts exceed 15 times.
    967      * During OTA provisioning, if SPC code is incorrect OTA provisioning will
    968      * fail. When SPC attempts are over 15, it shows SPC failure notice for one minute and
    969      * then phone will power down.
    970      */
    971     private void otaShowSpcErrorNotice(int length) {
    972         if (DBG) log("otaShowSpcErrorNotice()...");
    973         if (mOtaWidgetData.spcErrorDialog == null) {
    974             mApplication.cdmaOtaProvisionData.inOtaSpcState = true;
    975             DialogInterface.OnKeyListener keyListener;
    976             keyListener = new DialogInterface.OnKeyListener() {
    977                 public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
    978                     log("Ignoring key events...");
    979                     return true;
    980                 }};
    981             mOtaWidgetData.spcErrorDialog = new AlertDialog.Builder(null /* mInCallScreen */)
    982                     .setMessage(R.string.ota_spc_failure)
    983                     .setOnKeyListener(keyListener)
    984                     .create();
    985             mOtaWidgetData.spcErrorDialog.getWindow().addFlags(
    986                     WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
    987                     | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    988             mOtaWidgetData.spcErrorDialog.show();
    989             //close the dialer if open
    990             // if (isDialerOpened()) {
    991             //     mOtaCallCardDtmfDialer.closeDialer(false);
    992             // }
    993             long noticeTime = length*1000;
    994             if (DBG) log("otaShowSpcErrorNotice(), remaining SPC noticeTime" + noticeTime);
    995             // mInCallScreen.requestCloseSpcErrorNotice(noticeTime);
    996         }
    997     }
    998 
    999     /**
   1000      * When SPC notice times out, force phone to power down.
   1001      */
   1002     public void onOtaCloseSpcNotice() {
   1003         if (DBG) log("onOtaCloseSpcNotice(), send shutdown intent");
   1004         Intent shutdown = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
   1005         shutdown.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
   1006         shutdown.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   1007         mContext.startActivity(shutdown);
   1008     }
   1009 
   1010     /**
   1011      * Show two-second notice when OTA provisioning fails and number of failed attempts
   1012      * is less then 3.
   1013      */
   1014     private void otaShowProgramFailureNotice(int length) {
   1015         if (DBG) log("otaShowProgramFailureNotice()...");
   1016         if (mOtaWidgetData.otaFailureDialog == null) {
   1017             mOtaWidgetData.otaFailureDialog = new AlertDialog.Builder(null /* mInCallScreen */)
   1018                     .setMessage(R.string.ota_failure)
   1019                     .create();
   1020             mOtaWidgetData.otaFailureDialog.getWindow().addFlags(
   1021                     WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
   1022                     | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
   1023             mOtaWidgetData.otaFailureDialog.show();
   1024 
   1025             long noticeTime = length*1000;
   1026             // mInCallScreen.requestCloseOtaFailureNotice(noticeTime);
   1027         }
   1028     }
   1029 
   1030     /**
   1031      * Handle OTA unsuccessful notice expiry. Dismisses the
   1032      * two-second notice and shows the activation screen.
   1033      */
   1034     public void onOtaCloseFailureNotice() {
   1035         if (DBG) log("onOtaCloseFailureNotice()...");
   1036         if (mOtaWidgetData.otaFailureDialog != null) {
   1037             mOtaWidgetData.otaFailureDialog.dismiss();
   1038             mOtaWidgetData.otaFailureDialog = null;
   1039         }
   1040         otaShowActivateScreen();
   1041     }
   1042 
   1043     /**
   1044      * Initialize all OTA UI elements to be gone. Also set inCallPanel,
   1045      * callCard and the dialpad handle to be gone. This is called before any OTA screen
   1046      * gets drawn.
   1047      */
   1048     private void otaScreenInitialize() {
   1049         if (DBG) log("otaScreenInitialize()...");
   1050 
   1051         if (!mInteractive) {
   1052             // We should never be doing anything with UI elements in
   1053             // non-interactive mode.
   1054             Log.w(LOG_TAG, "otaScreenInitialize: not interactive!");
   1055             return;
   1056         }
   1057 
   1058         // if (mInCallTouchUi != null) mInCallTouchUi.setVisibility(View.GONE);
   1059         // if (mCallCard != null) {
   1060         //     mCallCard.setVisibility(View.GONE);
   1061         //     // TODO: try removing this.
   1062         //     mCallCard.hideCallCardElements();
   1063         // }
   1064 
   1065         mOtaWidgetData.otaTitle.setText(R.string.ota_title_activate);
   1066         mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
   1067         mOtaWidgetData.otaTextListenProgress.setVisibility(View.GONE);
   1068         mOtaWidgetData.otaTextProgressBar.setVisibility(View.GONE);
   1069         mOtaWidgetData.otaTextSuccessFail.setVisibility(View.GONE);
   1070         mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
   1071         mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
   1072         mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
   1073         // mOtaWidgetData.otaDtmfDialerView.setVisibility(View.GONE);
   1074         mOtaWidgetData.otaSpeakerButton.setVisibility(View.GONE);
   1075         mOtaWidgetData.otaTryAgainButton.setVisibility(View.GONE);
   1076         mOtaWidgetData.otaNextButton.setVisibility(View.GONE);
   1077         mOtaWidgetData.otaUpperWidgets.setVisibility(View.VISIBLE);
   1078         mOtaWidgetData.otaSkipButton.setVisibility(View.VISIBLE);
   1079     }
   1080 
   1081     public void hideOtaScreen() {
   1082         if (DBG) log("hideOtaScreen()...");
   1083 
   1084         mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
   1085         mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
   1086         mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
   1087         mOtaWidgetData.otaUpperWidgets.setVisibility(View.GONE);
   1088     }
   1089 
   1090     public boolean isDialerOpened() {
   1091         // boolean retval = (mOtaCallCardDtmfDialer != null && mOtaCallCardDtmfDialer.isOpened());
   1092         boolean retval = false;
   1093         if (DBG) log("- isDialerOpened() ==> " + retval);
   1094         return retval;
   1095     }
   1096 
   1097     /**
   1098      * Show the appropriate OTA screen based on the current state of OTA call.
   1099      *
   1100      * This is called from the InCallScreen when the screen needs to be
   1101      * refreshed (and thus is only ever used in interactive mode.)
   1102      *
   1103      * Since this is called as part of the InCallScreen.updateScreen() sequence,
   1104      * this method does *not* post an mInCallScreen.requestUpdateScreen()
   1105      * request.
   1106      */
   1107     public void otaShowProperScreen() {
   1108         if (DBG) log("otaShowProperScreen()...");
   1109         if (!mInteractive) {
   1110             // We shouldn't ever get here in non-interactive mode!
   1111             Log.w(LOG_TAG, "otaShowProperScreen: not interactive!");
   1112             return;
   1113         }
   1114 
   1115         // if ((mInCallScreen != null) && mInCallScreen.isForegroundActivity()) {
   1116         //     if (DBG) log("otaShowProperScreen(): InCallScreen in foreground, currentstate = "
   1117         //             + mApplication.cdmaOtaScreenState.otaScreenState);
   1118         //     if (mInCallTouchUi != null) {
   1119         //         mInCallTouchUi.setVisibility(View.GONE);
   1120         //     }
   1121         //     if (mCallCard != null) {
   1122         //         mCallCard.setVisibility(View.GONE);
   1123         //     }
   1124         //     if (mApplication.cdmaOtaScreenState.otaScreenState
   1125         //             == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION) {
   1126         //         otaShowActivateScreen();
   1127         //     } else if (mApplication.cdmaOtaScreenState.otaScreenState
   1128         //             == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING) {
   1129         //         otaShowListeningScreen();
   1130         //     } else if (mApplication.cdmaOtaScreenState.otaScreenState
   1131         //             == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS) {
   1132         //         otaShowInProgressScreen();
   1133         //     }
   1134 
   1135         //     if (mApplication.cdmaOtaProvisionData.inOtaSpcState) {
   1136         //         otaShowSpcErrorNotice(getOtaSpcDisplayTime());
   1137         //     }
   1138         // }
   1139     }
   1140 
   1141     /**
   1142      * Read configuration values for each OTA screen from config.xml.
   1143      * These configuration values control visibility of each screen.
   1144      */
   1145     private void readXmlSettings() {
   1146         if (DBG) log("readXmlSettings()...");
   1147         if (mApplication.cdmaOtaConfigData.configComplete) {
   1148             return;
   1149         }
   1150 
   1151         mApplication.cdmaOtaConfigData.configComplete = true;
   1152         int tmpOtaShowActivationScreen =
   1153                 mContext.getResources().getInteger(R.integer.OtaShowActivationScreen);
   1154         mApplication.cdmaOtaConfigData.otaShowActivationScreen = tmpOtaShowActivationScreen;
   1155         if (DBG) log("readXmlSettings(), otaShowActivationScreen = "
   1156                 + mApplication.cdmaOtaConfigData.otaShowActivationScreen);
   1157 
   1158         int tmpOtaShowListeningScreen =
   1159                 mContext.getResources().getInteger(R.integer.OtaShowListeningScreen);
   1160         mApplication.cdmaOtaConfigData.otaShowListeningScreen = tmpOtaShowListeningScreen;
   1161         if (DBG) log("readXmlSettings(), otaShowListeningScreen = "
   1162                 + mApplication.cdmaOtaConfigData.otaShowListeningScreen);
   1163 
   1164         int tmpOtaShowActivateFailTimes =
   1165                 mContext.getResources().getInteger(R.integer.OtaShowActivateFailTimes);
   1166         mApplication.cdmaOtaConfigData.otaShowActivateFailTimes = tmpOtaShowActivateFailTimes;
   1167         if (DBG) log("readXmlSettings(), otaShowActivateFailTimes = "
   1168                 + mApplication.cdmaOtaConfigData.otaShowActivateFailTimes);
   1169 
   1170         int tmpOtaPlaySuccessFailureTone =
   1171                 mContext.getResources().getInteger(R.integer.OtaPlaySuccessFailureTone);
   1172         mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone = tmpOtaPlaySuccessFailureTone;
   1173         if (DBG) log("readXmlSettings(), otaPlaySuccessFailureTone = "
   1174                 + mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone);
   1175     }
   1176 
   1177     /**
   1178      * Handle the click events for OTA buttons.
   1179      */
   1180     public void onClickHandler(int id) {
   1181         switch (id) {
   1182             case R.id.otaEndButton:
   1183                 onClickOtaEndButton();
   1184                 break;
   1185 
   1186             case R.id.otaSpeakerButton:
   1187                 onClickOtaSpeakerButton();
   1188                 break;
   1189 
   1190             case R.id.otaActivateButton:
   1191                 onClickOtaActivateButton();
   1192                 break;
   1193 
   1194             case R.id.otaSkipButton:
   1195                 onClickOtaActivateSkipButton();
   1196                 break;
   1197 
   1198             case R.id.otaNextButton:
   1199                 onClickOtaActivateNextButton();
   1200                 break;
   1201 
   1202             case R.id.otaTryAgainButton:
   1203                 onClickOtaTryAgainButton();
   1204                 break;
   1205 
   1206             default:
   1207                 if (DBG) log ("onClickHandler: received a click event for unrecognized id");
   1208                 break;
   1209         }
   1210     }
   1211 
   1212     private void onClickOtaTryAgainButton() {
   1213         if (DBG) log("Activation Try Again Clicked!");
   1214         if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
   1215             otaShowActivateScreen();
   1216         }
   1217     }
   1218 
   1219     private void onClickOtaEndButton() {
   1220         if (DBG) log("Activation End Call Button Clicked!");
   1221         if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
   1222             if (PhoneUtils.hangup(mApplication.mCM) == false) {
   1223                 // If something went wrong when placing the OTA call,
   1224                 // the screen is not updated by the call disconnect
   1225                 // handler and we have to do it here
   1226                 setSpeaker(false);
   1227                 // mInCallScreen.handleOtaCallEnd();
   1228             }
   1229         }
   1230     }
   1231 
   1232     private void onClickOtaSpeakerButton() {
   1233         if (DBG) log("OTA Speaker button Clicked!");
   1234         if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
   1235             boolean isChecked = !PhoneUtils.isSpeakerOn(mContext);
   1236             setSpeaker(isChecked);
   1237         }
   1238     }
   1239 
   1240     private void onClickOtaActivateButton() {
   1241         if (DBG) log("Call Activation Clicked!");
   1242         otaPerformActivation();
   1243     }
   1244 
   1245     private void onClickOtaActivateSkipButton() {
   1246         if (DBG) log("Activation Skip Clicked!");
   1247         DialogInterface.OnKeyListener keyListener;
   1248         keyListener = new DialogInterface.OnKeyListener() {
   1249             public boolean onKey(DialogInterface dialog, int keyCode,
   1250                     KeyEvent event) {
   1251                 if (DBG) log("Ignoring key events...");
   1252                 return true;
   1253             }
   1254         };
   1255         mOtaWidgetData.otaSkipConfirmationDialog = new AlertDialog.Builder(null /* mInCallScreen */)
   1256                 .setTitle(R.string.ota_skip_activation_dialog_title)
   1257                 .setMessage(R.string.ota_skip_activation_dialog_message)
   1258                 .setPositiveButton(
   1259                     android.R.string.ok,
   1260                     // "OK" means "skip activation".
   1261                     new AlertDialog.OnClickListener() {
   1262                         public void onClick(DialogInterface dialog, int which) {
   1263                             otaSkipActivation();
   1264                         }
   1265                     })
   1266                 .setNegativeButton(
   1267                     android.R.string.cancel,
   1268                     // "Cancel" means just dismiss the dialog.
   1269                     // Don't actually start an activation call.
   1270                     null)
   1271                 .setOnKeyListener(keyListener)
   1272                 .create();
   1273         mOtaWidgetData.otaSkipConfirmationDialog.show();
   1274     }
   1275 
   1276     private void onClickOtaActivateNextButton() {
   1277         if (DBG) log("Dialog Next Clicked!");
   1278         if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
   1279             mApplication.cdmaOtaScreenState.otaScreenState =
   1280                     CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
   1281             otaShowHome();
   1282         }
   1283     }
   1284 
   1285     public void dismissAllOtaDialogs() {
   1286         if (mOtaWidgetData != null) {
   1287             if (mOtaWidgetData.spcErrorDialog != null) {
   1288                 if (DBG) log("- DISMISSING mSpcErrorDialog.");
   1289                 mOtaWidgetData.spcErrorDialog.dismiss();
   1290                 mOtaWidgetData.spcErrorDialog = null;
   1291             }
   1292             if (mOtaWidgetData.otaFailureDialog != null) {
   1293                 if (DBG) log("- DISMISSING mOtaFailureDialog.");
   1294                 mOtaWidgetData.otaFailureDialog.dismiss();
   1295                 mOtaWidgetData.otaFailureDialog = null;
   1296             }
   1297         }
   1298     }
   1299 
   1300     private int getOtaSpcDisplayTime() {
   1301         if (DBG) log("getOtaSpcDisplayTime()...");
   1302         int tmpSpcTime = 1;
   1303         if (mApplication.cdmaOtaProvisionData.inOtaSpcState) {
   1304             long tmpOtaSpcRunningTime = 0;
   1305             long tmpOtaSpcLeftTime = 0;
   1306             tmpOtaSpcRunningTime = SystemClock.elapsedRealtime();
   1307             tmpOtaSpcLeftTime =
   1308                 tmpOtaSpcRunningTime - mApplication.cdmaOtaProvisionData.otaSpcUptime;
   1309             if (tmpOtaSpcLeftTime >= OTA_SPC_TIMEOUT*1000) {
   1310                 tmpSpcTime = 1;
   1311             } else {
   1312                 tmpSpcTime = OTA_SPC_TIMEOUT - (int)tmpOtaSpcLeftTime/1000;
   1313             }
   1314         }
   1315         if (DBG) log("getOtaSpcDisplayTime(), time for SPC error notice: " + tmpSpcTime);
   1316         return tmpSpcTime;
   1317     }
   1318 
   1319     /**
   1320      * Initialize the OTA widgets for all OTA screens.
   1321      */
   1322     private void initOtaInCallScreen() {
   1323         if (DBG) log("initOtaInCallScreen()...");
   1324         // mOtaWidgetData.otaTitle = (TextView) mInCallScreen.findViewById(R.id.otaTitle);
   1325         // mOtaWidgetData.otaTextActivate = (TextView) mInCallScreen.findViewById(R.id.otaActivate);
   1326         mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
   1327         // mOtaWidgetData.otaTextListenProgress =
   1328         //         (TextView) mInCallScreen.findViewById(R.id.otaListenProgress);
   1329         // mOtaWidgetData.otaTextProgressBar =
   1330         //         (ProgressBar) mInCallScreen.findViewById(R.id.progress_large);
   1331         mOtaWidgetData.otaTextProgressBar.setIndeterminate(true);
   1332         // mOtaWidgetData.otaTextSuccessFail =
   1333         //         (TextView) mInCallScreen.findViewById(R.id.otaSuccessFailStatus);
   1334 
   1335         // mOtaWidgetData.otaUpperWidgets =
   1336         //         (ViewGroup) mInCallScreen.findViewById(R.id.otaUpperWidgets);
   1337         // mOtaWidgetData.callCardOtaButtonsListenProgress =
   1338         //         (View) mInCallScreen.findViewById(R.id.callCardOtaListenProgress);
   1339         // mOtaWidgetData.callCardOtaButtonsActivate =
   1340         //         (View) mInCallScreen.findViewById(R.id.callCardOtaActivate);
   1341         // mOtaWidgetData.callCardOtaButtonsFailSuccess =
   1342         //         (View) mInCallScreen.findViewById(R.id.callCardOtaFailOrSuccessful);
   1343 
   1344         // mOtaWidgetData.otaEndButton = (Button) mInCallScreen.findViewById(R.id.otaEndButton);
   1345         // mOtaWidgetData.otaEndButton.setOnClickListener(mInCallScreen);
   1346         // mOtaWidgetData.otaSpeakerButton =
   1347         //         (ToggleButton) mInCallScreen.findViewById(R.id.otaSpeakerButton);
   1348         // mOtaWidgetData.otaSpeakerButton.setOnClickListener(mInCallScreen);
   1349         // mOtaWidgetData.otaActivateButton =
   1350         //         (Button) mInCallScreen.findViewById(R.id.otaActivateButton);
   1351         // mOtaWidgetData.otaActivateButton.setOnClickListener(mInCallScreen);
   1352         // mOtaWidgetData.otaSkipButton = (Button) mInCallScreen.findViewById(R.id.otaSkipButton);
   1353         // mOtaWidgetData.otaSkipButton.setOnClickListener(mInCallScreen);
   1354         // mOtaWidgetData.otaNextButton = (Button) mInCallScreen.findViewById(R.id.otaNextButton);
   1355         // mOtaWidgetData.otaNextButton.setOnClickListener(mInCallScreen);
   1356         // mOtaWidgetData.otaTryAgainButton =
   1357         //         (Button) mInCallScreen.findViewById(R.id.otaTryAgainButton);
   1358         // mOtaWidgetData.otaTryAgainButton.setOnClickListener(mInCallScreen);
   1359 
   1360         // mOtaWidgetData.otaDtmfDialerView =
   1361         //         (DTMFTwelveKeyDialerView) mInCallScreen.findViewById(R.id.otaDtmfDialerView);
   1362         // Sanity-check: the otaDtmfDialerView widget should *always* be present.
   1363         // if (mOtaWidgetData.otaDtmfDialerView == null) {
   1364         //     throw new IllegalStateException("initOtaInCallScreen: couldn't find otaDtmfDialerView");
   1365         // }
   1366 
   1367         // Create a new DTMFTwelveKeyDialer instance purely for use by the
   1368         // DTMFTwelveKeyDialerView ("otaDtmfDialerView") that comes from
   1369         // otacall_card.xml.
   1370         // mOtaCallCardDtmfDialer = new DTMFTwelveKeyDialer(mInCallScreen,
   1371         //                                                  mOtaWidgetData.otaDtmfDialerView);
   1372 
   1373         // Initialize the new DTMFTwelveKeyDialer instance.  This is
   1374         // needed to play local DTMF tones.
   1375         // mOtaCallCardDtmfDialer.startDialerSession();
   1376 
   1377         // mOtaWidgetData.otaDtmfDialerView.setDialer(mOtaCallCardDtmfDialer);
   1378     }
   1379 
   1380     /**
   1381      * Clear out all OTA UI widget elements. Needs to get called
   1382      * when OTA call ends or InCallScreen is destroyed.
   1383      * @param disableSpeaker parameter control whether Speaker should be turned off.
   1384      */
   1385     public void cleanOtaScreen(boolean disableSpeaker) {
   1386         if (DBG) log("OTA ends, cleanOtaScreen!");
   1387 
   1388         mApplication.cdmaOtaScreenState.otaScreenState =
   1389                 CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
   1390         mApplication.cdmaOtaProvisionData.isOtaCallCommitted = false;
   1391         mApplication.cdmaOtaProvisionData.isOtaCallIntentProcessed = false;
   1392         mApplication.cdmaOtaProvisionData.inOtaSpcState = false;
   1393         mApplication.cdmaOtaProvisionData.activationCount = 0;
   1394         mApplication.cdmaOtaProvisionData.otaSpcUptime = 0;
   1395         mApplication.cdmaOtaInCallScreenUiState.state = State.UNDEFINED;
   1396 
   1397         if (mInteractive && (mOtaWidgetData != null)) {
   1398             // if (mInCallTouchUi != null) mInCallTouchUi.setVisibility(View.VISIBLE);
   1399             // if (mCallCard != null) {
   1400             //     mCallCard.setVisibility(View.VISIBLE);
   1401             //     mCallCard.hideCallCardElements();
   1402             // }
   1403 
   1404             // Free resources from the DTMFTwelveKeyDialer instance we created
   1405             // in initOtaInCallScreen().
   1406             // if (mOtaCallCardDtmfDialer != null) {
   1407             //     mOtaCallCardDtmfDialer.stopDialerSession();
   1408             // }
   1409 
   1410             mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
   1411             mOtaWidgetData.otaTextListenProgress.setVisibility(View.GONE);
   1412             mOtaWidgetData.otaTextProgressBar.setVisibility(View.GONE);
   1413             mOtaWidgetData.otaTextSuccessFail.setVisibility(View.GONE);
   1414             mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
   1415             mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
   1416             mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
   1417             mOtaWidgetData.otaUpperWidgets.setVisibility(View.GONE);
   1418             // mOtaWidgetData.otaDtmfDialerView.setVisibility(View.GONE);
   1419             mOtaWidgetData.otaNextButton.setVisibility(View.GONE);
   1420             mOtaWidgetData.otaTryAgainButton.setVisibility(View.GONE);
   1421         }
   1422 
   1423         // turn off the speaker in case it was turned on
   1424         // but the OTA call could not be completed
   1425         if (disableSpeaker) {
   1426             setSpeaker(false);
   1427         }
   1428     }
   1429 
   1430     /**
   1431      * Defines OTA information that needs to be maintained during
   1432      * an OTA call when display orientation changes.
   1433      */
   1434     public static class CdmaOtaProvisionData {
   1435         public boolean isOtaCallCommitted;
   1436         public boolean isOtaCallIntentProcessed;
   1437         public boolean inOtaSpcState;
   1438         public int activationCount;
   1439         public long otaSpcUptime;
   1440     }
   1441 
   1442     /**
   1443      * Defines OTA screen configuration items read from config.xml
   1444      * and used to control OTA display.
   1445      */
   1446     public static class CdmaOtaConfigData {
   1447         public int otaShowActivationScreen;
   1448         public int otaShowListeningScreen;
   1449         public int otaShowActivateFailTimes;
   1450         public int otaPlaySuccessFailureTone;
   1451         public boolean configComplete;
   1452         public CdmaOtaConfigData() {
   1453             if (DBG) log("CdmaOtaConfigData constructor!");
   1454             otaShowActivationScreen = OTA_SHOW_ACTIVATION_SCREEN_OFF;
   1455             otaShowListeningScreen = OTA_SHOW_LISTENING_SCREEN_OFF;
   1456             otaShowActivateFailTimes = OTA_SHOW_ACTIVATE_FAIL_COUNT_OFF;
   1457             otaPlaySuccessFailureTone = OTA_PLAY_SUCCESS_FAILURE_TONE_OFF;
   1458         }
   1459     }
   1460 
   1461     /**
   1462      * The state of the OTA InCallScreen UI.
   1463      */
   1464     public static class CdmaOtaInCallScreenUiState {
   1465         public enum State {
   1466             UNDEFINED,
   1467             NORMAL,
   1468             ENDED
   1469         }
   1470 
   1471         public State state;
   1472 
   1473         public CdmaOtaInCallScreenUiState() {
   1474             if (DBG) log("CdmaOtaInCallScreenState: constructor init to UNDEFINED");
   1475             state = CdmaOtaInCallScreenUiState.State.UNDEFINED;
   1476         }
   1477     }
   1478 
   1479     /**
   1480      * Save the Ota InCallScreen UI state
   1481      */
   1482     public void setCdmaOtaInCallScreenUiState(CdmaOtaInCallScreenUiState.State state) {
   1483         if (DBG) log("setCdmaOtaInCallScreenState: " + state);
   1484         mApplication.cdmaOtaInCallScreenUiState.state = state;
   1485     }
   1486 
   1487     /**
   1488      * Get the Ota InCallScreen UI state
   1489      */
   1490     public CdmaOtaInCallScreenUiState.State getCdmaOtaInCallScreenUiState() {
   1491         if (DBG) log("getCdmaOtaInCallScreenState: "
   1492                      + mApplication.cdmaOtaInCallScreenUiState.state);
   1493         return mApplication.cdmaOtaInCallScreenUiState.state;
   1494     }
   1495 
   1496     /**
   1497      * The OTA screen state machine.
   1498      */
   1499     public static class CdmaOtaScreenState {
   1500         public enum OtaScreenState {
   1501             OTA_STATUS_UNDEFINED,
   1502             OTA_STATUS_ACTIVATION,
   1503             OTA_STATUS_LISTENING,
   1504             OTA_STATUS_PROGRESS,
   1505             OTA_STATUS_SUCCESS_FAILURE_DLG
   1506         }
   1507 
   1508         public OtaScreenState otaScreenState;
   1509 
   1510         public CdmaOtaScreenState() {
   1511             otaScreenState = OtaScreenState.OTA_STATUS_UNDEFINED;
   1512         }
   1513 
   1514         /**
   1515          * {@link PendingIntent} used to report an OTASP result status code
   1516          * back to our caller. Can be null.
   1517          *
   1518          * Our caller (presumably SetupWizard) may create this PendingIntent,
   1519          * pointing back at itself, and passes it along as an extra with the
   1520          * ACTION_PERFORM_CDMA_PROVISIONING intent.  Then, when there's an
   1521          * OTASP result to report, we send that PendingIntent back, adding an
   1522          * extra called EXTRA_OTASP_RESULT_CODE to indicate the result.
   1523          *
   1524          * Possible result values are the OTASP_RESULT_* constants.
   1525          */
   1526         public PendingIntent otaspResultCodePendingIntent;
   1527     }
   1528 
   1529     /** @see com.android.internal.telephony.Phone */
   1530     private static String otaProvisionStatusToString(int status) {
   1531         switch (status) {
   1532             case Phone.CDMA_OTA_PROVISION_STATUS_SPL_UNLOCKED:
   1533                 return "SPL_UNLOCKED";
   1534             case Phone.CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED:
   1535                 return "SPC_RETRIES_EXCEEDED";
   1536             case Phone.CDMA_OTA_PROVISION_STATUS_A_KEY_EXCHANGED:
   1537                 return "A_KEY_EXCHANGED";
   1538             case Phone.CDMA_OTA_PROVISION_STATUS_SSD_UPDATED:
   1539                 return "SSD_UPDATED";
   1540             case Phone.CDMA_OTA_PROVISION_STATUS_NAM_DOWNLOADED:
   1541                 return "NAM_DOWNLOADED";
   1542             case Phone.CDMA_OTA_PROVISION_STATUS_MDN_DOWNLOADED:
   1543                 return "MDN_DOWNLOADED";
   1544             case Phone.CDMA_OTA_PROVISION_STATUS_IMSI_DOWNLOADED:
   1545                 return "IMSI_DOWNLOADED";
   1546             case Phone.CDMA_OTA_PROVISION_STATUS_PRL_DOWNLOADED:
   1547                 return "PRL_DOWNLOADED";
   1548             case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
   1549                 return "COMMITTED";
   1550             case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STARTED:
   1551                 return "OTAPA_STARTED";
   1552             case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED:
   1553                 return "OTAPA_STOPPED";
   1554             case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_ABORTED:
   1555                 return "OTAPA_ABORTED";
   1556             default:
   1557                 return "<unknown status" + status + ">";
   1558         }
   1559     }
   1560 
   1561     private static int getLteOnCdmaMode(Context context) {
   1562         final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
   1563                 Context.TELEPHONY_SERVICE);
   1564         // If the telephony manager is not available yet, or if it doesn't know the answer yet,
   1565         // try falling back on the system property that may or may not be there
   1566         if (telephonyManager == null
   1567                 || telephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_UNKNOWN) {
   1568             return SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE,
   1569                     PhoneConstants.LTE_ON_CDMA_UNKNOWN);
   1570         }
   1571         return telephonyManager.getLteOnCdmaMode();
   1572     }
   1573 
   1574     private static void log(String msg) {
   1575         Log.d(LOG_TAG, msg);
   1576     }
   1577 
   1578     private static void loge(String msg) {
   1579         Log.e(LOG_TAG, msg);
   1580     }
   1581 }
   1582