OtaUtils.java revision 425b8e3c9846d5e0e76466604b35cad8856d79de
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
17package com.android.phone;
18
19import com.android.internal.telephony.Phone;
20
21import android.app.AlertDialog;
22import android.content.Context;
23import android.content.DialogInterface;
24import android.content.Intent;
25import android.content.pm.ResolveInfo;
26import android.os.AsyncResult;
27import android.os.Handler;
28import android.os.Message;
29import android.os.SystemClock;
30import android.os.SystemProperties;
31import android.provider.Settings;
32
33import android.util.Log;
34import android.view.KeyEvent;
35import android.view.View;
36import android.view.ViewGroup;
37import android.view.ViewStub;
38import android.view.WindowManager;
39
40import android.widget.Button;
41import android.widget.ToggleButton;
42import android.widget.ProgressBar;
43import android.widget.SlidingDrawer;
44import android.widget.TextView;
45
46/**
47 * Handles all OTA Call related logic and UI functionality.
48 * InCallScreen interacts with this class to perform OTA Call
49 */
50
51public class OtaUtils {
52    private static final String LOG_TAG = "OtaUtils";
53    private static final String UNACTIVATED_MIN2_VALUE = "000000";
54    private static final String UNACTIVATED_MIN_VALUE = "1111110111";
55    private static final boolean DBG = (PhoneApp.DBG_LEVEL >= 2);
56
57    public static final int OTA_SHOW_ACTIVATION_SCREEN_OFF = 0;
58    public static final int OTA_SHOW_ACTIVATION_SCREEN_ON = 1;
59    public static final int OTA_SHOW_LISTENING_SCREEN_OFF =0;
60    public static final int OTA_SHOW_LISTENING_SCREEN_ON =1;
61    public static final int OTA_SHOW_ACTIVATE_FAIL_COUNT_OFF = 0;
62    public static final int OTA_SHOW_ACTIVATE_FAIL_COUNT_THREE = 3;
63    public static final int OTA_PLAY_SUCCESS_FAILURE_TONE_OFF = 0;
64    public static final int OTA_PLAY_SUCCESS_FAILURE_TONE_ON = 1;
65
66    // SPC Timeout is 60 seconds
67    public final int OTA_SPC_TIMEOUT = 60;
68    public final int OTA_FAILURE_DIALOG_TIMEOUT = 2;
69
70    private InCallScreen mInCallScreen;
71    private Context mContext;
72    private PhoneApp mApplication;
73    private OtaWidgetData mOtaWidgetData;
74    private ViewGroup mInCallPanel;
75    private CallCard mCallCard;
76    private DTMFTwelveKeyDialer mDialer;
77    private SlidingDrawer mDialerDrawer;
78
79    /**
80     * OtaWidgetData class represent all OTA UI elements
81     */
82    private class OtaWidgetData {
83        public Button otaEndButton;
84        public Button otaActivateButton;
85        public Button otaCancelButton;
86        public Button otaDialogOKButton;
87        public Button otaKeypadButton;
88        public ToggleButton otaSpeakerButton;
89        public View otaCallCardBase;
90        public View callCardOtaButtonsFailSuccess;
91        public ProgressBar otaTextProgressBar;
92        public TextView otaTextSuccessFail;
93        public View callCardOtaButtonsActivate;
94        public View callCardOtaButtonsListenProgress;
95        public TextView otaTextActivate;
96        public TextView otaTextListenProgress;
97        public AlertDialog spcErrorDialog;
98        public AlertDialog otaFailureDialog;
99    }
100
101    public OtaUtils(Context context,
102                    InCallScreen inCallScreen,
103                    ViewGroup inCallPanel,
104                    CallCard callCard,
105                    DTMFTwelveKeyDialer dialer,
106                    SlidingDrawer dialerDrawer) {
107
108        if (DBG) log("Enter OtaUtil constructor");
109
110        mInCallScreen = inCallScreen;
111        mContext = context;
112        mInCallPanel = inCallPanel;
113        mCallCard = callCard;
114        mDialer = dialer;
115        mDialerDrawer = dialerDrawer;
116        mApplication = PhoneApp.getInstance();
117        mOtaWidgetData = new OtaWidgetData();
118
119        // inflate OTA Call card and footers
120        ViewStub otaCallCardStub = (ViewStub) mInCallScreen.findViewById(R.id.otaCallCardStub);
121        otaCallCardStub.inflate();
122        readXmlSettings();
123        initOtaInCallScreen();
124    }
125
126    /**
127     * Returns true if the phone needs activation.
128     *
129     * @param minString the phone's MIN configuration string
130     * @return true if phone needs activation
131     * @throws OtaConfigurationException if the string is invalid
132     */
133    public static boolean needsActivation(String minString) throws IllegalArgumentException {
134        if (minString == null || (minString.length() < 6)) {
135            throw new IllegalArgumentException();
136        }
137        return (minString.equals(UNACTIVATED_MIN_VALUE)
138                || minString.substring(0,6).equals(UNACTIVATED_MIN2_VALUE))
139                || SystemProperties.getBoolean("test_cdma_setup", false);
140    }
141
142    /**
143     * Starts the OTA provisioning call.  If the MIN isn't available yet, it returns false and adds
144     * an event to return the request to the calling app when it becomes available.
145     *
146     * @param context
147     * @param handler
148     * @param request
149     * @return true if we were able to launch Ota activity or it's not required; false otherwise
150     */
151    public static boolean maybeDoOtaCall(Context context, Handler handler, int request) {
152        PhoneApp app = PhoneApp.getInstance();
153        Phone phone = app.phone;
154
155        if (!isCdmaPhone()) {
156            if (DBG) Log.v("OtaUtils", "Can't run provisioning on a non-CDMA phone");
157            return true; // sanity check - a non-cdma phone doesn't need to run this
158        }
159
160        if (!phone.isMinInfoReady()) {
161            if (DBG) log("MIN is not ready. Registering to receive notification.");
162            phone.registerForSubscriptionInfoReady(handler, request, null);
163            return false;
164        }
165
166        phone.unregisterForSubscriptionInfoReady(handler);
167        String min = phone.getCdmaMin();
168
169        if (DBG) log("min_string: " + min);
170
171        boolean phoneNeedsActivation = false;
172        try {
173            phoneNeedsActivation = needsActivation(min);
174        } catch (IllegalArgumentException e) {
175            if (DBG) log("invalid MIN string, exit");
176            return true; // If the MIN string is wrong, there's nothing else we can do.
177        }
178
179        if (DBG) log("phoneNeedsActivation is set to " + phoneNeedsActivation);
180
181        int otaShowActivationScreen = context.getResources().getInteger(
182                R.integer.OtaShowActivationScreen);
183
184        if (DBG) log("otaShowActivationScreen: " + otaShowActivationScreen);
185
186        if (phoneNeedsActivation && (otaShowActivationScreen == OTA_SHOW_ACTIVATION_SCREEN_ON)) {
187            app.cdmaOtaProvisionData.isOtaCallIntentProcessed = false;
188            Intent newIntent = new Intent(InCallScreen.ACTION_SHOW_ACTIVATION);
189            newIntent.setClass(context, InCallScreen.class);
190            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
191            context.startActivity(newIntent);
192            if (DBG) log("activation intent sent.");
193        } else {
194            if (DBG) log("activation intent NOT sent.");
195        }
196        return true;
197    }
198
199    private void setSpeaker(boolean state) {
200        if (DBG) log("setSpeaker : " + state );
201        if (state == PhoneUtils.isSpeakerOn(mContext)) {
202            if (DBG) log("no change. returning");
203            return;
204        }
205
206        if (state && mInCallScreen.isBluetoothAvailable()
207                && mInCallScreen.isBluetoothAudioConnected()) {
208            mInCallScreen.disconnectBluetoothAudio();
209        }
210        PhoneUtils.turnOnSpeaker(mContext, state, true);
211    }
212
213    /**
214     * Handle OTA Provision events from Framework. Possible events are:
215     * OTA Commit Event - OTA provisioning was successful
216     * SPC retries exceeded - SPC failure retries has exceeded, and Phone needs to
217     *    power down.
218     */
219    public void onOtaProvisionStatusChanged(AsyncResult r) {
220        int OtaStatus[] = (int[]) r.result;
221        if (DBG) log("onOtaProvisionStatusChanged(): OtaStatus[0]" + OtaStatus[0]);
222
223        otaShowInProgressScreen();
224        switch(OtaStatus[0]) {
225            case Phone.CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED:
226                mApplication.cdmaOtaProvisionData.otaSpcUptime = SystemClock.elapsedRealtime();
227                otaShowSpcErrorNotice(OTA_SPC_TIMEOUT);
228                // Power.shutdown();
229                break;
230            case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
231                mApplication.cdmaOtaProvisionData.isOtaCallCommitted = true;
232                if (DBG) log("onOtaProvisionStatusChanged(): isOtaCallCommitted set to true");
233                break;
234        }
235    }
236
237    private void otaShowHome() {
238        if (DBG) log("OtaShowHome()...");
239        mApplication.cdmaOtaScreenState.otaScreenState =
240                CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
241        cleanOtaScreen();
242        Intent intent = new Intent(Intent.ACTION_MAIN);
243        intent.addCategory (Intent.CATEGORY_HOME);
244        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
245        mContext.startActivity(intent);
246        mInCallScreen.finish();
247        return;
248    }
249
250    /**
251     * Show Activation Screen when phone powers up and OTA provision is
252     * required. Also shown when activation fails and user needs
253     * to re-attempt it. Contains ACTIVE and CANCEL buttons
254     * which allow user to start OTA activation or cancel the activation process.
255     */
256    public void otaShowActivateScreen() {
257        if (DBG) log("OtaShowActivationScreen()...");
258        if (mApplication.cdmaOtaConfigData.otaShowActivationScreen
259                == OTA_SHOW_ACTIVATION_SCREEN_ON) {
260            if (DBG) log("OtaShowActivationScreen(): show activation screen");
261            if (!isDialerOpened()) {
262                otaScreenInitialize();
263                mOtaWidgetData.otaTextActivate.setVisibility(View.VISIBLE);
264                mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.VISIBLE);
265            } else {
266                if (mDialerDrawer != null) mDialerDrawer.setVisibility(View.VISIBLE);
267            }
268            mApplication.cdmaOtaScreenState.otaScreenState =
269                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION;
270        } else {
271            if (DBG) log("OtaShowActivationScreen(): show home screen");
272            otaShowHome();
273        }
274     }
275
276    /**
277     * Show "Listen for Instruction" screen during OTA call. Shown when OTA Call
278     * is initiated and user needs to listen for network instructions and press
279     * appropriate DTMF digits to proceed to the "Programming in Progress" phase.
280     */
281    private void otaShowListeningScreen() {
282        if (DBG) log("OtaShowListeningScreen()...");
283        if (mApplication.cdmaOtaConfigData.otaShowListeningScreen
284                == OTA_SHOW_LISTENING_SCREEN_ON) {
285            if (DBG) log("OtaShowListeningScreen(): show listening screen");
286            if (!isDialerOpened()) {
287                otaScreenInitialize();
288                mOtaWidgetData.otaTextListenProgress.setVisibility(View.VISIBLE);
289                mOtaWidgetData.otaTextListenProgress.setText(R.string.ota_listen);
290                mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.VISIBLE);
291            } else {
292                if (mDialerDrawer != null) mDialerDrawer.setVisibility(View.VISIBLE);
293            }
294            mApplication.cdmaOtaScreenState.otaScreenState =
295                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING;
296
297            // Update the state of the in-call menu items.
298            mInCallScreen.updateMenuItems();
299        } else {
300            if (DBG) log("OtaShowListeningScreen(): show progress screen");
301            otaShowInProgressScreen();
302        }
303    }
304
305    /**
306     * Show "Programming In Progress" screen during OTA call. Shown when OTA
307     * provisioning is in progress after user has selected an option.
308     */
309    private void otaShowInProgressScreen() {
310        if (DBG) log("OtaShowInProgressScreen()...");
311        if (!isDialerOpened()) {
312            otaScreenInitialize();
313            mOtaWidgetData.otaTextListenProgress.setVisibility(View.VISIBLE);
314            mOtaWidgetData.otaTextListenProgress.setText(R.string.ota_progress);
315            mOtaWidgetData.otaTextProgressBar.setVisibility(View.VISIBLE);
316            mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.VISIBLE);
317        } else {
318            if (mDialerDrawer != null) mDialerDrawer.setVisibility(View.VISIBLE);
319        }
320        mApplication.cdmaOtaScreenState.otaScreenState =
321            CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS;
322
323        // Update the state of the in-call menu items.
324        mInCallScreen.updateMenuItems();
325    }
326
327    /**
328     * Show programming failure dialog when OTA provisioning fails.
329     * If OTA provisioning attempts fail more than 3 times, then unsuccessful
330     * dialog is shown. Otherwise a two-second notice is shown with unsuccessful
331     * information. When notice expires, phone returns to activation screen.
332     */
333    private void otaShowProgramFailure( int length) {
334        if (DBG) log("OtaShowProgramFailure()...");
335        mApplication.cdmaOtaProvisionData.activationCount++;
336        if ((mApplication.cdmaOtaProvisionData.activationCount <
337                mApplication.cdmaOtaConfigData.otaShowActivateFailTimes)
338                && (mApplication.cdmaOtaConfigData.otaShowActivationScreen ==
339                OTA_SHOW_ACTIVATION_SCREEN_ON)) {
340            if (DBG) log("OtaShowProgramFailure(): activationCount"
341                    + mApplication.cdmaOtaProvisionData.activationCount);
342            if (DBG) log("OtaShowProgramFailure(): show failure notice");
343            otaShowProgramFailureNotice(length);
344        } else {
345            if (DBG) log("OtaShowProgramFailure(): show failure dialog");
346            otaShowProgramFailureDialog();
347        }
348    }
349
350    /**
351     * Show either programming success dialog when OTA provisioning succeeds, or
352     * programming failure dialog when it fails. See {@link otaShowProgramFailure}
353     * for more details.
354     */
355    public void otaShowSuccessFailure() {
356        if (DBG) log("OtaShowSuccessFailure()...");
357        otaScreenInitialize();
358        if (DBG) log("OtaShowSuccessFailure(): isOtaCallCommitted"
359                + mApplication.cdmaOtaProvisionData.isOtaCallCommitted);
360        if (mApplication.cdmaOtaProvisionData.isOtaCallCommitted) {
361            if (DBG) log("OtaShowSuccessFailure(), show success dialog");
362            otaShowProgramSuccessDialog();
363        } else {
364            if (DBG) log("OtaShowSuccessFailure(), show failure dialog");
365            otaShowProgramFailure(OTA_FAILURE_DIALOG_TIMEOUT);
366        }
367        return;
368    }
369
370    /**
371     * Show programming failure dialog when OTA provisioning fails more than 3
372     * times.
373     */
374    private void otaShowProgramFailureDialog() {
375        if (DBG) log("OtaShowProgramFailureDialog()...");
376        mApplication.cdmaOtaScreenState.otaScreenState =
377                CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG;
378        mOtaWidgetData.otaTextSuccessFail.setVisibility(View.VISIBLE);
379        mOtaWidgetData.otaTextSuccessFail.setText(R.string.ota_unsuccessful);
380        mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.VISIBLE);
381        //close the dialer if open
382        if (isDialerOpened()) {
383            mDialer.closeDialer(false);
384        }
385    }
386
387    /**
388     * Show programming success dialog when OTA provisioning succeeds.
389     */
390    private void otaShowProgramSuccessDialog() {
391        if (DBG) log("OtaShowProgramSuccessDialog()...");
392        mApplication.cdmaOtaScreenState.otaScreenState =
393                CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG;
394        mOtaWidgetData.otaTextSuccessFail.setVisibility(View.VISIBLE);
395        mOtaWidgetData.otaTextSuccessFail.setText(R.string.ota_successful);
396        mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.VISIBLE);
397        //close the dialer if open
398        if (isDialerOpened()) {
399            mDialer.closeDialer(false);
400        }
401    }
402
403    /**
404     * Show SPC failure notice when SPC attempts exceed 15 times.
405     * During OTA provisioning, if SPC code is incorrect OTA provisioning will
406     * fail. When SPC attempts are over 15, it shows SPC failure notice for one minute and
407     * then phone will power down.
408     */
409    private void otaShowSpcErrorNotice(int length) {
410        if (DBG) log("OtaShowSpcErrorNotice()...");
411        if (mOtaWidgetData.spcErrorDialog == null) {
412            mApplication.cdmaOtaProvisionData.inOtaSpcState = true;
413            DialogInterface.OnKeyListener keyListener;
414            keyListener = new DialogInterface.OnKeyListener() {
415                public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
416                    log("Ignoring key events...");
417                    return true;
418                }};
419            mOtaWidgetData.spcErrorDialog = new AlertDialog.Builder(mInCallScreen)
420                    .setMessage(R.string.ota_spc_failure)
421                    .setOnKeyListener(keyListener)
422                    .create();
423            mOtaWidgetData.spcErrorDialog.getWindow().addFlags(
424                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
425                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
426            mOtaWidgetData.spcErrorDialog.show();
427            //close the dialer if open
428            if (isDialerOpened()) {
429                mDialer.closeDialer(false);
430            }
431            long noticeTime = length*1000;
432            if (DBG) log("OtaShowSpcErrorNotice(), remaining SPC noticeTime"+noticeTime);
433            mInCallScreen.postNewMessageDelay(InCallScreen.CLOSE_SPC_ERROR_NOTICE,noticeTime);
434        }
435    }
436
437    /**
438     * When SPC notice times out, force phone to power down.
439     */
440    public void onOtaCloseSpcNotice() {
441        if (DBG) log("onOtaCloseSpcNotice(), send shutdown intent");
442        Intent shutdown = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
443        shutdown.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
444        shutdown.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
445        mContext.startActivity(shutdown);
446    }
447
448    /**
449     * Show two-second notice when OTA provisioning fails and number of failed attempts
450     * is less then 3.
451     */
452    private void otaShowProgramFailureNotice(int length) {
453        if (DBG) log("OtaShowProgramFailureNotice()...");
454        if (mOtaWidgetData.otaFailureDialog == null) {
455            mOtaWidgetData.otaFailureDialog = new AlertDialog.Builder(mInCallScreen)
456                    .setMessage(R.string.ota_failure)
457                    .create();
458            mOtaWidgetData.otaFailureDialog.getWindow().addFlags(
459                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
460                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
461            mOtaWidgetData.otaFailureDialog.show();
462
463            long noticeTime = length*1000;
464            mInCallScreen.postNewMessageDelay(InCallScreen.CLOSE_OTA_FAILURE_NOTICE, noticeTime);
465        }
466    }
467
468    /**
469     * Handle OTA unsuccessful notice expiry. Dismisses the
470     * two-second notice and shows the activation screen.
471     */
472    public void onOtaCloseFailureNotice() {
473        if (DBG) log("onOtaCloseFailureNotice()...");
474        if (mOtaWidgetData.otaFailureDialog != null) {
475            mOtaWidgetData.otaFailureDialog.dismiss();
476            mOtaWidgetData.otaFailureDialog = null;
477        }
478        otaShowActivateScreen();
479    }
480
481    /**
482     * Initialize all OTA UI elements to be gone. Also set inCallPanel,
483     * callCard and dialerDrawer to be gone. This is called before any OTA screen
484     * gets drawn.
485     */
486    private void otaScreenInitialize() {
487        if (DBG) log("OtaScreenInitialize()...");
488
489        if (mInCallPanel != null) mInCallPanel.setVisibility(View.GONE);
490        if (mCallCard != null) mCallCard.hideCallCardElements();
491        if (mDialerDrawer != null) mDialerDrawer.setVisibility(View.GONE);
492
493        mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
494        mOtaWidgetData.otaTextListenProgress.setVisibility(View.GONE);
495        mOtaWidgetData.otaTextProgressBar.setVisibility(View.GONE);
496        mOtaWidgetData.otaTextSuccessFail.setVisibility(View.GONE);
497        mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
498        mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
499        mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
500        mOtaWidgetData.otaCallCardBase.setVisibility(View.VISIBLE);
501    }
502
503    public void hideOtaScreen() {
504        if (DBG) log("hideOtaScreen()...");
505
506        mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
507        mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
508        mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
509        mOtaWidgetData.otaCallCardBase.setVisibility(View.GONE);
510    }
511
512    public boolean isDialerOpened() {
513        return (mDialer != null && mDialer.isOpened());
514    }
515
516    /**
517     * Show the appropriate OTA screen based on the current state of OTA call.
518     * Shown whenever calling screen is resumed.
519     */
520    public void otaShowProperScreen() {
521        if (DBG) log("otaShowProperScreen()...");
522        if (mInCallScreen.isForegroundActivity()) {
523            if (DBG) log("otaShowProperScreen(), OTA is foreground activity, currentstate ="
524                    + mApplication.cdmaOtaScreenState.otaScreenState);
525            if (mInCallPanel != null) {
526                mInCallPanel.setVisibility(View.GONE);
527            }
528            if (mApplication.cdmaOtaScreenState.otaScreenState
529                    == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION) {
530                otaShowActivateScreen();
531            } else if (mApplication.cdmaOtaScreenState.otaScreenState
532                    == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING) {
533                otaShowListeningScreen();
534            } else if (mApplication.cdmaOtaScreenState.otaScreenState
535                    == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS) {
536                otaShowInProgressScreen();
537            }
538
539            if (mApplication.cdmaOtaProvisionData.inOtaSpcState) {
540                otaShowSpcErrorNotice(getOtaSpcDisplayTime());
541            }
542        }
543    }
544
545    /**
546     * Read configuration values for each OTA screen from config.xml.
547     * These configuration values control visibility of each screen.
548     */
549    private void readXmlSettings() {
550        if (DBG) log("readXmlSettings()...");
551        if (mApplication.cdmaOtaConfigData.configComplete) {
552            return;
553        }
554
555        mApplication.cdmaOtaConfigData.configComplete = true;
556        int tmpOtaShowActivationScreen =
557                mContext.getResources().getInteger(R.integer.OtaShowActivationScreen);
558        mApplication.cdmaOtaConfigData.otaShowActivationScreen = tmpOtaShowActivationScreen;
559        if (DBG) log("readXmlSettings(), otaShowActivationScreen"
560                + mApplication.cdmaOtaConfigData.otaShowActivationScreen);
561
562        int tmpOtaShowListeningScreen =
563                mContext.getResources().getInteger(R.integer.OtaShowListeningScreen);
564        mApplication.cdmaOtaConfigData.otaShowListeningScreen = tmpOtaShowListeningScreen;
565        if (DBG) log("readXmlSettings(), otaShowListeningScreen"
566                + mApplication.cdmaOtaConfigData.otaShowListeningScreen);
567
568        int tmpOtaShowActivateFailTimes =
569                mContext.getResources().getInteger(R.integer.OtaShowActivateFailTimes);
570        mApplication.cdmaOtaConfigData.otaShowActivateFailTimes = tmpOtaShowActivateFailTimes;
571        if (DBG) log("readXmlSettings(), otaShowActivateFailTimes"
572                + mApplication.cdmaOtaConfigData.otaShowActivateFailTimes);
573
574        int tmpOtaPlaySuccessFailureTone =
575                mContext.getResources().getInteger(R.integer.OtaPlaySuccessFailureTone);
576        mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone = tmpOtaPlaySuccessFailureTone;
577        if (DBG) log("readXmlSettings(), otaPlaySuccessFailureTone"
578                + mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone);
579    }
580
581    /**
582     * Handle the click events for OTA buttons.
583     */
584    public void onClickHandler(int id) {
585        switch (id) {
586            case R.id.otaEndButton:
587                onClickOtaEndButton();
588                break;
589
590            case R.id.otaSpeakerButton:
591                onClickOtaSpeakerButton();
592                break;
593
594            case R.id.otaActivateButton:
595                onClickOtaActivateButton();
596                break;
597
598            case R.id.otaCancelButton:
599                onClickOtaActivateCancelButton();
600                break;
601
602            case R.id.otaOkButton:
603                onClickOtaActivateDialogOkButton();
604                break;
605
606            case R.id.otaDialButton:
607                onClickOtaKeypadButton();
608                break;
609
610            default:
611                if (DBG) log ("onClickHandler: received a click event for unrecognized id");
612                break;
613        }
614    }
615
616    private void onClickOtaEndButton() {
617        if (DBG) log("Activation Cancel Clicked!");
618        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
619            PhoneUtils.hangup(mApplication.phone);
620        }
621    }
622
623    private void onClickOtaSpeakerButton() {
624        if (DBG) log("OTA Speaker button Clicked!");
625        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
626            boolean isChecked = !PhoneUtils.isSpeakerOn(mContext);
627            setSpeaker(isChecked);
628        }
629    }
630
631    private void onClickOtaActivateButton() {
632        if (DBG) log("Call Activation Clicked!");
633        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
634            Intent newIntent = new Intent(Intent.ACTION_CALL);
635            newIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, InCallScreen.OTA_NUMBER);
636            mInCallScreen.internalResolveIntent(newIntent);
637            otaShowListeningScreen();
638        }
639    }
640
641    private void onClickOtaActivateCancelButton() {
642        if (DBG) log("Activation Cancel Clicked!");
643        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
644            otaShowHome();
645        }
646    }
647
648    private void onClickOtaActivateDialogOkButton() {
649        if (DBG) log("Dialog OK Clicked!");
650        if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) {
651            mApplication.cdmaOtaScreenState.otaScreenState =
652                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
653            otaShowHome();
654            mInCallScreen.finish();
655        }
656    }
657
658    private void onClickOtaKeypadButton() {
659        if (DBG) log("DTMF Keypad Button Clicked!");
660        if ((!InCallScreen.ConfigurationHelper.isLandscape())
661                && (!mApplication.cdmaOtaProvisionData.inOtaSpcState)) {
662            if (mDialer != null) {
663                mDialer.openDialer(true);
664            }
665            if (mDialerDrawer != null) {
666                mDialerDrawer.setVisibility(View.VISIBLE);
667            }
668        }
669    }
670
671    public void dismissAllOtaDialogs() {
672        if (mOtaWidgetData.spcErrorDialog != null) {
673            if (DBG) log("- DISMISSING mSpcErrorDialog.");
674            mOtaWidgetData.spcErrorDialog.dismiss();
675            mOtaWidgetData.spcErrorDialog = null;
676        }
677        if (mOtaWidgetData.otaFailureDialog != null) {
678            if (DBG) log("- DISMISSING mOtaFailureDialog.");
679            mOtaWidgetData.otaFailureDialog.dismiss();
680            mOtaWidgetData.otaFailureDialog = null;
681        }
682    }
683
684    private int getOtaSpcDisplayTime() {
685        if (DBG) log("getOtaSpcDisplayTime()...");
686        int tmpSpcTime = 1;
687        if (mApplication.cdmaOtaProvisionData.inOtaSpcState) {
688            long tmpOtaSpcRunningTime = 0;
689            long tmpOtaSpcLeftTime = 0;
690            tmpOtaSpcRunningTime = SystemClock.elapsedRealtime();
691            tmpOtaSpcLeftTime =
692                tmpOtaSpcRunningTime - mApplication.cdmaOtaProvisionData.otaSpcUptime;
693            if (tmpOtaSpcLeftTime >= OTA_SPC_TIMEOUT*1000) {
694                tmpSpcTime = 1;
695            } else {
696                tmpSpcTime = OTA_SPC_TIMEOUT - (int)tmpOtaSpcLeftTime/1000;
697            }
698        }
699        if (DBG) log("getOtaSpcDisplayTime(), time for SPC error notice: " + tmpSpcTime);
700        return tmpSpcTime;
701    }
702
703    /**
704     * Initialize the OTA widgets for all OTA screens.
705     */
706    private void initOtaInCallScreen() {
707        if (DBG) log("initOtaInCallScreen()...");
708        mOtaWidgetData.otaTextActivate = (TextView) mInCallScreen.findViewById(R.id.otaActivate);
709        mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
710        mOtaWidgetData.otaTextListenProgress =
711                (TextView) mInCallScreen.findViewById(R.id.otaListenProgress);
712        mOtaWidgetData.otaTextProgressBar =
713                (ProgressBar) mInCallScreen.findViewById(R.id.progress_large);
714        mOtaWidgetData.otaTextProgressBar.setIndeterminate(true);
715        mOtaWidgetData.otaTextSuccessFail =
716                (TextView) mInCallScreen.findViewById(R.id.otaSuccessFailStatus);
717
718        mOtaWidgetData.otaCallCardBase = (View) mInCallScreen.findViewById(R.id.otaBase);
719        mOtaWidgetData.callCardOtaButtonsListenProgress =
720                (View) mInCallScreen.findViewById(R.id.callCardOtaListenProgress);
721        mOtaWidgetData.callCardOtaButtonsActivate =
722                (View) mInCallScreen.findViewById(R.id.callCardOtaActivate);
723        mOtaWidgetData.callCardOtaButtonsFailSuccess =
724                (View) mInCallScreen.findViewById(R.id.callCardOtaFailOrSuccessful);
725
726        mOtaWidgetData.otaEndButton = (Button) mInCallScreen.findViewById(R.id.otaEndButton);
727        mOtaWidgetData.otaEndButton.setOnClickListener(mInCallScreen);
728        mOtaWidgetData.otaSpeakerButton =
729                (ToggleButton) mInCallScreen.findViewById(R.id.otaSpeakerButton);
730        mOtaWidgetData.otaSpeakerButton.setOnClickListener(mInCallScreen);
731        mOtaWidgetData.otaActivateButton =
732                (Button) mInCallScreen.findViewById(R.id.otaActivateButton);
733        mOtaWidgetData.otaActivateButton.setOnClickListener(mInCallScreen);
734        mOtaWidgetData.otaCancelButton =
735                (Button) mInCallScreen.findViewById(R.id.otaCancelButton);
736        mOtaWidgetData.otaCancelButton.setOnClickListener(mInCallScreen);
737        mOtaWidgetData.otaDialogOKButton =
738                (Button) mInCallScreen.findViewById(R.id.otaOkButton);
739        mOtaWidgetData.otaDialogOKButton.setOnClickListener(mInCallScreen);
740
741        if (!InCallScreen.ConfigurationHelper.isLandscape()) {
742            mOtaWidgetData.otaKeypadButton =
743                    (Button) mInCallScreen.findViewById(R.id.otaDialButton);
744            mOtaWidgetData.otaKeypadButton.setOnClickListener(mInCallScreen);
745        }
746    }
747
748    /**
749     * Clear out all OTA UI widget elements. Needs to get called
750     * when OTA call ends or InCallScreen is destroyed.
751     */
752    public void cleanOtaScreen() {
753        if (DBG) log("OTA ends, cleanOtaScreen!");
754            mApplication.cdmaOtaScreenState.otaScreenState =
755                    CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED;
756            mApplication.cdmaOtaProvisionData.isOtaCallCommitted = false;
757            mApplication.cdmaOtaProvisionData.isOtaCallIntentProcessed = false;
758            mApplication.cdmaOtaProvisionData.inOtaSpcState = false;
759            mApplication.cdmaOtaProvisionData.activationCount = 0;
760            mApplication.cdmaOtaProvisionData.otaSpcUptime = 0;
761
762            if (mInCallPanel != null) mInCallPanel.setVisibility(View.VISIBLE);
763            if (mCallCard != null) mCallCard.hideCallCardElements();
764            if (mDialerDrawer != null) mDialerDrawer.setVisibility(View.VISIBLE);
765
766            mOtaWidgetData.otaTextActivate.setVisibility(View.GONE);
767            mOtaWidgetData.otaTextListenProgress.setVisibility(View.GONE);
768            mOtaWidgetData.otaTextProgressBar.setVisibility(View.GONE);
769            mOtaWidgetData.otaTextSuccessFail.setVisibility(View.GONE);
770            mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE);
771            mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE);
772            mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE);
773            mOtaWidgetData.otaCallCardBase.setVisibility(View.GONE);
774    }
775
776    /**
777     * Defines OTA information that needs to be maintained during
778     * an OTA call when display orientation changes.
779     */
780    public static class CdmaOtaProvisionData {
781        public boolean isOtaCallCommitted;
782        public boolean isOtaCallIntentProcessed;
783        public boolean inOtaSpcState;
784        public int activationCount;
785        public long otaSpcUptime;
786    }
787
788    /**
789     * Defines OTA screen configuration items read from config.xml
790     * and used to control OTA display.
791     */
792    public static class CdmaOtaConfigData {
793        public int otaShowActivationScreen;
794        public int otaShowListeningScreen;
795        public int otaShowActivateFailTimes;
796        public int otaPlaySuccessFailureTone;
797        public boolean configComplete;
798        public CdmaOtaConfigData() {
799            if (DBG) log("CdmaOtaConfigData constructor!");
800            otaShowActivationScreen = OTA_SHOW_ACTIVATION_SCREEN_OFF;
801            otaShowListeningScreen = OTA_SHOW_LISTENING_SCREEN_OFF;
802            otaShowActivateFailTimes = OTA_SHOW_ACTIVATE_FAIL_COUNT_OFF;
803            otaPlaySuccessFailureTone = OTA_PLAY_SUCCESS_FAILURE_TONE_OFF;
804        }
805    }
806
807    /**
808     * The OTA screen state machine.
809     */
810    public static class CdmaOtaScreenState {
811        public enum OtaScreenState {
812            OTA_STATUS_UNDEFINED,
813            OTA_STATUS_ACTIVATION,
814            OTA_STATUS_LISTENING,
815            OTA_STATUS_PROGRESS,
816            OTA_STATUS_SUCCESS_FAILURE_DLG
817        }
818
819        public OtaScreenState otaScreenState;
820
821        public CdmaOtaScreenState() {
822            otaScreenState = OtaScreenState.OTA_STATUS_UNDEFINED;
823        }
824    }
825
826    private static void log(String msg) {
827        Log.d(LOG_TAG, msg);
828    }
829
830    public static boolean isCdmaPhone() {
831        return PhoneApp.getInstance().phone.getPhoneName().equals("CDMA");
832    }
833}
834