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