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