| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.phone; |
| |
| import com.android.internal.telephony.Phone; |
| import com.android.internal.telephony.PhoneConstants; |
| import com.android.internal.telephony.TelephonyCapabilities; |
| import com.android.internal.telephony.TelephonyProperties; |
| import com.android.phone.OtaUtils.CdmaOtaInCallScreenUiState.State; |
| |
| import android.app.Activity; |
| import android.app.ActivityManager; |
| import android.app.AlertDialog; |
| import android.app.PendingIntent; |
| import android.app.PendingIntent.CanceledException; |
| import android.content.ActivityNotFoundException; |
| import android.content.Context; |
| import android.content.DialogInterface; |
| import android.content.Intent; |
| import android.net.Uri; |
| import android.os.AsyncResult; |
| import android.os.Handler; |
| import android.os.SystemClock; |
| import android.os.SystemProperties; |
| import android.os.UserHandle; |
| import android.telephony.TelephonyManager; |
| import android.util.Log; |
| import android.view.KeyEvent; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.ViewStub; |
| import android.view.WindowManager; |
| import android.widget.Button; |
| import android.widget.ProgressBar; |
| import android.widget.ScrollView; |
| import android.widget.TextView; |
| import android.widget.ToggleButton; |
| |
| /** |
| * Handles all OTASP Call related logic and UI functionality. |
| * The InCallScreen interacts with this class to perform an OTASP Call. |
| * |
| * OTASP is a CDMA-specific feature: |
| * OTA or OTASP == Over The Air service provisioning |
| * SPC == Service Programming Code |
| * TODO: Include pointer to more detailed documentation. |
| * |
| * TODO: This is Over The Air Service Provisioning (OTASP) |
| * A better name would be OtaspUtils.java. |
| */ |
| public class OtaUtils { |
| private static final String LOG_TAG = "OtaUtils"; |
| private static final boolean DBG = false; |
| |
| public static final int OTA_SHOW_ACTIVATION_SCREEN_OFF = 0; |
| public static final int OTA_SHOW_ACTIVATION_SCREEN_ON = 1; |
| public static final int OTA_SHOW_LISTENING_SCREEN_OFF =0; |
| public static final int OTA_SHOW_LISTENING_SCREEN_ON =1; |
| public static final int OTA_SHOW_ACTIVATE_FAIL_COUNT_OFF = 0; |
| public static final int OTA_SHOW_ACTIVATE_FAIL_COUNT_THREE = 3; |
| public static final int OTA_PLAY_SUCCESS_FAILURE_TONE_OFF = 0; |
| public static final int OTA_PLAY_SUCCESS_FAILURE_TONE_ON = 1; |
| |
| // SPC Timeout is 60 seconds |
| public final int OTA_SPC_TIMEOUT = 60; |
| public final int OTA_FAILURE_DIALOG_TIMEOUT = 2; |
| |
| // Constants for OTASP-related Intents and intent extras. |
| // Watch out: these must agree with the corresponding constants in |
| // apps/SetupWizard! |
| |
| // Intent action to launch an OTASP call. |
| public static final String ACTION_PERFORM_CDMA_PROVISIONING = |
| "com.android.phone.PERFORM_CDMA_PROVISIONING"; |
| |
| // Intent action to launch activation on a non-voice capable device |
| public static final String ACTION_PERFORM_VOICELESS_CDMA_PROVISIONING = |
| "com.android.phone.PERFORM_VOICELESS_CDMA_PROVISIONING"; |
| |
| // Intent action to display the InCallScreen in the OTASP "activation" state. |
| public static final String ACTION_DISPLAY_ACTIVATION_SCREEN = |
| "com.android.phone.DISPLAY_ACTIVATION_SCREEN"; |
| |
| // boolean voiceless provisioning extra that enables a "don't show this again" checkbox |
| // the user can check to never see the activity upon bootup again |
| public static final String EXTRA_VOICELESS_PROVISIONING_OFFER_DONTSHOW = |
| "com.android.phone.VOICELESS_PROVISIONING_OFFER_DONTSHOW"; |
| |
| // Activity result codes for the ACTION_PERFORM_CDMA_PROVISIONING intent |
| // (see the InCallScreenShowActivation activity.) |
| // |
| // Note: currently, our caller won't ever actually receive the |
| // RESULT_INTERACTIVE_OTASP_STARTED result code; see comments in |
| // InCallScreenShowActivation.onCreate() for details. |
| |
| public static final int RESULT_INTERACTIVE_OTASP_STARTED = Activity.RESULT_FIRST_USER; |
| public static final int RESULT_NONINTERACTIVE_OTASP_STARTED = Activity.RESULT_FIRST_USER + 1; |
| public static final int RESULT_NONINTERACTIVE_OTASP_FAILED = Activity.RESULT_FIRST_USER + 2; |
| |
| // Testing: Extra for the ACTION_PERFORM_CDMA_PROVISIONING intent that |
| // allows the caller to manually enable/disable "interactive mode" for |
| // the OTASP call. Only available in userdebug or eng builds. |
| public static final String EXTRA_OVERRIDE_INTERACTIVE_MODE = |
| "ota_override_interactive_mode"; |
| |
| // Extra for the ACTION_PERFORM_CDMA_PROVISIONING intent, holding a |
| // PendingIntent which the phone app can use to send a result code |
| // back to the caller. |
| public static final String EXTRA_OTASP_RESULT_CODE_PENDING_INTENT = |
| "otasp_result_code_pending_intent"; |
| |
| // Extra attached to the above PendingIntent that indicates |
| // success or failure. |
| public static final String EXTRA_OTASP_RESULT_CODE = |
| "otasp_result_code"; |
| public static final int OTASP_UNKNOWN = 0; |
| public static final int OTASP_USER_SKIPPED = 1; // Only meaningful with interactive OTASP |
| public static final int OTASP_SUCCESS = 2; |
| public static final int OTASP_FAILURE = 3; |
| // failed due to CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED |
| public static final int OTASP_FAILURE_SPC_RETRIES = 4; |
| // TODO: Distinguish between interactive and non-interactive success |
| // and failure. Then, have the PendingIntent be sent after |
| // interactive OTASP as well (so the caller can find out definitively |
| // when interactive OTASP completes.) |
| |
| private static final String OTASP_NUMBER = "*228"; |
| private static final String OTASP_NUMBER_NON_INTERACTIVE = "*22899"; |
| |
| private InCallScreen mInCallScreen; |
| private Context mContext; |
| private PhoneGlobals mApplication; |
| private OtaWidgetData mOtaWidgetData; |
| private ViewGroup mInCallTouchUi; // UI controls for regular calls |
| private CallCard mCallCard; |
| |
| // The DTMFTwelveKeyDialer instance. We create this in |
| // initOtaInCallScreen(), and attach it to the DTMFTwelveKeyDialerView |
| // ("otaDtmfDialerView") that comes from otacall_card.xml. |
| private DTMFTwelveKeyDialer mOtaCallCardDtmfDialer; |
| |
| private static boolean sIsWizardMode = true; |
| |
| // How many times do we retry maybeDoOtaCall() if the LTE state is not known yet, |
| // and how long do we wait between retries |
| private static final int OTA_CALL_LTE_RETRIES_MAX = 5; |
| private static final int OTA_CALL_LTE_RETRY_PERIOD = 3000; |
| private static int sOtaCallLteRetries = 0; |
| |
| // In "interactive mode", the OtaUtils object is tied to an |
| // InCallScreen instance, where we display a bunch of UI specific to |
| // the OTASP call. But on devices that are not "voice capable", the |
| // OTASP call runs in a non-interactive mode, and we don't have |
| // an InCallScreen or CallCard or any OTASP UI elements at all. |
| private boolean mInteractive = true; |
| |
| |
| /** |
| * OtaWidgetData class represent all OTA UI elements |
| * |
| * TODO(OTASP): It's really ugly for the OtaUtils object to reach into the |
| * InCallScreen like this and directly manipulate its widgets. |
| * |
| * Instead, the model/view separation should be more clear: OtaUtils |
| * should only know about a higher-level abstraction of the |
| * OTASP-specific UI state (just like how the CallController uses the |
| * InCallUiState object), and the InCallScreen itself should translate |
| * that higher-level abstraction into actual onscreen views and widgets. |
| */ |
| private class OtaWidgetData { |
| public Button otaEndButton; |
| public Button otaActivateButton; |
| public Button otaSkipButton; |
| public Button otaNextButton; |
| public ToggleButton otaSpeakerButton; |
| public ViewGroup otaUpperWidgets; |
| public View callCardOtaButtonsFailSuccess; |
| public ProgressBar otaTextProgressBar; |
| public TextView otaTextSuccessFail; |
| public View callCardOtaButtonsActivate; |
| public View callCardOtaButtonsListenProgress; |
| public TextView otaTextActivate; |
| public TextView otaTextListenProgress; |
| public AlertDialog spcErrorDialog; |
| public AlertDialog otaFailureDialog; |
| public AlertDialog otaSkipConfirmationDialog; |
| public TextView otaTitle; |
| public DTMFTwelveKeyDialerView otaDtmfDialerView; |
| public Button otaTryAgainButton; |
| } |
| |
| /** |
| * OtaUtils constructor. |
| * |
| * @param context the Context of the calling Activity or Application |
| * @param interactive if true, use the InCallScreen to display the progress |
| * and result of the OTASP call. In practice this is |
| * true IFF the current device is a voice-capable phone. |
| * |
| * Note if interactive is true, you must also call updateUiWidgets() as soon |
| * as the InCallScreen instance is ready. |
| */ |
| public OtaUtils(Context context, boolean interactive) { |
| if (DBG) log("OtaUtils constructor..."); |
| mApplication = PhoneGlobals.getInstance(); |
| mContext = context; |
| mInteractive = interactive; |
| } |
| |
| /** |
| * Updates the OtaUtils object's references to some UI elements belonging to |
| * the InCallScreen. This is used only in interactive mode. |
| * |
| * Use clearUiWidgets() to clear out these references. (The InCallScreen |
| * is responsible for doing this from its onDestroy() method.) |
| * |
| * This method has no effect if the UI widgets have already been set up. |
| * (In other words, it's safe to call this every time through |
| * InCallScreen.onResume().) |
| */ |
| public void updateUiWidgets(InCallScreen inCallScreen, |
| ViewGroup inCallTouchUi, CallCard callCard) { |
| if (DBG) log("updateUiWidgets()... mInCallScreen = " + mInCallScreen); |
| |
| if (!mInteractive) { |
| throw new IllegalStateException("updateUiWidgets() called in non-interactive mode"); |
| } |
| |
| if (mInCallScreen != null) { |
| if (DBG) log("updateUiWidgets(): widgets already set up, nothing to do..."); |
| return; |
| } |
| |
| mInCallScreen = inCallScreen; |
| mInCallTouchUi = inCallTouchUi; |
| mCallCard = callCard; |
| mOtaWidgetData = new OtaWidgetData(); |
| |
| // Inflate OTASP-specific UI elements: |
| ViewStub otaCallCardStub = (ViewStub) mInCallScreen.findViewById(R.id.otaCallCardStub); |
| if (otaCallCardStub != null) { |
| // If otaCallCardStub is null here, that means it's already been |
| // inflated (which could have happened in the current InCallScreen |
| // instance for a *prior* OTASP call.) |
| otaCallCardStub.inflate(); |
| } |
| |
| readXmlSettings(); |
| initOtaInCallScreen(); |
| } |
| |
| /** |
| * Clear out the OtaUtils object's references to any InCallScreen UI |
| * elements. This is the opposite of updateUiWidgets(). |
| */ |
| public void clearUiWidgets() { |
| mInCallScreen = null; |
| mInCallTouchUi = null; |
| mCallCard = null; |
| mOtaWidgetData = null; |
| } |
| |
| /** |
| * Starts the OTA provisioning call. If the MIN isn't available yet, it returns false and adds |
| * an event to return the request to the calling app when it becomes available. |
| * |
| * @param context |
| * @param handler |
| * @param request |
| * @return true if we were able to launch Ota activity or it's not required; false otherwise |
| */ |
| public static boolean maybeDoOtaCall(Context context, Handler handler, int request) { |
| PhoneGlobals app = PhoneGlobals.getInstance(); |
| Phone phone = app.phone; |
| |
| if (ActivityManager.isRunningInTestHarness()) { |
| Log.i(LOG_TAG, "Don't run provisioning when in test harness"); |
| return true; |
| } |
| |
| if (!TelephonyCapabilities.supportsOtasp(phone)) { |
| // Presumably not a CDMA phone. |
| if (DBG) log("maybeDoOtaCall: OTASP not supported on this device"); |
| return true; // Nothing to do here. |
| } |
| |
| if (!phone.isMinInfoReady()) { |
| if (DBG) log("MIN is not ready. Registering to receive notification."); |
| phone.registerForSubscriptionInfoReady(handler, request, null); |
| return false; |
| } |
| phone.unregisterForSubscriptionInfoReady(handler); |
| |
| if (getLteOnCdmaMode(context) == PhoneConstants.LTE_ON_CDMA_UNKNOWN) { |
| if (sOtaCallLteRetries < OTA_CALL_LTE_RETRIES_MAX) { |
| if (DBG) log("maybeDoOtaCall: LTE state still unknown: retrying"); |
| handler.sendEmptyMessageDelayed(request, OTA_CALL_LTE_RETRY_PERIOD); |
| sOtaCallLteRetries++; |
| return false; |
| } else { |
| Log.w(LOG_TAG, "maybeDoOtaCall: LTE state still unknown: giving up"); |
| return true; |
| } |
| } |
| |
| boolean phoneNeedsActivation = phone.needsOtaServiceProvisioning(); |
| if (DBG) log("phoneNeedsActivation is set to " + phoneNeedsActivation); |
| |
| int otaShowActivationScreen = context.getResources().getInteger( |
| R.integer.OtaShowActivationScreen); |
| if (DBG) log("otaShowActivationScreen: " + otaShowActivationScreen); |
| |
| // Run the OTASP call in "interactive" mode only if |
| // this is a non-LTE "voice capable" device. |
| if (PhoneGlobals.sVoiceCapable && getLteOnCdmaMode(context) == PhoneConstants.LTE_ON_CDMA_FALSE) { |
| if (phoneNeedsActivation |
| && (otaShowActivationScreen == OTA_SHOW_ACTIVATION_SCREEN_ON)) { |
| app.cdmaOtaProvisionData.isOtaCallIntentProcessed = false; |
| sIsWizardMode = false; |
| |
| if (DBG) Log.d(LOG_TAG, "==> Starting interactive CDMA provisioning..."); |
| OtaUtils.startInteractiveOtasp(context); |
| |
| if (DBG) log("maybeDoOtaCall: voice capable; activation started."); |
| } else { |
| if (DBG) log("maybeDoOtaCall: voice capable; activation NOT started."); |
| } |
| } else { |
| if (phoneNeedsActivation) { |
| app.cdmaOtaProvisionData.isOtaCallIntentProcessed = false; |
| Intent newIntent = new Intent(ACTION_PERFORM_VOICELESS_CDMA_PROVISIONING); |
| newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| newIntent.putExtra(EXTRA_VOICELESS_PROVISIONING_OFFER_DONTSHOW, true); |
| try { |
| context.startActivity(newIntent); |
| } catch (ActivityNotFoundException e) { |
| loge("No activity Handling PERFORM_VOICELESS_CDMA_PROVISIONING!"); |
| return false; |
| } |
| if (DBG) log("maybeDoOtaCall: non-interactive; activation intent sent."); |
| } else { |
| if (DBG) log("maybeDoOtaCall: non-interactive, no need for OTASP."); |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Starts a normal "interactive" OTASP call (i.e. CDMA activation |
| * for regular voice-capable phone devices.) |
| * |
| * This method is called from the InCallScreenShowActivation activity when |
| * handling the ACTION_PERFORM_CDMA_PROVISIONING intent. |
| */ |
| public static void startInteractiveOtasp(Context context) { |
| if (DBG) log("startInteractiveOtasp()..."); |
| PhoneGlobals app = PhoneGlobals.getInstance(); |
| |
| // There are two ways to start OTASP on voice-capable devices: |
| // |
| // (1) via the PERFORM_CDMA_PROVISIONING intent |
| // - this is triggered by the "Activate device" button in settings, |
| // or can be launched automatically upon boot if the device |
| // thinks it needs to be provisioned. |
| // - the intent is handled by InCallScreenShowActivation.onCreate(), |
| // which calls this method |
| // - we prepare for OTASP by initializing the OtaUtils object |
| // - we bring up the InCallScreen in the ready-to-activate state |
| // - when the user presses the "Activate" button we launch the |
| // call by calling CallController.placeCall() via the |
| // otaPerformActivation() method. |
| // |
| // (2) by manually making an outgoing call to a special OTASP number |
| // like "*228" or "*22899". |
| // - That sequence does NOT involve this method (OtaUtils.startInteractiveOtasp()). |
| // Instead, the outgoing call request goes straight to CallController.placeCall(). |
| // - CallController.placeCall() notices that it's an OTASP |
| // call, and initializes the OtaUtils object. |
| // - The InCallScreen is launched (as the last step of |
| // CallController.placeCall()). The InCallScreen notices that |
| // OTASP is active and shows the correct UI. |
| |
| // Here, we start sequence (1): |
| // Do NOT immediately start the call. Instead, bring up the InCallScreen |
| // in the special "activate" state (see OtaUtils.otaShowActivateScreen()). |
| // We won't actually make the call until the user presses the "Activate" |
| // button. |
| |
| Intent activationScreenIntent = new Intent().setClass(context, InCallScreen.class) |
| .setAction(ACTION_DISPLAY_ACTIVATION_SCREEN); |
| |
| // Watch out: in the scenario where OTASP gets triggered from the |
| // BOOT_COMPLETED broadcast (see OtaStartupReceiver.java), we might be |
| // running in the PhoneApp's context right now. |
| // So the FLAG_ACTIVITY_NEW_TASK flag is required here. |
| activationScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| |
| // We're about to start the OTASP sequence, so create and initialize the |
| // OtaUtils instance. (This needs to happen before bringing up the |
| // InCallScreen.) |
| OtaUtils.setupOtaspCall(activationScreenIntent); |
| |
| // And bring up the InCallScreen... |
| Log.i(LOG_TAG, "startInteractiveOtasp: launching InCallScreen in 'activate' state: " |
| + activationScreenIntent); |
| context.startActivity(activationScreenIntent); |
| } |
| |
| /** |
| * Starts the OTASP call *without* involving the InCallScreen or |
| * displaying any UI. |
| * |
| * This is used on data-only devices, which don't support any kind of |
| * in-call phone UI. |
| * |
| * @return PhoneUtils.CALL_STATUS_DIALED if we successfully |
| * dialed the OTASP number, or one of the other |
| * CALL_STATUS_* constants if there was a failure. |
| */ |
| public static int startNonInteractiveOtasp(Context context) { |
| if (DBG) log("startNonInteractiveOtasp()..."); |
| PhoneGlobals app = PhoneGlobals.getInstance(); |
| |
| if (app.otaUtils != null) { |
| // An OtaUtils instance already exists, presumably from a previous OTASP call. |
| Log.i(LOG_TAG, "startNonInteractiveOtasp: " |
| + "OtaUtils already exists; nuking the old one and starting again..."); |
| } |
| |
| // Create the OtaUtils instance. |
| app.otaUtils = new OtaUtils(context, false /* non-interactive mode */); |
| if (DBG) log("- created OtaUtils: " + app.otaUtils); |
| |
| // ... and kick off the OTASP call. |
| // TODO(InCallScreen redesign): This should probably go through |
| // the CallController, rather than directly calling |
| // PhoneUtils.placeCall(). |
| Phone phone = PhoneGlobals.getPhone(); |
| String number = OTASP_NUMBER_NON_INTERACTIVE; |
| Log.i(LOG_TAG, "startNonInteractiveOtasp: placing call to '" + number + "'..."); |
| int callStatus = PhoneUtils.placeCall(context, |
| phone, |
| number, |
| null, // contactRef |
| false, //isEmergencyCall |
| null); // gatewayUri |
| |
| if (callStatus == PhoneUtils.CALL_STATUS_DIALED) { |
| if (DBG) log(" ==> successful return from placeCall(): callStatus = " + callStatus); |
| } else { |
| Log.w(LOG_TAG, "Failure from placeCall() for OTA number '" |
| + number + "': code " + callStatus); |
| return callStatus; |
| } |
| |
| // TODO: Any other special work to do here? |
| // Such as: |
| // |
| // - manually kick off progress updates, either using TelephonyRegistry |
| // or else by sending PendingIntents directly to our caller? |
| // |
| // - manually silence the in-call audio? (Probably unnecessary |
| // if Stingray truly has no audio path from phone baseband |
| // to the device's speakers.) |
| // |
| |
| return callStatus; |
| } |
| |
| /** |
| * @return true if the specified Intent is a CALL action that's an attempt |
| * to initate an OTASP call. |
| * |
| * OTASP is a CDMA-specific concept, so this method will always return false |
| * on GSM phones. |
| * |
| * This code was originally part of the InCallScreen.checkIsOtaCall() method. |
| */ |
| public static boolean isOtaspCallIntent(Intent intent) { |
| if (DBG) log("isOtaspCallIntent(" + intent + ")..."); |
| PhoneGlobals app = PhoneGlobals.getInstance(); |
| Phone phone = app.mCM.getDefaultPhone(); |
| |
| if (intent == null) { |
| return false; |
| } |
| if (!TelephonyCapabilities.supportsOtasp(phone)) { |
| return false; |
| } |
| |
| String action = intent.getAction(); |
| if (action == null) { |
| return false; |
| } |
| if (!action.equals(Intent.ACTION_CALL)) { |
| if (DBG) log("isOtaspCallIntent: not a CALL action: '" + action + "' ==> not OTASP"); |
| return false; |
| } |
| |
| if ((app.cdmaOtaScreenState == null) || (app.cdmaOtaProvisionData == null)) { |
| // Uh oh -- something wrong with our internal OTASP state. |
| // (Since this is an OTASP-capable device, these objects |
| // *should* have already been created by PhoneApp.onCreate().) |
| throw new IllegalStateException("isOtaspCallIntent: " |
| + "app.cdmaOta* objects(s) not initialized"); |
| } |
| |
| // This is an OTASP call iff the number we're trying to dial is one of |
| // the magic OTASP numbers. |
| String number; |
| try { |
| number = PhoneUtils.getInitialNumber(intent); |
| } catch (PhoneUtils.VoiceMailNumberMissingException ex) { |
| // This was presumably a "voicemail:" intent, so it's |
| // obviously not an OTASP number. |
| if (DBG) log("isOtaspCallIntent: VoiceMailNumberMissingException => not OTASP"); |
| return false; |
| } |
| if (phone.isOtaSpNumber(number)) { |
| if (DBG) log("isOtaSpNumber: ACTION_CALL to '" + number + "' ==> OTASP call!"); |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Set up for an OTASP call. |
| * |
| * This method is called as part of the CallController placeCall() sequence |
| * before initiating an outgoing OTASP call. |
| * |
| * The purpose of this method is mainly to create and initialize the |
| * OtaUtils instance, along with some other misc pre-OTASP cleanup. |
| */ |
| public static void setupOtaspCall(Intent intent) { |
| if (DBG) log("setupOtaspCall(): preparing for OTASP call to " + intent); |
| PhoneGlobals app = PhoneGlobals.getInstance(); |
| |
| if (app.otaUtils != null) { |
| // An OtaUtils instance already exists, presumably from a prior OTASP call. |
| // Nuke the old one and start this call with a fresh instance. |
| Log.i(LOG_TAG, "setupOtaspCall: " |
| + "OtaUtils already exists; replacing with new instance..."); |
| } |
| |
| // Create the OtaUtils instance. |
| app.otaUtils = new OtaUtils(app.getApplicationContext(), true /* interactive */); |
| if (DBG) log("- created OtaUtils: " + app.otaUtils); |
| |
| // NOTE we still need to call OtaUtils.updateUiWidgets() once the |
| // InCallScreen instance is ready; see InCallScreen.checkOtaspStateOnResume() |
| |
| // Make sure the InCallScreen knows that it needs to switch into OTASP mode. |
| // |
| // NOTE in gingerbread and earlier, we used to do |
| // setInCallScreenMode(InCallScreenMode.OTA_NORMAL); |
| // directly in the InCallScreen, back when this check happened inside the InCallScreen. |
| // |
| // But now, set the global CdmaOtaInCallScreenUiState object into |
| // NORMAL mode, which will then cause the InCallScreen (when it |
| // comes up) to realize that an OTA call is active. |
| |
| app.otaUtils.setCdmaOtaInCallScreenUiState( |
| OtaUtils.CdmaOtaInCallScreenUiState.State.NORMAL); |
| |
| // TODO(OTASP): note app.inCallUiState.inCallScreenMode and |
| // app.cdmaOtaInCallScreenUiState.state are mostly redundant. Combine them. |
| app.inCallUiState.inCallScreenMode = InCallUiState.InCallScreenMode.OTA_NORMAL; |
| |
| // TODO(OTASP / bug 5092031): we ideally should call |
| // otaShowListeningScreen() here to make sure that the DTMF dialpad |
| // becomes visible at the start of the "*228" call: |
| // |
| // // ...and get the OTASP-specific UI into the right state. |
| // app.otaUtils.otaShowListeningScreen(); |
| // if (app.otaUtils.mInCallScreen != null) { |
| // app.otaUtils.mInCallScreen.requestUpdateScreen(); |
| // } |
| // |
| // But this doesn't actually work; the call to otaShowListeningScreen() |
| // *doesn't* actually bring up the listening screen, since the |
| // cdmaOtaConfigData.otaShowListeningScreen config parameter hasn't been |
| // initialized (we haven't run readXmlSettings() yet at this point!) |
| |
| // Also, since the OTA call is now just starting, clear out |
| // the "committed" flag in app.cdmaOtaProvisionData. |
| if (app.cdmaOtaProvisionData != null) { |
| app.cdmaOtaProvisionData.isOtaCallCommitted = false; |
| } |
| } |
| |
| private void setSpeaker(boolean state) { |
| if (DBG) log("setSpeaker : " + state ); |
| |
| if (!mInteractive) { |
| if (DBG) log("non-interactive mode, ignoring setSpeaker."); |
| return; |
| } |
| |
| if (state == PhoneUtils.isSpeakerOn(mContext)) { |
| if (DBG) log("no change. returning"); |
| return; |
| } |
| |
| if (state && mInCallScreen.isBluetoothAvailable() |
| && mInCallScreen.isBluetoothAudioConnected()) { |
| mInCallScreen.disconnectBluetoothAudio(); |
| } |
| PhoneUtils.turnOnSpeaker(mContext, state, true); |
| } |
| |
| /** |
| * Handles OTA Provision events from the telephony layer. |
| * These events come in to this method whether or not |
| * the InCallScreen is visible. |
| * |
| * Possible events are: |
| * OTA Commit Event - OTA provisioning was successful |
| * SPC retries exceeded - SPC failure retries has exceeded, and Phone needs to |
| * power down. |
| */ |
| public void onOtaProvisionStatusChanged(AsyncResult r) { |
| int OtaStatus[] = (int[]) r.result; |
| if (DBG) log("Provision status event!"); |
| if (DBG) log("onOtaProvisionStatusChanged(): status = " |
| + OtaStatus[0] + " ==> " + otaProvisionStatusToString(OtaStatus[0])); |
| |
| // In practice, in a normal successful OTASP call, events come in as follows: |
| // - SPL_UNLOCKED within a couple of seconds after the call starts |
| // - then a delay of around 45 seconds |
| // - then PRL_DOWNLOADED and MDN_DOWNLOADED and COMMITTED within a span of 2 seconds |
| |
| switch(OtaStatus[0]) { |
| case Phone.CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED: |
| if (DBG) log("onOtaProvisionStatusChanged(): RETRIES EXCEEDED"); |
| updateOtaspProgress(); |
| mApplication.cdmaOtaProvisionData.otaSpcUptime = SystemClock.elapsedRealtime(); |
| if (mInteractive) { |
| otaShowSpcErrorNotice(OTA_SPC_TIMEOUT); |
| } else { |
| sendOtaspResult(OTASP_FAILURE_SPC_RETRIES); |
| } |
| // Power.shutdown(); |
| break; |
| |
| case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED: |
| if (DBG) { |
| log("onOtaProvisionStatusChanged(): DONE, isOtaCallCommitted set to true"); |
| } |
| mApplication.cdmaOtaProvisionData.isOtaCallCommitted = true; |
| if (mApplication.cdmaOtaScreenState.otaScreenState != |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED) { |
| updateOtaspProgress(); |
| } |
| |
| break; |
| |
| case Phone.CDMA_OTA_PROVISION_STATUS_SPL_UNLOCKED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_A_KEY_EXCHANGED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_SSD_UPDATED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_NAM_DOWNLOADED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_MDN_DOWNLOADED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_IMSI_DOWNLOADED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_PRL_DOWNLOADED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STARTED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED: |
| case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_ABORTED: |
| // Only update progress when OTA call is in normal state |
| if (getCdmaOtaInCallScreenUiState() == CdmaOtaInCallScreenUiState.State.NORMAL) { |
| if (DBG) log("onOtaProvisionStatusChanged(): change to ProgressScreen"); |
| updateOtaspProgress(); |
| } |
| break; |
| |
| default: |
| if (DBG) log("onOtaProvisionStatusChanged(): Ignoring OtaStatus " + OtaStatus[0]); |
| break; |
| } |
| } |
| |
| /** |
| * Handle a disconnect event from the OTASP call. |
| */ |
| public void onOtaspDisconnect() { |
| if (DBG) log("onOtaspDisconnect()..."); |
| // We only handle this event explicitly in non-interactive mode. |
| // (In interactive mode, the InCallScreen does any post-disconnect |
| // cleanup.) |
| if (!mInteractive) { |
| // Send a success or failure indication back to our caller. |
| updateNonInteractiveOtaSuccessFailure(); |
| } |
| } |
| |
| private void otaShowHome() { |
| if (DBG) log("otaShowHome()..."); |
| mApplication.cdmaOtaScreenState.otaScreenState = |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED; |
| mInCallScreen.endInCallScreenSession(); |
| Intent intent = new Intent(Intent.ACTION_MAIN); |
| intent.addCategory (Intent.CATEGORY_HOME); |
| intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| mContext.startActivityAsUser(intent, UserHandle.CURRENT); |
| return; |
| } |
| |
| private void otaSkipActivation() { |
| if (DBG) log("otaSkipActivation()..."); |
| |
| sendOtaspResult(OTASP_USER_SKIPPED); |
| |
| if (mInteractive) mInCallScreen.finish(); |
| return; |
| } |
| |
| /** |
| * Actually initiate the OTASP call. This method is triggered by the |
| * onscreen "Activate" button, and is only used in interactive mode. |
| */ |
| private void otaPerformActivation() { |
| if (DBG) log("otaPerformActivation()..."); |
| if (!mInteractive) { |
| // We shouldn't ever get here in non-interactive mode! |
| Log.w(LOG_TAG, "otaPerformActivation: not interactive!"); |
| return; |
| } |
| |
| if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) { |
| // Place an outgoing call to the special OTASP number: |
| Intent newIntent = new Intent(Intent.ACTION_CALL); |
| newIntent.setData(Uri.fromParts(Constants.SCHEME_TEL, OTASP_NUMBER, null)); |
| |
| // Initiate the outgoing call: |
| mApplication.callController.placeCall(newIntent); |
| |
| // ...and get the OTASP-specific UI into the right state. |
| otaShowListeningScreen(); |
| mInCallScreen.requestUpdateScreen(); |
| } |
| return; |
| } |
| |
| /** |
| * Show Activation Screen when phone powers up and OTA provision is |
| * required. Also shown when activation fails and user needs |
| * to re-attempt it. Contains ACTIVATE and SKIP buttons |
| * which allow user to start OTA activation or skip the activation process. |
| */ |
| public void otaShowActivateScreen() { |
| if (DBG) log("otaShowActivateScreen()..."); |
| if (mApplication.cdmaOtaConfigData.otaShowActivationScreen |
| == OTA_SHOW_ACTIVATION_SCREEN_ON) { |
| if (DBG) log("otaShowActivateScreen(): show activation screen"); |
| if (!isDialerOpened()) { |
| otaScreenInitialize(); |
| mOtaWidgetData.otaSkipButton.setVisibility(sIsWizardMode ? |
| View.VISIBLE : View.INVISIBLE); |
| mOtaWidgetData.otaTextActivate.setVisibility(View.VISIBLE); |
| mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.VISIBLE); |
| } |
| mApplication.cdmaOtaScreenState.otaScreenState = |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION; |
| } else { |
| if (DBG) log("otaShowActivateScreen(): show home screen"); |
| otaShowHome(); |
| } |
| } |
| |
| /** |
| * Show "Listen for Instruction" screen during OTA call. Shown when OTA Call |
| * is initiated and user needs to listen for network instructions and press |
| * appropriate DTMF digits to proceed to the "Programming in Progress" phase. |
| */ |
| private void otaShowListeningScreen() { |
| if (DBG) log("otaShowListeningScreen()..."); |
| if (!mInteractive) { |
| // We shouldn't ever get here in non-interactive mode! |
| Log.w(LOG_TAG, "otaShowListeningScreen: not interactive!"); |
| return; |
| } |
| |
| if (mApplication.cdmaOtaConfigData.otaShowListeningScreen |
| == OTA_SHOW_LISTENING_SCREEN_ON) { |
| if (DBG) log("otaShowListeningScreen(): show listening screen"); |
| if (!isDialerOpened()) { |
| otaScreenInitialize(); |
| mOtaWidgetData.otaTextListenProgress.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaTextListenProgress.setText(R.string.ota_listen); |
| mOtaWidgetData.otaDtmfDialerView.setVisibility(View.VISIBLE); |
| mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaSpeakerButton.setVisibility(View.VISIBLE); |
| boolean speakerOn = PhoneUtils.isSpeakerOn(mContext); |
| mOtaWidgetData.otaSpeakerButton.setChecked(speakerOn); |
| } |
| mApplication.cdmaOtaScreenState.otaScreenState = |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING; |
| } else { |
| if (DBG) log("otaShowListeningScreen(): show progress screen"); |
| otaShowInProgressScreen(); |
| } |
| } |
| |
| /** |
| * Do any necessary updates (of onscreen UI, for example) |
| * based on the latest status of the OTASP call. |
| */ |
| private void updateOtaspProgress() { |
| if (DBG) log("updateOtaspProgress()... mInteractive = " + mInteractive); |
| if (mInteractive) { |
| // On regular phones we just call through to |
| // otaShowInProgressScreen(), which updates the |
| // InCallScreen's onscreen UI. |
| otaShowInProgressScreen(); |
| } else { |
| // We're not using the InCallScreen to show OTA progress. |
| |
| // For now, at least, there's nothing to do here. |
| // The overall "success" or "failure" indication we send back |
| // (to our caller) is triggered by the DISCONNECT event; |
| // see updateNonInteractiveOtaSuccessFailure(). |
| |
| // But if we ever need to send *intermediate* progress updates back |
| // to our caller, we'd do that here, possbily using the same |
| // PendingIntent that we already use to indicate success or failure. |
| } |
| } |
| |
| /** |
| * When a non-interactive OTASP call completes, send a success or |
| * failure indication back to our caller. |
| * |
| * This is basically the non-interactive equivalent of |
| * otaShowSuccessFailure(). |
| */ |
| private void updateNonInteractiveOtaSuccessFailure() { |
| // This is basically the same logic as otaShowSuccessFailure(): we |
| // check the isOtaCallCommitted bit, and if that's true it means |
| // that activation was successful. |
| |
| if (DBG) log("updateNonInteractiveOtaSuccessFailure(): isOtaCallCommitted = " |
| + mApplication.cdmaOtaProvisionData.isOtaCallCommitted); |
| int resultCode = |
| mApplication.cdmaOtaProvisionData.isOtaCallCommitted |
| ? OTASP_SUCCESS : OTASP_FAILURE; |
| sendOtaspResult(resultCode); |
| } |
| |
| /** |
| * Sends the specified OTASP result code back to our caller (presumably |
| * SetupWizard) via the PendingIntent that they originally sent along with |
| * the ACTION_PERFORM_CDMA_PROVISIONING intent. |
| */ |
| private void sendOtaspResult(int resultCode) { |
| if (DBG) log("sendOtaspResult: resultCode = " + resultCode); |
| |
| // Pass the success or failure indication back to our caller by |
| // adding an additional extra to the PendingIntent we already |
| // have. |
| // (NB: there's a PendingIntent send() method that takes a resultCode |
| // directly, but we can't use that here since that call is only |
| // meaningful for pending intents that are actually used as activity |
| // results.) |
| |
| Intent extraStuff = new Intent(); |
| extraStuff.putExtra(EXTRA_OTASP_RESULT_CODE, resultCode); |
| // When we call PendingIntent.send() below, the extras from this |
| // intent will get merged with any extras already present in |
| // cdmaOtaScreenState.otaspResultCodePendingIntent. |
| |
| if (mApplication.cdmaOtaScreenState == null) { |
| Log.e(LOG_TAG, "updateNonInteractiveOtaSuccessFailure: no cdmaOtaScreenState object!"); |
| return; |
| } |
| if (mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent == null) { |
| Log.w(LOG_TAG, "updateNonInteractiveOtaSuccessFailure: " |
| + "null otaspResultCodePendingIntent!"); |
| return; |
| } |
| |
| try { |
| if (DBG) log("- sendOtaspResult: SENDING PENDING INTENT: " + |
| mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent); |
| mApplication.cdmaOtaScreenState.otaspResultCodePendingIntent.send( |
| mContext, |
| 0, /* resultCode (unused) */ |
| extraStuff); |
| } catch (CanceledException e) { |
| // should never happen because no code cancels the pending intent right now, |
| Log.e(LOG_TAG, "PendingIntent send() failed: " + e); |
| } |
| } |
| |
| /** |
| * Show "Programming In Progress" screen during OTA call. Shown when OTA |
| * provisioning is in progress after user has selected an option. |
| */ |
| private void otaShowInProgressScreen() { |
| if (DBG) log("otaShowInProgressScreen()..."); |
| if (!mInteractive) { |
| // We shouldn't ever get here in non-interactive mode! |
| Log.w(LOG_TAG, "otaShowInProgressScreen: not interactive!"); |
| return; |
| } |
| |
| mApplication.cdmaOtaScreenState.otaScreenState = |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS; |
| |
| if ((mOtaWidgetData == null) || (mInCallScreen == null)) { |
| Log.w(LOG_TAG, "otaShowInProgressScreen: UI widgets not set up yet!"); |
| |
| // TODO(OTASP): our CdmaOtaScreenState is now correct; we just set |
| // it to OTA_STATUS_PROGRESS. But we still need to make sure that |
| // when the InCallScreen eventually comes to the foreground, it |
| // notices that state and does all the same UI updating we do below. |
| return; |
| } |
| |
| if (!isDialerOpened()) { |
| otaScreenInitialize(); |
| mOtaWidgetData.otaTextListenProgress.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaTextListenProgress.setText(R.string.ota_progress); |
| mOtaWidgetData.otaTextProgressBar.setVisibility(View.VISIBLE); |
| mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaSpeakerButton.setVisibility(View.VISIBLE); |
| boolean speakerOn = PhoneUtils.isSpeakerOn(mContext); |
| mOtaWidgetData.otaSpeakerButton.setChecked(speakerOn); |
| } |
| } |
| |
| /** |
| * Show programming failure dialog when OTA provisioning fails. |
| * If OTA provisioning attempts fail more than 3 times, then unsuccessful |
| * dialog is shown. Otherwise a two-second notice is shown with unsuccessful |
| * information. When notice expires, phone returns to activation screen. |
| */ |
| private void otaShowProgramFailure(int length) { |
| if (DBG) log("otaShowProgramFailure()..."); |
| mApplication.cdmaOtaProvisionData.activationCount++; |
| if ((mApplication.cdmaOtaProvisionData.activationCount < |
| mApplication.cdmaOtaConfigData.otaShowActivateFailTimes) |
| && (mApplication.cdmaOtaConfigData.otaShowActivationScreen == |
| OTA_SHOW_ACTIVATION_SCREEN_ON)) { |
| if (DBG) log("otaShowProgramFailure(): activationCount" |
| + mApplication.cdmaOtaProvisionData.activationCount); |
| if (DBG) log("otaShowProgramFailure(): show failure notice"); |
| otaShowProgramFailureNotice(length); |
| } else { |
| if (DBG) log("otaShowProgramFailure(): show failure dialog"); |
| otaShowProgramFailureDialog(); |
| } |
| } |
| |
| /** |
| * Show either programming success dialog when OTA provisioning succeeds, or |
| * programming failure dialog when it fails. See {@link #otaShowProgramFailure} |
| * for more details. |
| */ |
| public void otaShowSuccessFailure() { |
| if (DBG) log("otaShowSuccessFailure()..."); |
| if (!mInteractive) { |
| // We shouldn't ever get here in non-interactive mode! |
| Log.w(LOG_TAG, "otaShowSuccessFailure: not interactive!"); |
| return; |
| } |
| |
| otaScreenInitialize(); |
| if (DBG) log("otaShowSuccessFailure(): isOtaCallCommitted" |
| + mApplication.cdmaOtaProvisionData.isOtaCallCommitted); |
| if (mApplication.cdmaOtaProvisionData.isOtaCallCommitted) { |
| if (DBG) log("otaShowSuccessFailure(), show success dialog"); |
| otaShowProgramSuccessDialog(); |
| } else { |
| if (DBG) log("otaShowSuccessFailure(), show failure dialog"); |
| otaShowProgramFailure(OTA_FAILURE_DIALOG_TIMEOUT); |
| } |
| return; |
| } |
| |
| /** |
| * Show programming failure dialog when OTA provisioning fails more than 3 |
| * times. |
| */ |
| private void otaShowProgramFailureDialog() { |
| if (DBG) log("otaShowProgramFailureDialog()..."); |
| mApplication.cdmaOtaScreenState.otaScreenState = |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG; |
| mOtaWidgetData.otaTitle.setText(R.string.ota_title_problem_with_activation); |
| mOtaWidgetData.otaTextSuccessFail.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaTextSuccessFail.setText(R.string.ota_unsuccessful); |
| mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaTryAgainButton.setVisibility(View.VISIBLE); |
| //close the dialer if open |
| if (isDialerOpened()) { |
| mOtaCallCardDtmfDialer.closeDialer(false); |
| } |
| } |
| |
| /** |
| * Show programming success dialog when OTA provisioning succeeds. |
| */ |
| private void otaShowProgramSuccessDialog() { |
| if (DBG) log("otaShowProgramSuccessDialog()..."); |
| mApplication.cdmaOtaScreenState.otaScreenState = |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG; |
| mOtaWidgetData.otaTitle.setText(R.string.ota_title_activate_success); |
| mOtaWidgetData.otaTextSuccessFail.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaTextSuccessFail.setText(R.string.ota_successful); |
| mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaNextButton.setVisibility(View.VISIBLE); |
| //close the dialer if open |
| if (isDialerOpened()) { |
| mOtaCallCardDtmfDialer.closeDialer(false); |
| } |
| } |
| |
| /** |
| * Show SPC failure notice when SPC attempts exceed 15 times. |
| * During OTA provisioning, if SPC code is incorrect OTA provisioning will |
| * fail. When SPC attempts are over 15, it shows SPC failure notice for one minute and |
| * then phone will power down. |
| */ |
| private void otaShowSpcErrorNotice(int length) { |
| if (DBG) log("otaShowSpcErrorNotice()..."); |
| if (mOtaWidgetData.spcErrorDialog == null) { |
| mApplication.cdmaOtaProvisionData.inOtaSpcState = true; |
| DialogInterface.OnKeyListener keyListener; |
| keyListener = new DialogInterface.OnKeyListener() { |
| public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { |
| log("Ignoring key events..."); |
| return true; |
| }}; |
| mOtaWidgetData.spcErrorDialog = new AlertDialog.Builder(mInCallScreen) |
| .setMessage(R.string.ota_spc_failure) |
| .setOnKeyListener(keyListener) |
| .create(); |
| mOtaWidgetData.spcErrorDialog.getWindow().addFlags( |
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
| | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); |
| mOtaWidgetData.spcErrorDialog.show(); |
| //close the dialer if open |
| if (isDialerOpened()) { |
| mOtaCallCardDtmfDialer.closeDialer(false); |
| } |
| long noticeTime = length*1000; |
| if (DBG) log("otaShowSpcErrorNotice(), remaining SPC noticeTime" + noticeTime); |
| mInCallScreen.requestCloseSpcErrorNotice(noticeTime); |
| } |
| } |
| |
| /** |
| * When SPC notice times out, force phone to power down. |
| */ |
| public void onOtaCloseSpcNotice() { |
| if (DBG) log("onOtaCloseSpcNotice(), send shutdown intent"); |
| Intent shutdown = new Intent(Intent.ACTION_REQUEST_SHUTDOWN); |
| shutdown.putExtra(Intent.EXTRA_KEY_CONFIRM, false); |
| shutdown.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| mContext.startActivity(shutdown); |
| } |
| |
| /** |
| * Show two-second notice when OTA provisioning fails and number of failed attempts |
| * is less then 3. |
| */ |
| private void otaShowProgramFailureNotice(int length) { |
| if (DBG) log("otaShowProgramFailureNotice()..."); |
| if (mOtaWidgetData.otaFailureDialog == null) { |
| mOtaWidgetData.otaFailureDialog = new AlertDialog.Builder(mInCallScreen) |
| .setMessage(R.string.ota_failure) |
| .create(); |
| mOtaWidgetData.otaFailureDialog.getWindow().addFlags( |
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
| | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); |
| mOtaWidgetData.otaFailureDialog.show(); |
| |
| long noticeTime = length*1000; |
| mInCallScreen.requestCloseOtaFailureNotice(noticeTime); |
| } |
| } |
| |
| /** |
| * Handle OTA unsuccessful notice expiry. Dismisses the |
| * two-second notice and shows the activation screen. |
| */ |
| public void onOtaCloseFailureNotice() { |
| if (DBG) log("onOtaCloseFailureNotice()..."); |
| if (mOtaWidgetData.otaFailureDialog != null) { |
| mOtaWidgetData.otaFailureDialog.dismiss(); |
| mOtaWidgetData.otaFailureDialog = null; |
| } |
| otaShowActivateScreen(); |
| } |
| |
| /** |
| * Initialize all OTA UI elements to be gone. Also set inCallPanel, |
| * callCard and the dialpad handle to be gone. This is called before any OTA screen |
| * gets drawn. |
| */ |
| private void otaScreenInitialize() { |
| if (DBG) log("otaScreenInitialize()..."); |
| |
| if (!mInteractive) { |
| // We should never be doing anything with UI elements in |
| // non-interactive mode. |
| Log.w(LOG_TAG, "otaScreenInitialize: not interactive!"); |
| return; |
| } |
| |
| if (mInCallTouchUi != null) mInCallTouchUi.setVisibility(View.GONE); |
| if (mCallCard != null) { |
| mCallCard.setVisibility(View.GONE); |
| // TODO: try removing this. |
| mCallCard.hideCallCardElements(); |
| } |
| |
| mOtaWidgetData.otaTitle.setText(R.string.ota_title_activate); |
| mOtaWidgetData.otaTextActivate.setVisibility(View.GONE); |
| mOtaWidgetData.otaTextListenProgress.setVisibility(View.GONE); |
| mOtaWidgetData.otaTextProgressBar.setVisibility(View.GONE); |
| mOtaWidgetData.otaTextSuccessFail.setVisibility(View.GONE); |
| mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE); |
| mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE); |
| mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE); |
| mOtaWidgetData.otaDtmfDialerView.setVisibility(View.GONE); |
| mOtaWidgetData.otaSpeakerButton.setVisibility(View.GONE); |
| mOtaWidgetData.otaTryAgainButton.setVisibility(View.GONE); |
| mOtaWidgetData.otaNextButton.setVisibility(View.GONE); |
| mOtaWidgetData.otaUpperWidgets.setVisibility(View.VISIBLE); |
| mOtaWidgetData.otaSkipButton.setVisibility(View.VISIBLE); |
| } |
| |
| public void hideOtaScreen() { |
| if (DBG) log("hideOtaScreen()..."); |
| |
| mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE); |
| mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE); |
| mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE); |
| mOtaWidgetData.otaUpperWidgets.setVisibility(View.GONE); |
| } |
| |
| public boolean isDialerOpened() { |
| boolean retval = (mOtaCallCardDtmfDialer != null && mOtaCallCardDtmfDialer.isOpened()); |
| if (DBG) log("- isDialerOpened() ==> " + retval); |
| return retval; |
| } |
| |
| /** |
| * Show the appropriate OTA screen based on the current state of OTA call. |
| * |
| * This is called from the InCallScreen when the screen needs to be |
| * refreshed (and thus is only ever used in interactive mode.) |
| * |
| * Since this is called as part of the InCallScreen.updateScreen() sequence, |
| * this method does *not* post an mInCallScreen.requestUpdateScreen() |
| * request. |
| */ |
| public void otaShowProperScreen() { |
| if (DBG) log("otaShowProperScreen()..."); |
| if (!mInteractive) { |
| // We shouldn't ever get here in non-interactive mode! |
| Log.w(LOG_TAG, "otaShowProperScreen: not interactive!"); |
| return; |
| } |
| |
| if ((mInCallScreen != null) && mInCallScreen.isForegroundActivity()) { |
| if (DBG) log("otaShowProperScreen(): InCallScreen in foreground, currentstate = " |
| + mApplication.cdmaOtaScreenState.otaScreenState); |
| if (mInCallTouchUi != null) { |
| mInCallTouchUi.setVisibility(View.GONE); |
| } |
| if (mCallCard != null) { |
| mCallCard.setVisibility(View.GONE); |
| } |
| if (mApplication.cdmaOtaScreenState.otaScreenState |
| == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION) { |
| otaShowActivateScreen(); |
| } else if (mApplication.cdmaOtaScreenState.otaScreenState |
| == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_LISTENING) { |
| otaShowListeningScreen(); |
| } else if (mApplication.cdmaOtaScreenState.otaScreenState |
| == CdmaOtaScreenState.OtaScreenState.OTA_STATUS_PROGRESS) { |
| otaShowInProgressScreen(); |
| } |
| |
| if (mApplication.cdmaOtaProvisionData.inOtaSpcState) { |
| otaShowSpcErrorNotice(getOtaSpcDisplayTime()); |
| } |
| } |
| } |
| |
| /** |
| * Read configuration values for each OTA screen from config.xml. |
| * These configuration values control visibility of each screen. |
| */ |
| private void readXmlSettings() { |
| if (DBG) log("readXmlSettings()..."); |
| if (mApplication.cdmaOtaConfigData.configComplete) { |
| return; |
| } |
| |
| mApplication.cdmaOtaConfigData.configComplete = true; |
| int tmpOtaShowActivationScreen = |
| mContext.getResources().getInteger(R.integer.OtaShowActivationScreen); |
| mApplication.cdmaOtaConfigData.otaShowActivationScreen = tmpOtaShowActivationScreen; |
| if (DBG) log("readXmlSettings(), otaShowActivationScreen = " |
| + mApplication.cdmaOtaConfigData.otaShowActivationScreen); |
| |
| int tmpOtaShowListeningScreen = |
| mContext.getResources().getInteger(R.integer.OtaShowListeningScreen); |
| mApplication.cdmaOtaConfigData.otaShowListeningScreen = tmpOtaShowListeningScreen; |
| if (DBG) log("readXmlSettings(), otaShowListeningScreen = " |
| + mApplication.cdmaOtaConfigData.otaShowListeningScreen); |
| |
| int tmpOtaShowActivateFailTimes = |
| mContext.getResources().getInteger(R.integer.OtaShowActivateFailTimes); |
| mApplication.cdmaOtaConfigData.otaShowActivateFailTimes = tmpOtaShowActivateFailTimes; |
| if (DBG) log("readXmlSettings(), otaShowActivateFailTimes = " |
| + mApplication.cdmaOtaConfigData.otaShowActivateFailTimes); |
| |
| int tmpOtaPlaySuccessFailureTone = |
| mContext.getResources().getInteger(R.integer.OtaPlaySuccessFailureTone); |
| mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone = tmpOtaPlaySuccessFailureTone; |
| if (DBG) log("readXmlSettings(), otaPlaySuccessFailureTone = " |
| + mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone); |
| } |
| |
| /** |
| * Handle the click events for OTA buttons. |
| */ |
| public void onClickHandler(int id) { |
| switch (id) { |
| case R.id.otaEndButton: |
| onClickOtaEndButton(); |
| break; |
| |
| case R.id.otaSpeakerButton: |
| onClickOtaSpeakerButton(); |
| break; |
| |
| case R.id.otaActivateButton: |
| onClickOtaActivateButton(); |
| break; |
| |
| case R.id.otaSkipButton: |
| onClickOtaActivateSkipButton(); |
| break; |
| |
| case R.id.otaNextButton: |
| onClickOtaActivateNextButton(); |
| break; |
| |
| case R.id.otaTryAgainButton: |
| onClickOtaTryAgainButton(); |
| break; |
| |
| default: |
| if (DBG) log ("onClickHandler: received a click event for unrecognized id"); |
| break; |
| } |
| } |
| |
| private void onClickOtaTryAgainButton() { |
| if (DBG) log("Activation Try Again Clicked!"); |
| if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) { |
| otaShowActivateScreen(); |
| } |
| } |
| |
| private void onClickOtaEndButton() { |
| if (DBG) log("Activation End Call Button Clicked!"); |
| if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) { |
| if (PhoneUtils.hangup(mApplication.mCM) == false) { |
| // If something went wrong when placing the OTA call, |
| // the screen is not updated by the call disconnect |
| // handler and we have to do it here |
| setSpeaker(false); |
| mInCallScreen.handleOtaCallEnd(); |
| } |
| } |
| } |
| |
| private void onClickOtaSpeakerButton() { |
| if (DBG) log("OTA Speaker button Clicked!"); |
| if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) { |
| boolean isChecked = !PhoneUtils.isSpeakerOn(mContext); |
| setSpeaker(isChecked); |
| } |
| } |
| |
| private void onClickOtaActivateButton() { |
| if (DBG) log("Call Activation Clicked!"); |
| otaPerformActivation(); |
| } |
| |
| private void onClickOtaActivateSkipButton() { |
| if (DBG) log("Activation Skip Clicked!"); |
| DialogInterface.OnKeyListener keyListener; |
| keyListener = new DialogInterface.OnKeyListener() { |
| public boolean onKey(DialogInterface dialog, int keyCode, |
| KeyEvent event) { |
| if (DBG) log("Ignoring key events..."); |
| return true; |
| } |
| }; |
| mOtaWidgetData.otaSkipConfirmationDialog = new AlertDialog.Builder(mInCallScreen) |
| .setTitle(R.string.ota_skip_activation_dialog_title) |
| .setMessage(R.string.ota_skip_activation_dialog_message) |
| .setPositiveButton( |
| android.R.string.ok, |
| // "OK" means "skip activation". |
| new AlertDialog.OnClickListener() { |
| public void onClick(DialogInterface dialog, int which) { |
| otaSkipActivation(); |
| } |
| }) |
| .setNegativeButton( |
| android.R.string.cancel, |
| // "Cancel" means just dismiss the dialog. |
| // Don't actually start an activation call. |
| null) |
| .setOnKeyListener(keyListener) |
| .create(); |
| mOtaWidgetData.otaSkipConfirmationDialog.show(); |
| } |
| |
| private void onClickOtaActivateNextButton() { |
| if (DBG) log("Dialog Next Clicked!"); |
| if (!mApplication.cdmaOtaProvisionData.inOtaSpcState) { |
| mApplication.cdmaOtaScreenState.otaScreenState = |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED; |
| otaShowHome(); |
| } |
| } |
| |
| public void dismissAllOtaDialogs() { |
| if (mOtaWidgetData != null) { |
| if (mOtaWidgetData.spcErrorDialog != null) { |
| if (DBG) log("- DISMISSING mSpcErrorDialog."); |
| mOtaWidgetData.spcErrorDialog.dismiss(); |
| mOtaWidgetData.spcErrorDialog = null; |
| } |
| if (mOtaWidgetData.otaFailureDialog != null) { |
| if (DBG) log("- DISMISSING mOtaFailureDialog."); |
| mOtaWidgetData.otaFailureDialog.dismiss(); |
| mOtaWidgetData.otaFailureDialog = null; |
| } |
| } |
| } |
| |
| private int getOtaSpcDisplayTime() { |
| if (DBG) log("getOtaSpcDisplayTime()..."); |
| int tmpSpcTime = 1; |
| if (mApplication.cdmaOtaProvisionData.inOtaSpcState) { |
| long tmpOtaSpcRunningTime = 0; |
| long tmpOtaSpcLeftTime = 0; |
| tmpOtaSpcRunningTime = SystemClock.elapsedRealtime(); |
| tmpOtaSpcLeftTime = |
| tmpOtaSpcRunningTime - mApplication.cdmaOtaProvisionData.otaSpcUptime; |
| if (tmpOtaSpcLeftTime >= OTA_SPC_TIMEOUT*1000) { |
| tmpSpcTime = 1; |
| } else { |
| tmpSpcTime = OTA_SPC_TIMEOUT - (int)tmpOtaSpcLeftTime/1000; |
| } |
| } |
| if (DBG) log("getOtaSpcDisplayTime(), time for SPC error notice: " + tmpSpcTime); |
| return tmpSpcTime; |
| } |
| |
| /** |
| * Initialize the OTA widgets for all OTA screens. |
| */ |
| private void initOtaInCallScreen() { |
| if (DBG) log("initOtaInCallScreen()..."); |
| mOtaWidgetData.otaTitle = (TextView) mInCallScreen.findViewById(R.id.otaTitle); |
| mOtaWidgetData.otaTextActivate = (TextView) mInCallScreen.findViewById(R.id.otaActivate); |
| mOtaWidgetData.otaTextActivate.setVisibility(View.GONE); |
| mOtaWidgetData.otaTextListenProgress = |
| (TextView) mInCallScreen.findViewById(R.id.otaListenProgress); |
| mOtaWidgetData.otaTextProgressBar = |
| (ProgressBar) mInCallScreen.findViewById(R.id.progress_large); |
| mOtaWidgetData.otaTextProgressBar.setIndeterminate(true); |
| mOtaWidgetData.otaTextSuccessFail = |
| (TextView) mInCallScreen.findViewById(R.id.otaSuccessFailStatus); |
| |
| mOtaWidgetData.otaUpperWidgets = |
| (ViewGroup) mInCallScreen.findViewById(R.id.otaUpperWidgets); |
| mOtaWidgetData.callCardOtaButtonsListenProgress = |
| (View) mInCallScreen.findViewById(R.id.callCardOtaListenProgress); |
| mOtaWidgetData.callCardOtaButtonsActivate = |
| (View) mInCallScreen.findViewById(R.id.callCardOtaActivate); |
| mOtaWidgetData.callCardOtaButtonsFailSuccess = |
| (View) mInCallScreen.findViewById(R.id.callCardOtaFailOrSuccessful); |
| |
| mOtaWidgetData.otaEndButton = (Button) mInCallScreen.findViewById(R.id.otaEndButton); |
| mOtaWidgetData.otaEndButton.setOnClickListener(mInCallScreen); |
| mOtaWidgetData.otaSpeakerButton = |
| (ToggleButton) mInCallScreen.findViewById(R.id.otaSpeakerButton); |
| mOtaWidgetData.otaSpeakerButton.setOnClickListener(mInCallScreen); |
| mOtaWidgetData.otaActivateButton = |
| (Button) mInCallScreen.findViewById(R.id.otaActivateButton); |
| mOtaWidgetData.otaActivateButton.setOnClickListener(mInCallScreen); |
| mOtaWidgetData.otaSkipButton = (Button) mInCallScreen.findViewById(R.id.otaSkipButton); |
| mOtaWidgetData.otaSkipButton.setOnClickListener(mInCallScreen); |
| mOtaWidgetData.otaNextButton = (Button) mInCallScreen.findViewById(R.id.otaNextButton); |
| mOtaWidgetData.otaNextButton.setOnClickListener(mInCallScreen); |
| mOtaWidgetData.otaTryAgainButton = |
| (Button) mInCallScreen.findViewById(R.id.otaTryAgainButton); |
| mOtaWidgetData.otaTryAgainButton.setOnClickListener(mInCallScreen); |
| |
| mOtaWidgetData.otaDtmfDialerView = |
| (DTMFTwelveKeyDialerView) mInCallScreen.findViewById(R.id.otaDtmfDialerView); |
| // Sanity-check: the otaDtmfDialerView widget should *always* be present. |
| if (mOtaWidgetData.otaDtmfDialerView == null) { |
| throw new IllegalStateException("initOtaInCallScreen: couldn't find otaDtmfDialerView"); |
| } |
| |
| // Create a new DTMFTwelveKeyDialer instance purely for use by the |
| // DTMFTwelveKeyDialerView ("otaDtmfDialerView") that comes from |
| // otacall_card.xml. |
| mOtaCallCardDtmfDialer = new DTMFTwelveKeyDialer(mInCallScreen, |
| mOtaWidgetData.otaDtmfDialerView); |
| |
| // Initialize the new DTMFTwelveKeyDialer instance. This is |
| // needed to play local DTMF tones. |
| mOtaCallCardDtmfDialer.startDialerSession(); |
| |
| mOtaWidgetData.otaDtmfDialerView.setDialer(mOtaCallCardDtmfDialer); |
| } |
| |
| /** |
| * Clear out all OTA UI widget elements. Needs to get called |
| * when OTA call ends or InCallScreen is destroyed. |
| * @param disableSpeaker parameter control whether Speaker should be turned off. |
| */ |
| public void cleanOtaScreen(boolean disableSpeaker) { |
| if (DBG) log("OTA ends, cleanOtaScreen!"); |
| |
| mApplication.cdmaOtaScreenState.otaScreenState = |
| CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED; |
| mApplication.cdmaOtaProvisionData.isOtaCallCommitted = false; |
| mApplication.cdmaOtaProvisionData.isOtaCallIntentProcessed = false; |
| mApplication.cdmaOtaProvisionData.inOtaSpcState = false; |
| mApplication.cdmaOtaProvisionData.activationCount = 0; |
| mApplication.cdmaOtaProvisionData.otaSpcUptime = 0; |
| mApplication.cdmaOtaInCallScreenUiState.state = State.UNDEFINED; |
| |
| if (mInteractive && (mOtaWidgetData != null)) { |
| if (mInCallTouchUi != null) mInCallTouchUi.setVisibility(View.VISIBLE); |
| if (mCallCard != null) { |
| mCallCard.setVisibility(View.VISIBLE); |
| mCallCard.hideCallCardElements(); |
| } |
| |
| // Free resources from the DTMFTwelveKeyDialer instance we created |
| // in initOtaInCallScreen(). |
| if (mOtaCallCardDtmfDialer != null) { |
| mOtaCallCardDtmfDialer.stopDialerSession(); |
| } |
| |
| mOtaWidgetData.otaTextActivate.setVisibility(View.GONE); |
| mOtaWidgetData.otaTextListenProgress.setVisibility(View.GONE); |
| mOtaWidgetData.otaTextProgressBar.setVisibility(View.GONE); |
| mOtaWidgetData.otaTextSuccessFail.setVisibility(View.GONE); |
| mOtaWidgetData.callCardOtaButtonsActivate.setVisibility(View.GONE); |
| mOtaWidgetData.callCardOtaButtonsListenProgress.setVisibility(View.GONE); |
| mOtaWidgetData.callCardOtaButtonsFailSuccess.setVisibility(View.GONE); |
| mOtaWidgetData.otaUpperWidgets.setVisibility(View.GONE); |
| mOtaWidgetData.otaDtmfDialerView.setVisibility(View.GONE); |
| mOtaWidgetData.otaNextButton.setVisibility(View.GONE); |
| mOtaWidgetData.otaTryAgainButton.setVisibility(View.GONE); |
| } |
| |
| // turn off the speaker in case it was turned on |
| // but the OTA call could not be completed |
| if (disableSpeaker) { |
| setSpeaker(false); |
| } |
| } |
| |
| /** |
| * Defines OTA information that needs to be maintained during |
| * an OTA call when display orientation changes. |
| */ |
| public static class CdmaOtaProvisionData { |
| public boolean isOtaCallCommitted; |
| public boolean isOtaCallIntentProcessed; |
| public boolean inOtaSpcState; |
| public int activationCount; |
| public long otaSpcUptime; |
| } |
| |
| /** |
| * Defines OTA screen configuration items read from config.xml |
| * and used to control OTA display. |
| */ |
| public static class CdmaOtaConfigData { |
| public int otaShowActivationScreen; |
| public int otaShowListeningScreen; |
| public int otaShowActivateFailTimes; |
| public int otaPlaySuccessFailureTone; |
| public boolean configComplete; |
| public CdmaOtaConfigData() { |
| if (DBG) log("CdmaOtaConfigData constructor!"); |
| otaShowActivationScreen = OTA_SHOW_ACTIVATION_SCREEN_OFF; |
| otaShowListeningScreen = OTA_SHOW_LISTENING_SCREEN_OFF; |
| otaShowActivateFailTimes = OTA_SHOW_ACTIVATE_FAIL_COUNT_OFF; |
| otaPlaySuccessFailureTone = OTA_PLAY_SUCCESS_FAILURE_TONE_OFF; |
| } |
| } |
| |
| /** |
| * The state of the OTA InCallScreen UI. |
| */ |
| public static class CdmaOtaInCallScreenUiState { |
| public enum State { |
| UNDEFINED, |
| NORMAL, |
| ENDED |
| } |
| |
| public State state; |
| |
| public CdmaOtaInCallScreenUiState() { |
| if (DBG) log("CdmaOtaInCallScreenState: constructor init to UNDEFINED"); |
| state = CdmaOtaInCallScreenUiState.State.UNDEFINED; |
| } |
| } |
| |
| /** |
| * Save the Ota InCallScreen UI state |
| */ |
| public void setCdmaOtaInCallScreenUiState(CdmaOtaInCallScreenUiState.State state) { |
| if (DBG) log("setCdmaOtaInCallScreenState: " + state); |
| mApplication.cdmaOtaInCallScreenUiState.state = state; |
| } |
| |
| /** |
| * Get the Ota InCallScreen UI state |
| */ |
| public CdmaOtaInCallScreenUiState.State getCdmaOtaInCallScreenUiState() { |
| if (DBG) log("getCdmaOtaInCallScreenState: " |
| + mApplication.cdmaOtaInCallScreenUiState.state); |
| return mApplication.cdmaOtaInCallScreenUiState.state; |
| } |
| |
| /** |
| * The OTA screen state machine. |
| */ |
| public static class CdmaOtaScreenState { |
| public enum OtaScreenState { |
| OTA_STATUS_UNDEFINED, |
| OTA_STATUS_ACTIVATION, |
| OTA_STATUS_LISTENING, |
| OTA_STATUS_PROGRESS, |
| OTA_STATUS_SUCCESS_FAILURE_DLG |
| } |
| |
| public OtaScreenState otaScreenState; |
| |
| public CdmaOtaScreenState() { |
| otaScreenState = OtaScreenState.OTA_STATUS_UNDEFINED; |
| } |
| |
| /** |
| * {@link PendingIntent} used to report an OTASP result status code |
| * back to our caller. Can be null. |
| * |
| * Our caller (presumably SetupWizard) may create this PendingIntent, |
| * pointing back at itself, and passes it along as an extra with the |
| * ACTION_PERFORM_CDMA_PROVISIONING intent. Then, when there's an |
| * OTASP result to report, we send that PendingIntent back, adding an |
| * extra called EXTRA_OTASP_RESULT_CODE to indicate the result. |
| * |
| * Possible result values are the OTASP_RESULT_* constants. |
| */ |
| public PendingIntent otaspResultCodePendingIntent; |
| } |
| |
| /** @see com.android.internal.telephony.Phone */ |
| private static String otaProvisionStatusToString(int status) { |
| switch (status) { |
| case Phone.CDMA_OTA_PROVISION_STATUS_SPL_UNLOCKED: |
| return "SPL_UNLOCKED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_SPC_RETRIES_EXCEEDED: |
| return "SPC_RETRIES_EXCEEDED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_A_KEY_EXCHANGED: |
| return "A_KEY_EXCHANGED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_SSD_UPDATED: |
| return "SSD_UPDATED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_NAM_DOWNLOADED: |
| return "NAM_DOWNLOADED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_MDN_DOWNLOADED: |
| return "MDN_DOWNLOADED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_IMSI_DOWNLOADED: |
| return "IMSI_DOWNLOADED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_PRL_DOWNLOADED: |
| return "PRL_DOWNLOADED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED: |
| return "COMMITTED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STARTED: |
| return "OTAPA_STARTED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED: |
| return "OTAPA_STOPPED"; |
| case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_ABORTED: |
| return "OTAPA_ABORTED"; |
| default: |
| return "<unknown status" + status + ">"; |
| } |
| } |
| |
| private static int getLteOnCdmaMode(Context context) { |
| final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( |
| Context.TELEPHONY_SERVICE); |
| // If the telephony manager is not available yet, or if it doesn't know the answer yet, |
| // try falling back on the system property that may or may not be there |
| if (telephonyManager == null |
| || telephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_UNKNOWN) { |
| return SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE, |
| PhoneConstants.LTE_ON_CDMA_UNKNOWN); |
| } |
| return telephonyManager.getLteOnCdmaMode(); |
| } |
| |
| private static void log(String msg) { |
| Log.d(LOG_TAG, msg); |
| } |
| |
| private static void loge(String msg) { |
| Log.e(LOG_TAG, msg); |
| } |
| } |