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