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