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