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