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