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