Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2006 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 android.app.Activity;
     20 import android.app.Application;
     21 import android.app.KeyguardManager;
     22 import android.app.ProgressDialog;
     23 import android.app.StatusBarManager;
     24 import android.bluetooth.BluetoothAdapter;
     25 import android.bluetooth.BluetoothHeadset;
     26 import android.content.BroadcastReceiver;
     27 import android.content.ContentResolver;
     28 import android.content.Context;
     29 import android.content.Intent;
     30 import android.content.IntentFilter;
     31 import android.content.res.Configuration;
     32 import android.media.AudioManager;
     33 import android.net.Uri;
     34 import android.os.AsyncResult;
     35 import android.os.Binder;
     36 import android.os.Handler;
     37 import android.os.IBinder;
     38 import android.os.IPowerManager;
     39 import android.os.LocalPowerManager;
     40 import android.os.Message;
     41 import android.os.PowerManager;
     42 import android.os.RemoteException;
     43 import android.os.ServiceManager;
     44 import android.os.SystemClock;
     45 import android.os.SystemProperties;
     46 import android.preference.PreferenceManager;
     47 import android.provider.Settings.System;
     48 import android.telephony.ServiceState;
     49 import android.util.Config;
     50 import android.util.Log;
     51 import android.view.KeyEvent;
     52 import android.widget.Toast;
     53 
     54 import com.android.internal.telephony.Call;
     55 import com.android.internal.telephony.CallManager;
     56 import com.android.internal.telephony.IccCard;
     57 import com.android.internal.telephony.MmiCode;
     58 import com.android.internal.telephony.Phone;
     59 import com.android.internal.telephony.PhoneFactory;
     60 import com.android.internal.telephony.TelephonyIntents;
     61 import com.android.internal.telephony.cdma.EriInfo;
     62 import com.android.internal.telephony.cdma.TtyIntent;
     63 import com.android.internal.telephony.sip.SipPhoneFactory;
     64 import com.android.phone.OtaUtils.CdmaOtaScreenState;
     65 import com.android.server.sip.SipService;
     66 
     67 /**
     68  * Top-level Application class for the Phone app.
     69  */
     70 public class PhoneApp extends Application implements AccelerometerListener.OrientationListener {
     71     /* package */ static final String LOG_TAG = "PhoneApp";
     72 
     73     /**
     74      * Phone app-wide debug level:
     75      *   0 - no debug logging
     76      *   1 - normal debug logging if ro.debuggable is set (which is true in
     77      *       "eng" and "userdebug" builds but not "user" builds)
     78      *   2 - ultra-verbose debug logging
     79      *
     80      * Most individual classes in the phone app have a local DBG constant,
     81      * typically set to
     82      *   (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1)
     83      * or else
     84      *   (PhoneApp.DBG_LEVEL >= 2)
     85      * depending on the desired verbosity.
     86      *
     87      * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 *************
     88      */
     89     /* package */ static final int DBG_LEVEL = 0;
     90 
     91     private static final boolean DBG =
     92             (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
     93     private static final boolean VDBG = (PhoneApp.DBG_LEVEL >= 2);
     94 
     95     // Message codes; see mHandler below.
     96     private static final int EVENT_SIM_NETWORK_LOCKED = 3;
     97     private static final int EVENT_WIRED_HEADSET_PLUG = 7;
     98     private static final int EVENT_SIM_STATE_CHANGED = 8;
     99     private static final int EVENT_UPDATE_INCALL_NOTIFICATION = 9;
    100     private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10;
    101     private static final int EVENT_DATA_ROAMING_OK = 11;
    102     private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
    103     private static final int EVENT_DOCK_STATE_CHANGED = 13;
    104     private static final int EVENT_TTY_PREFERRED_MODE_CHANGED = 14;
    105     private static final int EVENT_TTY_MODE_GET = 15;
    106     private static final int EVENT_TTY_MODE_SET = 16;
    107     private static final int EVENT_START_SIP_SERVICE = 17;
    108 
    109     // The MMI codes are also used by the InCallScreen.
    110     public static final int MMI_INITIATE = 51;
    111     public static final int MMI_COMPLETE = 52;
    112     public static final int MMI_CANCEL = 53;
    113     // Don't use message codes larger than 99 here; those are reserved for
    114     // the individual Activities of the Phone UI.
    115 
    116     /**
    117      * Allowable values for the poke lock code (timeout between a user activity and the
    118      * going to sleep), please refer to {@link com.android.server.PowerManagerService}
    119      * for additional reference.
    120      *   SHORT uses the short delay for the timeout (SHORT_KEYLIGHT_DELAY, 6 sec)
    121      *   MEDIUM uses the medium delay for the timeout (MEDIUM_KEYLIGHT_DELAY, 15 sec)
    122      *   DEFAULT is the system-wide default delay for the timeout (1 min)
    123      */
    124     public enum ScreenTimeoutDuration {
    125         SHORT,
    126         MEDIUM,
    127         DEFAULT
    128     }
    129 
    130     /**
    131      * Allowable values for the wake lock code.
    132      *   SLEEP means the device can be put to sleep.
    133      *   PARTIAL means wake the processor, but we display can be kept off.
    134      *   FULL means wake both the processor and the display.
    135      */
    136     public enum WakeState {
    137         SLEEP,
    138         PARTIAL,
    139         FULL
    140     }
    141 
    142     private static PhoneApp sMe;
    143 
    144     // A few important fields we expose to the rest of the package
    145     // directly (rather than thru set/get methods) for efficiency.
    146     Phone phone;
    147     CallNotifier notifier;
    148     Ringer ringer;
    149     BluetoothHandsfree mBtHandsfree;
    150     PhoneInterfaceManager phoneMgr;
    151     CallManager mCM;
    152     int mBluetoothHeadsetState = BluetoothHeadset.STATE_ERROR;
    153     int mBluetoothHeadsetAudioState = BluetoothHeadset.STATE_ERROR;
    154     boolean mShowBluetoothIndication = false;
    155     static int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    156 
    157     // Internal PhoneApp Call state tracker
    158     CdmaPhoneCallState cdmaPhoneCallState;
    159 
    160     // The InCallScreen instance (or null if the InCallScreen hasn't been
    161     // created yet.)
    162     private InCallScreen mInCallScreen;
    163 
    164     // The currently-active PUK entry activity and progress dialog.
    165     // Normally, these are the Emergency Dialer and the subsequent
    166     // progress dialog.  null if there is are no such objects in
    167     // the foreground.
    168     private Activity mPUKEntryActivity;
    169     private ProgressDialog mPUKEntryProgressDialog;
    170 
    171     private boolean mIsSimPinEnabled;
    172     private String mCachedSimPin;
    173 
    174     // True if a wired headset is currently plugged in, based on the state
    175     // from the latest Intent.ACTION_HEADSET_PLUG broadcast we received in
    176     // mReceiver.onReceive().
    177     private boolean mIsHeadsetPlugged;
    178 
    179     // True if the keyboard is currently *not* hidden
    180     // Gets updated whenever there is a Configuration change
    181     private boolean mIsHardKeyboardOpen;
    182 
    183     // True if we are beginning a call, but the phone state has not changed yet
    184     private boolean mBeginningCall;
    185 
    186     // Last phone state seen by updatePhoneState()
    187     Phone.State mLastPhoneState = Phone.State.IDLE;
    188 
    189     private WakeState mWakeState = WakeState.SLEEP;
    190     private ScreenTimeoutDuration mScreenTimeoutDuration = ScreenTimeoutDuration.DEFAULT;
    191     private boolean mIgnoreTouchUserActivity = false;
    192     private IBinder mPokeLockToken = new Binder();
    193     private IPowerManager mPowerManagerService;
    194     private PowerManager.WakeLock mWakeLock;
    195     private PowerManager.WakeLock mPartialWakeLock;
    196     private PowerManager.WakeLock mProximityWakeLock;
    197     private KeyguardManager mKeyguardManager;
    198     private StatusBarManager mStatusBarManager;
    199     private int mStatusBarDisableCount;
    200     private AccelerometerListener mAccelerometerListener;
    201     private int mOrientation = AccelerometerListener.ORIENTATION_UNKNOWN;
    202 
    203     // Broadcast receiver for various intent broadcasts (see onCreate())
    204     private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver();
    205 
    206     // Broadcast receiver purely for ACTION_MEDIA_BUTTON broadcasts
    207     private final BroadcastReceiver mMediaButtonReceiver = new MediaButtonBroadcastReceiver();
    208 
    209     /** boolean indicating restoring mute state on InCallScreen.onResume() */
    210     private boolean mShouldRestoreMuteOnInCallResume;
    211 
    212     // Following are the CDMA OTA information Objects used during OTA Call.
    213     // cdmaOtaProvisionData object store static OTA information that needs
    214     // to be maintained even during Slider open/close scenarios.
    215     // cdmaOtaConfigData object stores configuration info to control visiblity
    216     // of each OTA Screens.
    217     // cdmaOtaScreenState object store OTA Screen State information.
    218     public OtaUtils.CdmaOtaProvisionData cdmaOtaProvisionData;
    219     public OtaUtils.CdmaOtaConfigData cdmaOtaConfigData;
    220     public OtaUtils.CdmaOtaScreenState cdmaOtaScreenState;
    221     public OtaUtils.CdmaOtaInCallScreenUiState cdmaOtaInCallScreenUiState;
    222 
    223     // TTY feature enabled on this platform
    224     private boolean mTtyEnabled;
    225     // Current TTY operating mode selected by user
    226     private int mPreferredTtyMode = Phone.TTY_MODE_OFF;
    227 
    228     /**
    229      * Set the restore mute state flag. Used when we are setting the mute state
    230      * OUTSIDE of user interaction {@link PhoneUtils#startNewCall(Phone)}
    231      */
    232     /*package*/void setRestoreMuteOnInCallResume (boolean mode) {
    233         mShouldRestoreMuteOnInCallResume = mode;
    234     }
    235 
    236     /**
    237      * Get the restore mute state flag.
    238      * This is used by the InCallScreen {@link InCallScreen#onResume()} to figure
    239      * out if we need to restore the mute state for the current active call.
    240      */
    241     /*package*/boolean getRestoreMuteOnInCallResume () {
    242         return mShouldRestoreMuteOnInCallResume;
    243     }
    244 
    245     Handler mHandler = new Handler() {
    246         @Override
    247         public void handleMessage(Message msg) {
    248             Phone.State phoneState;
    249             switch (msg.what) {
    250                 // Starts the SIP service. It's a no-op if SIP API is not supported
    251                 // on the deivce.
    252                 // TODO: Having the phone process host the SIP service is only
    253                 // temporary. Will move it to a persistent communication process
    254                 // later.
    255                 case EVENT_START_SIP_SERVICE:
    256                     SipService.start(getApplicationContext());
    257                     break;
    258 
    259                 // TODO: This event should be handled by the lock screen, just
    260                 // like the "SIM missing" and "Sim locked" cases (bug 1804111).
    261                 case EVENT_SIM_NETWORK_LOCKED:
    262                     if (getResources().getBoolean(R.bool.ignore_sim_network_locked_events)) {
    263                         // Some products don't have the concept of a "SIM network lock"
    264                         Log.i(LOG_TAG, "Ignoring EVENT_SIM_NETWORK_LOCKED event; "
    265                               + "not showing 'SIM network unlock' PIN entry screen");
    266                     } else {
    267                         // Normal case: show the "SIM network unlock" PIN entry screen.
    268                         // The user won't be able to do anything else until
    269                         // they enter a valid SIM network PIN.
    270                         Log.i(LOG_TAG, "show sim depersonal panel");
    271                         IccNetworkDepersonalizationPanel ndpPanel =
    272                                 new IccNetworkDepersonalizationPanel(PhoneApp.getInstance());
    273                         ndpPanel.show();
    274                     }
    275                     break;
    276 
    277                 case EVENT_UPDATE_INCALL_NOTIFICATION:
    278                     // Tell the NotificationMgr to update the "ongoing
    279                     // call" icon in the status bar, if necessary.
    280                     // Currently, this is triggered by a bluetooth headset
    281                     // state change (since the status bar icon needs to
    282                     // turn blue when bluetooth is active.)
    283                     if (DBG) Log.d (LOG_TAG, "- updating in-call notification from handler...");
    284                     NotificationMgr.getDefault().updateInCallNotification();
    285                     break;
    286 
    287                 case EVENT_DATA_ROAMING_DISCONNECTED:
    288                     NotificationMgr.getDefault().showDataDisconnectedRoaming();
    289                     break;
    290 
    291                 case EVENT_DATA_ROAMING_OK:
    292                     NotificationMgr.getDefault().hideDataDisconnectedRoaming();
    293                     break;
    294 
    295                 case MMI_COMPLETE:
    296                     onMMIComplete((AsyncResult) msg.obj);
    297                     break;
    298 
    299                 case MMI_CANCEL:
    300                     PhoneUtils.cancelMmiCode(phone);
    301                     break;
    302 
    303                 case EVENT_WIRED_HEADSET_PLUG:
    304                     // Since the presence of a wired headset or bluetooth affects the
    305                     // speakerphone, update the "speaker" state.  We ONLY want to do
    306                     // this on the wired headset connect / disconnect events for now
    307                     // though, so we're only triggering on EVENT_WIRED_HEADSET_PLUG.
    308 
    309                     phoneState = mCM.getState();
    310                     // Do not change speaker state if phone is not off hook
    311                     if (phoneState == Phone.State.OFFHOOK) {
    312                         if (mBtHandsfree == null || !mBtHandsfree.isAudioOn()) {
    313                             if (!isHeadsetPlugged()) {
    314                                 // if the state is "not connected", restore the speaker state.
    315                                 PhoneUtils.restoreSpeakerMode(getApplicationContext());
    316                             } else {
    317                                 // if the state is "connected", force the speaker off without
    318                                 // storing the state.
    319                                 PhoneUtils.turnOnSpeaker(getApplicationContext(), false, false);
    320                             }
    321                         }
    322                     }
    323                     // Update the Proximity sensor based on headset state
    324                     updateProximitySensorMode(phoneState);
    325 
    326                     // Force TTY state update according to new headset state
    327                     if (mTtyEnabled) {
    328                         sendMessage(obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0));
    329                     }
    330                     break;
    331 
    332                 case EVENT_SIM_STATE_CHANGED:
    333                     // Marks the event where the SIM goes into ready state.
    334                     // Right now, this is only used for the PUK-unlocking
    335                     // process.
    336                     if (msg.obj.equals(IccCard.INTENT_VALUE_ICC_READY)) {
    337                         // when the right event is triggered and there
    338                         // are UI objects in the foreground, we close
    339                         // them to display the lock panel.
    340                         if (mPUKEntryActivity != null) {
    341                             mPUKEntryActivity.finish();
    342                             mPUKEntryActivity = null;
    343                         }
    344                         if (mPUKEntryProgressDialog != null) {
    345                             mPUKEntryProgressDialog.dismiss();
    346                             mPUKEntryProgressDialog = null;
    347                         }
    348                     }
    349                     break;
    350 
    351                 case EVENT_UNSOL_CDMA_INFO_RECORD:
    352                     //TODO: handle message here;
    353                     break;
    354 
    355                 case EVENT_DOCK_STATE_CHANGED:
    356                     // If the phone is docked/undocked during a call, and no wired or BT headset
    357                     // is connected: turn on/off the speaker accordingly.
    358                     boolean inDockMode = false;
    359                     if (mDockState == Intent.EXTRA_DOCK_STATE_DESK ||
    360                             mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
    361                         inDockMode = true;
    362                     }
    363                     if (VDBG) Log.d(LOG_TAG, "received EVENT_DOCK_STATE_CHANGED. Phone inDock = "
    364                             + inDockMode);
    365 
    366                     phoneState = mCM.getState();
    367                     if (phoneState == Phone.State.OFFHOOK &&
    368                             !isHeadsetPlugged() &&
    369                             !(mBtHandsfree != null && mBtHandsfree.isAudioOn())) {
    370                         PhoneUtils.turnOnSpeaker(getApplicationContext(), inDockMode, true);
    371 
    372                         if (mInCallScreen != null) {
    373                             mInCallScreen.requestUpdateTouchUi();
    374                         }
    375                     }
    376 
    377                 case EVENT_TTY_PREFERRED_MODE_CHANGED:
    378                     // TTY mode is only applied if a headset is connected
    379                     int ttyMode;
    380                     if (isHeadsetPlugged()) {
    381                         ttyMode = mPreferredTtyMode;
    382                     } else {
    383                         ttyMode = Phone.TTY_MODE_OFF;
    384                     }
    385                     phone.setTTYMode(ttyMode, mHandler.obtainMessage(EVENT_TTY_MODE_SET));
    386                     break;
    387 
    388                 case EVENT_TTY_MODE_GET:
    389                     handleQueryTTYModeResponse(msg);
    390                     break;
    391 
    392                 case EVENT_TTY_MODE_SET:
    393                     handleSetTTYModeResponse(msg);
    394                     break;
    395             }
    396         }
    397     };
    398 
    399     public PhoneApp() {
    400         sMe = this;
    401     }
    402 
    403     @Override
    404     public void onCreate() {
    405         if (VDBG) Log.v(LOG_TAG, "onCreate()...");
    406 
    407         ContentResolver resolver = getContentResolver();
    408 
    409         if (phone == null) {
    410             // Initialize the telephony framework
    411             PhoneFactory.makeDefaultPhones(this);
    412 
    413             // Get the default phone
    414             phone = PhoneFactory.getDefaultPhone();
    415 
    416             mCM = CallManager.getInstance();
    417             mCM.registerPhone(phone);
    418 
    419 
    420             NotificationMgr.init(this);
    421 
    422             phoneMgr = new PhoneInterfaceManager(this, phone);
    423 
    424             mHandler.sendEmptyMessage(EVENT_START_SIP_SERVICE);
    425 
    426             int phoneType = phone.getPhoneType();
    427 
    428             if (phoneType == Phone.PHONE_TYPE_CDMA) {
    429                 // Create an instance of CdmaPhoneCallState and initialize it to IDLE
    430                 cdmaPhoneCallState = new CdmaPhoneCallState();
    431                 cdmaPhoneCallState.CdmaPhoneCallStateInit();
    432             }
    433 
    434             if (BluetoothAdapter.getDefaultAdapter() != null) {
    435                 mBtHandsfree = new BluetoothHandsfree(this, mCM);
    436                 startService(new Intent(this, BluetoothHeadsetService.class));
    437             } else {
    438                 // Device is not bluetooth capable
    439                 mBtHandsfree = null;
    440             }
    441 
    442             ringer = new Ringer(this);
    443 
    444             // before registering for phone state changes
    445             PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    446             mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
    447                     | PowerManager.ACQUIRE_CAUSES_WAKEUP,
    448                     LOG_TAG);
    449             // lock used to keep the processor awake, when we don't care for the display.
    450             mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
    451                     | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
    452             // Wake lock used to control proximity sensor behavior.
    453             if ((pm.getSupportedWakeLockFlags()
    454                  & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) != 0x0) {
    455                 mProximityWakeLock =
    456                         pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, LOG_TAG);
    457             }
    458             if (DBG) Log.d(LOG_TAG, "onCreate: mProximityWakeLock: " + mProximityWakeLock);
    459 
    460             // create mAccelerometerListener only if we are using the proximity sensor
    461             if (proximitySensorModeEnabled()) {
    462                 mAccelerometerListener = new AccelerometerListener(this, this);
    463             }
    464 
    465             mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    466             mStatusBarManager = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
    467 
    468             // get a handle to the service so that we can use it later when we
    469             // want to set the poke lock.
    470             mPowerManagerService = IPowerManager.Stub.asInterface(
    471                     ServiceManager.getService("power"));
    472 
    473             notifier = new CallNotifier(this, phone, ringer, mBtHandsfree, new CallLogAsync());
    474 
    475             // register for ICC status
    476             IccCard sim = phone.getIccCard();
    477             if (sim != null) {
    478                 if (VDBG) Log.v(LOG_TAG, "register for ICC status");
    479                 sim.registerForNetworkLocked(mHandler, EVENT_SIM_NETWORK_LOCKED, null);
    480             }
    481 
    482             // register for MMI/USSD
    483             mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
    484 
    485             // register connection tracking to PhoneUtils
    486             PhoneUtils.initializeConnectionHandler(mCM);
    487 
    488             // Read platform settings for TTY feature
    489             mTtyEnabled = getResources().getBoolean(R.bool.tty_enabled);
    490 
    491             // Register for misc other intent broadcasts.
    492             IntentFilter intentFilter =
    493                     new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
    494             intentFilter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
    495             intentFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
    496             intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
    497             intentFilter.addAction(Intent.ACTION_HEADSET_PLUG);
    498             intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
    499             intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
    500             intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    501             intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
    502             intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
    503             intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
    504             if (mTtyEnabled) {
    505                 intentFilter.addAction(TtyIntent.TTY_PREFERRED_MODE_CHANGE_ACTION);
    506             }
    507             intentFilter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
    508             registerReceiver(mReceiver, intentFilter);
    509 
    510             // Use a separate receiver for ACTION_MEDIA_BUTTON broadcasts,
    511             // since we need to manually adjust its priority (to make sure
    512             // we get these intents *before* the media player.)
    513             IntentFilter mediaButtonIntentFilter =
    514                     new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
    515             //
    516             // Make sure we're higher priority than the media player's
    517             // MediaButtonIntentReceiver (which currently has the default
    518             // priority of zero; see apps/Music/AndroidManifest.xml.)
    519             mediaButtonIntentFilter.setPriority(1);
    520             //
    521             registerReceiver(mMediaButtonReceiver, mediaButtonIntentFilter);
    522 
    523             //set the default values for the preferences in the phone.
    524             PreferenceManager.setDefaultValues(this, R.xml.network_setting, false);
    525 
    526             PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);
    527 
    528             // Make sure the audio mode (along with some
    529             // audio-mode-related state of our own) is initialized
    530             // correctly, given the current state of the phone.
    531             PhoneUtils.setAudioMode(mCM);
    532         }
    533 
    534         boolean phoneIsCdma = (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
    535 
    536         if (phoneIsCdma) {
    537             cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
    538             cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();
    539             cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();
    540             cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();
    541         }
    542 
    543         // XXX pre-load the SimProvider so that it's ready
    544         resolver.getType(Uri.parse("content://icc/adn"));
    545 
    546         // start with the default value to set the mute state.
    547         mShouldRestoreMuteOnInCallResume = false;
    548 
    549         // TODO: Register for Cdma Information Records
    550         // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);
    551 
    552         // Read TTY settings and store it into BP NV.
    553         // AP owns (i.e. stores) the TTY setting in AP settings database and pushes the setting
    554         // to BP at power up (BP does not need to make the TTY setting persistent storage).
    555         // This way, there is a single owner (i.e AP) for the TTY setting in the phone.
    556         if (mTtyEnabled) {
    557             mPreferredTtyMode = android.provider.Settings.Secure.getInt(
    558                     phone.getContext().getContentResolver(),
    559                     android.provider.Settings.Secure.PREFERRED_TTY_MODE,
    560                     Phone.TTY_MODE_OFF);
    561             mHandler.sendMessage(mHandler.obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0));
    562         }
    563         // Read HAC settings and configure audio hardware
    564         if (getResources().getBoolean(R.bool.hac_enabled)) {
    565             int hac = android.provider.Settings.System.getInt(phone.getContext().getContentResolver(),
    566                                                               android.provider.Settings.System.HEARING_AID,
    567                                                               0);
    568             AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    569             audioManager.setParameter(CallFeaturesSetting.HAC_KEY, hac != 0 ?
    570                                       CallFeaturesSetting.HAC_VAL_ON :
    571                                       CallFeaturesSetting.HAC_VAL_OFF);
    572         }
    573    }
    574 
    575     @Override
    576     public void onConfigurationChanged(Configuration newConfig) {
    577         if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
    578             mIsHardKeyboardOpen = true;
    579         } else {
    580             mIsHardKeyboardOpen = false;
    581         }
    582 
    583         // Update the Proximity sensor based on keyboard state
    584         updateProximitySensorMode(mCM.getState());
    585         super.onConfigurationChanged(newConfig);
    586     }
    587 
    588     /**
    589      * Returns the singleton instance of the PhoneApp.
    590      */
    591     static PhoneApp getInstance() {
    592         return sMe;
    593     }
    594 
    595     /**
    596      * Returns the Phone associated with this instance
    597      */
    598     static Phone getPhone() {
    599         return getInstance().phone;
    600     }
    601 
    602     Ringer getRinger() {
    603         return ringer;
    604     }
    605 
    606     BluetoothHandsfree getBluetoothHandsfree() {
    607         return mBtHandsfree;
    608     }
    609 
    610     static Intent createCallLogIntent() {
    611         Intent  intent = new Intent(Intent.ACTION_VIEW, null);
    612         intent.setType("vnd.android.cursor.dir/calls");
    613         return intent;
    614     }
    615 
    616     /**
    617      * Return an Intent that can be used to bring up the in-call screen.
    618      *
    619      * This intent can only be used from within the Phone app, since the
    620      * InCallScreen is not exported from our AndroidManifest.
    621      */
    622     /* package */ static Intent createInCallIntent() {
    623         Intent intent = new Intent(Intent.ACTION_MAIN, null);
    624         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
    625                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
    626                 | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
    627         intent.setClassName("com.android.phone", getCallScreenClassName());
    628         return intent;
    629     }
    630 
    631     /**
    632      * Variation of createInCallIntent() that also specifies whether the
    633      * DTMF dialpad should be initially visible when the InCallScreen
    634      * comes up.
    635      */
    636     /* package */ static Intent createInCallIntent(boolean showDialpad) {
    637         Intent intent = createInCallIntent();
    638         intent.putExtra(InCallScreen.SHOW_DIALPAD_EXTRA, showDialpad);
    639         return intent;
    640     }
    641 
    642     static String getCallScreenClassName() {
    643         return InCallScreen.class.getName();
    644     }
    645 
    646     /**
    647      * Starts the InCallScreen Activity.
    648      */
    649     private void displayCallScreen() {
    650         if (VDBG) Log.d(LOG_TAG, "displayCallScreen()...");
    651         startActivity(createInCallIntent());
    652         Profiler.callScreenRequested();
    653     }
    654 
    655     boolean isSimPinEnabled() {
    656         return mIsSimPinEnabled;
    657     }
    658 
    659     boolean authenticateAgainstCachedSimPin(String pin) {
    660         return (mCachedSimPin != null && mCachedSimPin.equals(pin));
    661     }
    662 
    663     void setCachedSimPin(String pin) {
    664         mCachedSimPin = pin;
    665     }
    666 
    667     void setInCallScreenInstance(InCallScreen inCallScreen) {
    668         mInCallScreen = inCallScreen;
    669     }
    670 
    671     /**
    672      * @return true if the in-call UI is running as the foreground
    673      * activity.  (In other words, from the perspective of the
    674      * InCallScreen activity, return true between onResume() and
    675      * onPause().)
    676      *
    677      * Note this method will return false if the screen is currently off,
    678      * even if the InCallScreen *was* in the foreground just before the
    679      * screen turned off.  (This is because the foreground activity is
    680      * always "paused" while the screen is off.)
    681      */
    682     boolean isShowingCallScreen() {
    683         if (mInCallScreen == null) return false;
    684         return mInCallScreen.isForegroundActivity();
    685     }
    686 
    687     /**
    688      * Dismisses the in-call UI.
    689      *
    690      * This also ensures that you won't be able to get back to the in-call
    691      * UI via the BACK button (since this call removes the InCallScreen
    692      * from the activity history.)
    693      * For OTA Call, it call InCallScreen api to handle OTA Call End scenario
    694      * to display OTA Call End screen.
    695      */
    696     void dismissCallScreen() {
    697         if (mInCallScreen != null) {
    698             if ((phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) &&
    699                     (mInCallScreen.isOtaCallInActiveState()
    700                     || mInCallScreen.isOtaCallInEndState()
    701                     || ((cdmaOtaScreenState != null)
    702                     && (cdmaOtaScreenState.otaScreenState
    703                             != CdmaOtaScreenState.OtaScreenState.OTA_STATUS_UNDEFINED)))) {
    704                 // TODO: During OTA Call, display should not become dark to
    705                 // allow user to see OTA UI update. Phone app needs to hold
    706                 // a SCREEN_DIM_WAKE_LOCK wake lock during the entire OTA call.
    707                 wakeUpScreen();
    708                 // If InCallScreen is not in foreground we resume it to show the OTA call end screen
    709                 // Fire off the InCallScreen intent
    710                 displayCallScreen();
    711 
    712                 mInCallScreen.handleOtaCallEnd();
    713                 return;
    714             } else {
    715                 mInCallScreen.finish();
    716             }
    717         }
    718     }
    719 
    720     /**
    721      * Handle OTA events
    722      *
    723      * When OTA call is active and display becomes dark, then CallNotifier will
    724      * handle OTA Events by calling this api which then calls OtaUtil function.
    725      */
    726     void handleOtaEvents(Message msg) {
    727 
    728         if (DBG) Log.d(LOG_TAG, "Enter handleOtaEvents");
    729         if ((mInCallScreen != null) && (!isShowingCallScreen())) {
    730             if (mInCallScreen.otaUtils != null) {
    731                 mInCallScreen.otaUtils.onOtaProvisionStatusChanged((AsyncResult) msg.obj);
    732             }
    733         }
    734     }
    735 
    736 
    737     /**
    738      * Sets the activity responsible for un-PUK-blocking the device
    739      * so that we may close it when we receive a positive result.
    740      * mPUKEntryActivity is also used to indicate to the device that
    741      * we are trying to un-PUK-lock the phone. In other words, iff
    742      * it is NOT null, then we are trying to unlock and waiting for
    743      * the SIM to move to READY state.
    744      *
    745      * @param activity is the activity to close when PUK has
    746      * finished unlocking. Can be set to null to indicate the unlock
    747      * or SIM READYing process is over.
    748      */
    749     void setPukEntryActivity(Activity activity) {
    750         mPUKEntryActivity = activity;
    751     }
    752 
    753     Activity getPUKEntryActivity() {
    754         return mPUKEntryActivity;
    755     }
    756 
    757     /**
    758      * Sets the dialog responsible for notifying the user of un-PUK-
    759      * blocking - SIM READYing progress, so that we may dismiss it
    760      * when we receive a positive result.
    761      *
    762      * @param dialog indicates the progress dialog informing the user
    763      * of the state of the device.  Dismissed upon completion of
    764      * READYing process
    765      */
    766     void setPukEntryProgressDialog(ProgressDialog dialog) {
    767         mPUKEntryProgressDialog = dialog;
    768     }
    769 
    770     ProgressDialog getPUKEntryProgressDialog() {
    771         return mPUKEntryProgressDialog;
    772     }
    773 
    774     /**
    775      * Disables the status bar.  This is used by the phone app when in-call UI is active.
    776      *
    777      * Any call to this method MUST be followed (eventually)
    778      * by a corresponding reenableStatusBar() call.
    779      */
    780     /* package */ void disableStatusBar() {
    781         if (DBG) Log.d(LOG_TAG, "disable status bar");
    782         synchronized (this) {
    783             if (mStatusBarDisableCount++ == 0) {
    784                if (DBG)  Log.d(LOG_TAG, "StatusBarManager.DISABLE_EXPAND");
    785                 mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
    786             }
    787         }
    788     }
    789 
    790     /**
    791      * Re-enables the status bar after a previous disableStatusBar() call.
    792      *
    793      * Any call to this method MUST correspond to (i.e. be balanced with)
    794      * a previous disableStatusBar() call.
    795      */
    796     /* package */ void reenableStatusBar() {
    797         if (DBG) Log.d(LOG_TAG, "re-enable status bar");
    798         synchronized (this) {
    799             if (mStatusBarDisableCount > 0) {
    800                 if (--mStatusBarDisableCount == 0) {
    801                     if (DBG) Log.d(LOG_TAG, "StatusBarManager.DISABLE_NONE");
    802                     mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);
    803                 }
    804             } else {
    805                 Log.e(LOG_TAG, "mStatusBarDisableCount is already zero");
    806             }
    807         }
    808     }
    809 
    810     /**
    811      * Controls how quickly the screen times out.
    812      *
    813      * The poke lock controls how long it takes before the screen powers
    814      * down, and therefore has no immediate effect when the current
    815      * WakeState (see {@link PhoneApp#requestWakeState}) is FULL.
    816      * If we're in a state where the screen *is* allowed to turn off,
    817      * though, the poke lock will determine the timeout interval (long or
    818      * short).
    819      *
    820      * @param shortPokeLock tells the device the timeout duration to use
    821      * before going to sleep
    822      * {@link com.android.server.PowerManagerService#SHORT_KEYLIGHT_DELAY}.
    823      */
    824     /* package */ void setScreenTimeout(ScreenTimeoutDuration duration) {
    825         if (VDBG) Log.d(LOG_TAG, "setScreenTimeout(" + duration + ")...");
    826 
    827         // make sure we don't set the poke lock repeatedly so that we
    828         // avoid triggering the userActivity calls in
    829         // PowerManagerService.setPokeLock().
    830         if (duration == mScreenTimeoutDuration) {
    831             return;
    832         }
    833         // stick with default timeout if we are using the proximity sensor
    834         if (proximitySensorModeEnabled()) {
    835             return;
    836         }
    837         mScreenTimeoutDuration = duration;
    838         updatePokeLock();
    839     }
    840 
    841     /**
    842      * Update the state of the poke lock held by the phone app,
    843      * based on the current desired screen timeout and the
    844      * current "ignore user activity on touch" flag.
    845      */
    846     private void updatePokeLock() {
    847         // This is kind of convoluted, but the basic thing to remember is
    848         // that the poke lock just sends a message to the screen to tell
    849         // it to stay on for a while.
    850         // The default is 0, for a long timeout and should be set that way
    851         // when we are heading back into a the keyguard / screen off
    852         // state, and also when we're trying to keep the screen alive
    853         // while ringing.  We'll also want to ignore the cheek events
    854         // regardless of the timeout duration.
    855         // The short timeout is really used whenever we want to give up
    856         // the screen lock, such as when we're in call.
    857         int pokeLockSetting = LocalPowerManager.POKE_LOCK_IGNORE_CHEEK_EVENTS;
    858         switch (mScreenTimeoutDuration) {
    859             case SHORT:
    860                 // Set the poke lock to timeout the display after a short
    861                 // timeout (5s). This ensures that the screen goes to sleep
    862                 // as soon as acceptably possible after we the wake lock
    863                 // has been released.
    864                 pokeLockSetting |= LocalPowerManager.POKE_LOCK_SHORT_TIMEOUT;
    865                 break;
    866 
    867             case MEDIUM:
    868                 // Set the poke lock to timeout the display after a medium
    869                 // timeout (15s). This ensures that the screen goes to sleep
    870                 // as soon as acceptably possible after we the wake lock
    871                 // has been released.
    872                 pokeLockSetting |= LocalPowerManager.POKE_LOCK_MEDIUM_TIMEOUT;
    873                 break;
    874 
    875             case DEFAULT:
    876             default:
    877                 // set the poke lock to timeout the display after a long
    878                 // delay by default.
    879                 // TODO: it may be nice to be able to disable cheek presses
    880                 // for long poke locks (emergency dialer, for instance).
    881                 break;
    882         }
    883 
    884         if (mIgnoreTouchUserActivity) {
    885             pokeLockSetting |= LocalPowerManager.POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS;
    886         }
    887 
    888         // Send the request
    889         try {
    890             mPowerManagerService.setPokeLock(pokeLockSetting, mPokeLockToken, LOG_TAG);
    891         } catch (RemoteException e) {
    892             Log.w(LOG_TAG, "mPowerManagerService.setPokeLock() failed: " + e);
    893         }
    894     }
    895 
    896     /**
    897      * Controls whether or not the screen is allowed to sleep.
    898      *
    899      * Once sleep is allowed (WakeState is SLEEP), it will rely on the
    900      * settings for the poke lock to determine when to timeout and let
    901      * the device sleep {@link PhoneApp#setScreenTimeout}.
    902      *
    903      * @param ws tells the device to how to wake.
    904      */
    905     /* package */ void requestWakeState(WakeState ws) {
    906         if (VDBG) Log.d(LOG_TAG, "requestWakeState(" + ws + ")...");
    907         synchronized (this) {
    908             if (mWakeState != ws) {
    909                 switch (ws) {
    910                     case PARTIAL:
    911                         // acquire the processor wake lock, and release the FULL
    912                         // lock if it is being held.
    913                         mPartialWakeLock.acquire();
    914                         if (mWakeLock.isHeld()) {
    915                             mWakeLock.release();
    916                         }
    917                         break;
    918                     case FULL:
    919                         // acquire the full wake lock, and release the PARTIAL
    920                         // lock if it is being held.
    921                         mWakeLock.acquire();
    922                         if (mPartialWakeLock.isHeld()) {
    923                             mPartialWakeLock.release();
    924                         }
    925                         break;
    926                     case SLEEP:
    927                     default:
    928                         // release both the PARTIAL and FULL locks.
    929                         if (mWakeLock.isHeld()) {
    930                             mWakeLock.release();
    931                         }
    932                         if (mPartialWakeLock.isHeld()) {
    933                             mPartialWakeLock.release();
    934                         }
    935                         break;
    936                 }
    937                 mWakeState = ws;
    938             }
    939         }
    940     }
    941 
    942     /**
    943      * If we are not currently keeping the screen on, then poke the power
    944      * manager to wake up the screen for the user activity timeout duration.
    945      */
    946     /* package */ void wakeUpScreen() {
    947         synchronized (this) {
    948             if (mWakeState == WakeState.SLEEP) {
    949                 if (DBG) Log.d(LOG_TAG, "pulse screen lock");
    950                 try {
    951                     mPowerManagerService.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
    952                 } catch (RemoteException ex) {
    953                     // Ignore -- the system process is dead.
    954                 }
    955             }
    956         }
    957     }
    958 
    959     /**
    960      * Sets the wake state and screen timeout based on the current state
    961      * of the phone, and the current state of the in-call UI.
    962      *
    963      * This method is a "UI Policy" wrapper around
    964      * {@link PhoneApp#requestWakeState} and {@link PhoneApp#setScreenTimeout}.
    965      *
    966      * It's safe to call this method regardless of the state of the Phone
    967      * (e.g. whether or not it's idle), and regardless of the state of the
    968      * Phone UI (e.g. whether or not the InCallScreen is active.)
    969      */
    970     /* package */ void updateWakeState() {
    971         Phone.State state = mCM.getState();
    972 
    973         // True if the in-call UI is the foreground activity.
    974         // (Note this will be false if the screen is currently off,
    975         // since in that case *no* activity is in the foreground.)
    976         boolean isShowingCallScreen = isShowingCallScreen();
    977 
    978         // True if the InCallScreen's DTMF dialer is currently opened.
    979         // (Note this does NOT imply whether or not the InCallScreen
    980         // itself is visible.)
    981         boolean isDialerOpened = (mInCallScreen != null) && mInCallScreen.isDialerOpened();
    982 
    983         // True if the speakerphone is in use.  (If so, we *always* use
    984         // the default timeout.  Since the user is obviously not holding
    985         // the phone up to his/her face, we don't need to worry about
    986         // false touches, and thus don't need to turn the screen off so
    987         // aggressively.)
    988         // Note that we need to make a fresh call to this method any
    989         // time the speaker state changes.  (That happens in
    990         // PhoneUtils.turnOnSpeaker().)
    991         boolean isSpeakerInUse = (state == Phone.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this);
    992 
    993         // TODO (bug 1440854): The screen timeout *might* also need to
    994         // depend on the bluetooth state, but this isn't as clear-cut as
    995         // the speaker state (since while using BT it's common for the
    996         // user to put the phone straight into a pocket, in which case the
    997         // timeout should probably still be short.)
    998 
    999         if (DBG) Log.d(LOG_TAG, "updateWakeState: callscreen " + isShowingCallScreen
   1000                        + ", dialer " + isDialerOpened
   1001                        + ", speaker " + isSpeakerInUse + "...");
   1002 
   1003         //
   1004         // (1) Set the screen timeout.
   1005         //
   1006         // Note that the "screen timeout" value we determine here is
   1007         // meaningless if the screen is forced on (see (2) below.)
   1008         //
   1009         if (!isShowingCallScreen || isSpeakerInUse) {
   1010             // Use the system-wide default timeout.
   1011             setScreenTimeout(ScreenTimeoutDuration.DEFAULT);
   1012         } else {
   1013             // We're on the in-call screen, and *not* using the speakerphone.
   1014             if (isDialerOpened) {
   1015                 // The DTMF dialpad is up.  This case is special because
   1016                 // the in-call UI has its own "touch lock" mechanism to
   1017                 // disable the dialpad after a very short amount of idle
   1018                 // time (to avoid false touches from the user's face while
   1019                 // in-call.)
   1020                 //
   1021                 // In this case the *physical* screen just uses the
   1022                 // system-wide default timeout.
   1023                 setScreenTimeout(ScreenTimeoutDuration.DEFAULT);
   1024             } else {
   1025                 // We're on the in-call screen, and not using the DTMF dialpad.
   1026                 // There's actually no touchable UI onscreen at all in
   1027                 // this state.  Also, the user is (most likely) not
   1028                 // looking at the screen at all, since they're probably
   1029                 // holding the phone up to their face.  Here we use a
   1030                 // special screen timeout value specific to the in-call
   1031                 // screen, purely to save battery life.
   1032                 setScreenTimeout(ScreenTimeoutDuration.MEDIUM);
   1033             }
   1034         }
   1035 
   1036         //
   1037         // (2) Decide whether to force the screen on or not.
   1038         //
   1039         // Force the screen to be on if the phone is ringing or dialing,
   1040         // or if we're displaying the "Call ended" UI for a connection in
   1041         // the "disconnected" state.
   1042         //
   1043         boolean isRinging = (state == Phone.State.RINGING);
   1044         boolean isDialing = (phone.getForegroundCall().getState() == Call.State.DIALING);
   1045         boolean showingDisconnectedConnection =
   1046                 PhoneUtils.hasDisconnectedConnections(phone) && isShowingCallScreen;
   1047         boolean keepScreenOn = isRinging || isDialing || showingDisconnectedConnection;
   1048         if (DBG) Log.d(LOG_TAG, "updateWakeState: keepScreenOn = " + keepScreenOn
   1049                        + " (isRinging " + isRinging
   1050                        + ", isDialing " + isDialing
   1051                        + ", showingDisc " + showingDisconnectedConnection + ")");
   1052         // keepScreenOn == true means we'll hold a full wake lock:
   1053         requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP);
   1054     }
   1055 
   1056     /**
   1057      * Wrapper around the PowerManagerService.preventScreenOn() API.
   1058      * This allows the in-call UI to prevent the screen from turning on
   1059      * even if a subsequent call to updateWakeState() causes us to acquire
   1060      * a full wake lock.
   1061      */
   1062     /* package */ void preventScreenOn(boolean prevent) {
   1063         if (VDBG) Log.d(LOG_TAG, "- preventScreenOn(" + prevent + ")...");
   1064         try {
   1065             mPowerManagerService.preventScreenOn(prevent);
   1066         } catch (RemoteException e) {
   1067             Log.w(LOG_TAG, "mPowerManagerService.preventScreenOn() failed: " + e);
   1068         }
   1069     }
   1070 
   1071     /**
   1072      * Sets or clears the flag that tells the PowerManager that touch
   1073      * (and cheek) events should NOT be considered "user activity".
   1074      *
   1075      * Since the in-call UI is totally insensitive to touch in most
   1076      * states, we set this flag whenever the InCallScreen is in the
   1077      * foreground.  (Otherwise, repeated unintentional touches could
   1078      * prevent the device from going to sleep.)
   1079      *
   1080      * There *are* some some touch events that really do count as user
   1081      * activity, though.  For those, we need to manually poke the
   1082      * PowerManager's userActivity method; see pokeUserActivity().
   1083      */
   1084     /* package */ void setIgnoreTouchUserActivity(boolean ignore) {
   1085         if (VDBG) Log.d(LOG_TAG, "setIgnoreTouchUserActivity(" + ignore + ")...");
   1086         mIgnoreTouchUserActivity = ignore;
   1087         updatePokeLock();
   1088     }
   1089 
   1090     /**
   1091      * Manually pokes the PowerManager's userActivity method.  Since we
   1092      * hold the POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS poke lock while
   1093      * the InCallScreen is active, we need to do this for touch events
   1094      * that really do count as user activity (like DTMF key presses, or
   1095      * unlocking the "touch lock" overlay.)
   1096      */
   1097     /* package */ void pokeUserActivity() {
   1098         if (VDBG) Log.d(LOG_TAG, "pokeUserActivity()...");
   1099         try {
   1100             mPowerManagerService.userActivity(SystemClock.uptimeMillis(), false);
   1101         } catch (RemoteException e) {
   1102             Log.w(LOG_TAG, "mPowerManagerService.userActivity() failed: " + e);
   1103         }
   1104     }
   1105 
   1106     /**
   1107      * Set when a new outgoing call is beginning, so we can update
   1108      * the proximity sensor state.
   1109      * Cleared when the InCallScreen is no longer in the foreground,
   1110      * in case the call fails without changing the telephony state.
   1111      */
   1112     /* package */ void setBeginningCall(boolean beginning) {
   1113         // Note that we are beginning a new call, for proximity sensor support
   1114         mBeginningCall = beginning;
   1115         // Update the Proximity sensor based on mBeginningCall state
   1116         updateProximitySensorMode(mCM.getState());
   1117     }
   1118 
   1119     /**
   1120      * Updates the wake lock used to control proximity sensor behavior,
   1121      * based on the current state of the phone.  This method is called
   1122      * from the CallNotifier on any phone state change.
   1123      *
   1124      * On devices that have a proximity sensor, to avoid false touches
   1125      * during a call, we hold a PROXIMITY_SCREEN_OFF_WAKE_LOCK wake lock
   1126      * whenever the phone is off hook.  (When held, that wake lock causes
   1127      * the screen to turn off automatically when the sensor detects an
   1128      * object close to the screen.)
   1129      *
   1130      * This method is a no-op for devices that don't have a proximity
   1131      * sensor.
   1132      *
   1133      * Note this method doesn't care if the InCallScreen is the foreground
   1134      * activity or not.  That's because we want the proximity sensor to be
   1135      * enabled any time the phone is in use, to avoid false cheek events
   1136      * for whatever app you happen to be running.
   1137      *
   1138      * Proximity wake lock will *not* be held if any one of the
   1139      * conditions is true while on a call:
   1140      * 1) If the audio is routed via Bluetooth
   1141      * 2) If a wired headset is connected
   1142      * 3) if the speaker is ON
   1143      * 4) If the slider is open(i.e. the hardkeyboard is *not* hidden)
   1144      *
   1145      * @param state current state of the phone (see {@link Phone#State})
   1146      */
   1147     /* package */ void updateProximitySensorMode(Phone.State state) {
   1148         if (VDBG) Log.d(LOG_TAG, "updateProximitySensorMode: state = " + state);
   1149 
   1150         if (proximitySensorModeEnabled()) {
   1151             synchronized (mProximityWakeLock) {
   1152                 // turn proximity sensor off and turn screen on immediately if
   1153                 // we are using a headset, the keyboard is open, or the device
   1154                 // is being held in a horizontal position.
   1155                 boolean screenOnImmediately = (isHeadsetPlugged()
   1156                             || PhoneUtils.isSpeakerOn(this)
   1157                             || ((mBtHandsfree != null) && mBtHandsfree.isAudioOn())
   1158                             || mIsHardKeyboardOpen);
   1159                 // We do not keep the screen off when we are horizontal, but we do not force it
   1160                 // on when we become horizontal until the proximity sensor goes negative.
   1161                 boolean horizontal = (mOrientation == AccelerometerListener.ORIENTATION_HORIZONTAL);
   1162 
   1163                 if (((state == Phone.State.OFFHOOK) || mBeginningCall) &&
   1164                         !screenOnImmediately && !horizontal) {
   1165                     // Phone is in use!  Arrange for the screen to turn off
   1166                     // automatically when the sensor detects a close object.
   1167                     if (!mProximityWakeLock.isHeld()) {
   1168                         if (DBG) Log.d(LOG_TAG, "updateProximitySensorMode: acquiring...");
   1169                         mProximityWakeLock.acquire();
   1170                     } else {
   1171                         if (VDBG) Log.d(LOG_TAG, "updateProximitySensorMode: lock already held.");
   1172                     }
   1173                 } else {
   1174                     // Phone is either idle, or ringing.  We don't want any
   1175                     // special proximity sensor behavior in either case.
   1176                     if (mProximityWakeLock.isHeld()) {
   1177                         if (DBG) Log.d(LOG_TAG, "updateProximitySensorMode: releasing...");
   1178                         // Wait until user has moved the phone away from his head if we are
   1179                         // releasing due to the phone call ending.
   1180                         // Qtherwise, turn screen on immediately
   1181                         int flags =
   1182                             (screenOnImmediately ? 0 : PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
   1183                         mProximityWakeLock.release(flags);
   1184                     } else {
   1185                         if (VDBG) {
   1186                             Log.d(LOG_TAG, "updateProximitySensorMode: lock already released.");
   1187                         }
   1188                     }
   1189                 }
   1190             }
   1191         }
   1192     }
   1193 
   1194     public void orientationChanged(int orientation) {
   1195         mOrientation = orientation;
   1196         updateProximitySensorMode(mCM.getState());
   1197     }
   1198 
   1199     /**
   1200      * Notifies the phone app when the phone state changes.
   1201      * Currently used only for proximity sensor support.
   1202      */
   1203     /* package */ void updatePhoneState(Phone.State state) {
   1204         if (state != mLastPhoneState) {
   1205             mLastPhoneState = state;
   1206             updateProximitySensorMode(state);
   1207             if (mAccelerometerListener != null) {
   1208                 // use accelerometer to augment proximity sensor when in call
   1209                 mOrientation = AccelerometerListener.ORIENTATION_UNKNOWN;
   1210                 mAccelerometerListener.enable(state == Phone.State.OFFHOOK);
   1211             }
   1212             // clear our beginning call flag
   1213             mBeginningCall = false;
   1214             // While we are in call, the in-call screen should dismiss the keyguard.
   1215             // This allows the user to press Home to go directly home without going through
   1216             // an insecure lock screen.
   1217             // But we do not want to do this if there is no active call so we do not
   1218             // bypass the keyguard if the call is not answered or declined.
   1219             if (mInCallScreen != null) {
   1220                 mInCallScreen.updateKeyguardPolicy(state == Phone.State.OFFHOOK);
   1221             }
   1222         }
   1223     }
   1224 
   1225     /* package */ Phone.State getPhoneState() {
   1226         return mLastPhoneState;
   1227     }
   1228 
   1229     /**
   1230      * @return true if this device supports the "proximity sensor
   1231      * auto-lock" feature while in-call (see updateProximitySensorMode()).
   1232      */
   1233     /* package */ boolean proximitySensorModeEnabled() {
   1234         return (mProximityWakeLock != null);
   1235     }
   1236 
   1237     KeyguardManager getKeyguardManager() {
   1238         return mKeyguardManager;
   1239     }
   1240 
   1241     private void onMMIComplete(AsyncResult r) {
   1242         if (VDBG) Log.d(LOG_TAG, "onMMIComplete()...");
   1243         MmiCode mmiCode = (MmiCode) r.result;
   1244         PhoneUtils.displayMMIComplete(phone, getInstance(), mmiCode, null, null);
   1245     }
   1246 
   1247     private void initForNewRadioTechnology() {
   1248         if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
   1249 
   1250         if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
   1251             // Create an instance of CdmaPhoneCallState and initialize it to IDLE
   1252             cdmaPhoneCallState = new CdmaPhoneCallState();
   1253             cdmaPhoneCallState.CdmaPhoneCallStateInit();
   1254 
   1255             //create instances of CDMA OTA data classes
   1256             if (cdmaOtaProvisionData == null) {
   1257                 cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
   1258             }
   1259             if (cdmaOtaConfigData == null) {
   1260                 cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();
   1261             }
   1262             if (cdmaOtaScreenState == null) {
   1263                 cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();
   1264             }
   1265             if (cdmaOtaInCallScreenUiState == null) {
   1266                 cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();
   1267             }
   1268         } else {
   1269             //Clean up OTA data in GSM/UMTS. It is valid only for CDMA
   1270             clearOtaState();
   1271         }
   1272 
   1273         ringer.updateRingerContextAfterRadioTechnologyChange(this.phone);
   1274         notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange();
   1275         if (mBtHandsfree != null) {
   1276             mBtHandsfree.updateBtHandsfreeAfterRadioTechnologyChange();
   1277         }
   1278         if (mInCallScreen != null) {
   1279             mInCallScreen.updateAfterRadioTechnologyChange();
   1280         }
   1281 
   1282         // Update registration for ICC status after radio technology change
   1283         IccCard sim = phone.getIccCard();
   1284         if (sim != null) {
   1285             if (DBG) Log.d(LOG_TAG, "Update registration for ICC status...");
   1286 
   1287             //Register all events new to the new active phone
   1288             sim.registerForNetworkLocked(mHandler, EVENT_SIM_NETWORK_LOCKED, null);
   1289         }
   1290     }
   1291 
   1292 
   1293     /**
   1294      * @return true if a wired headset is currently plugged in.
   1295      *
   1296      * @see Intent.ACTION_HEADSET_PLUG (which we listen for in mReceiver.onReceive())
   1297      */
   1298     boolean isHeadsetPlugged() {
   1299         return mIsHeadsetPlugged;
   1300     }
   1301 
   1302     /**
   1303      * @return true if the onscreen UI should currently be showing the
   1304      * special "bluetooth is active" indication in a couple of places (in
   1305      * which UI elements turn blue and/or show the bluetooth logo.)
   1306      *
   1307      * This depends on the BluetoothHeadset state *and* the current
   1308      * telephony state; see shouldShowBluetoothIndication().
   1309      *
   1310      * @see CallCard
   1311      * @see NotificationMgr.updateInCallNotification
   1312      */
   1313     /* package */ boolean showBluetoothIndication() {
   1314         return mShowBluetoothIndication;
   1315     }
   1316 
   1317     /**
   1318      * Recomputes the mShowBluetoothIndication flag based on the current
   1319      * bluetooth state and current telephony state.
   1320      *
   1321      * This needs to be called any time the bluetooth headset state or the
   1322      * telephony state changes.
   1323      *
   1324      * @param forceUiUpdate if true, force the UI elements that care
   1325      *                      about this flag to update themselves.
   1326      */
   1327     /* package */ void updateBluetoothIndication(boolean forceUiUpdate) {
   1328         mShowBluetoothIndication = shouldShowBluetoothIndication(mBluetoothHeadsetState,
   1329                                                                  mBluetoothHeadsetAudioState,
   1330                                                                  mCM);
   1331         if (forceUiUpdate) {
   1332             // Post Handler messages to the various components that might
   1333             // need to be refreshed based on the new state.
   1334             if (isShowingCallScreen()) mInCallScreen.requestUpdateBluetoothIndication();
   1335             if (DBG) Log.d (LOG_TAG, "- updating in-call notification for BT state change...");
   1336             mHandler.sendEmptyMessage(EVENT_UPDATE_INCALL_NOTIFICATION);
   1337         }
   1338 
   1339         // Update the Proximity sensor based on Bluetooth audio state
   1340         updateProximitySensorMode(mCM.getState());
   1341     }
   1342 
   1343     /**
   1344      * UI policy helper function for the couple of places in the UI that
   1345      * have some way of indicating that "bluetooth is in use."
   1346      *
   1347      * @return true if the onscreen UI should indicate that "bluetooth is in use",
   1348      *         based on the specified bluetooth headset state, and the
   1349      *         current state of the phone.
   1350      * @see showBluetoothIndication()
   1351      */
   1352     private static boolean shouldShowBluetoothIndication(int bluetoothState,
   1353                                                          int bluetoothAudioState,
   1354                                                          CallManager cm) {
   1355         // We want the UI to indicate that "bluetooth is in use" in two
   1356         // slightly different cases:
   1357         //
   1358         // (a) The obvious case: if a bluetooth headset is currently in
   1359         //     use for an ongoing call.
   1360         //
   1361         // (b) The not-so-obvious case: if an incoming call is ringing,
   1362         //     and we expect that audio *will* be routed to a bluetooth
   1363         //     headset once the call is answered.
   1364 
   1365         switch (cm.getState()) {
   1366             case OFFHOOK:
   1367                 // This covers normal active calls, and also the case if
   1368                 // the foreground call is DIALING or ALERTING.  In this
   1369                 // case, bluetooth is considered "active" if a headset
   1370                 // is connected *and* audio is being routed to it.
   1371                 return ((bluetoothState == BluetoothHeadset.STATE_CONNECTED)
   1372                         && (bluetoothAudioState == BluetoothHeadset.AUDIO_STATE_CONNECTED));
   1373 
   1374             case RINGING:
   1375                 // If an incoming call is ringing, we're *not* yet routing
   1376                 // audio to the headset (since there's no in-call audio
   1377                 // yet!)  In this case, if a bluetooth headset is
   1378                 // connected at all, we assume that it'll become active
   1379                 // once the user answers the phone.
   1380                 return (bluetoothState == BluetoothHeadset.STATE_CONNECTED);
   1381 
   1382             default:  // Presumably IDLE
   1383                 return false;
   1384         }
   1385     }
   1386 
   1387 
   1388     /**
   1389      * Receiver for misc intent broadcasts the Phone app cares about.
   1390      */
   1391     private class PhoneAppBroadcastReceiver extends BroadcastReceiver {
   1392         @Override
   1393         public void onReceive(Context context, Intent intent) {
   1394             String action = intent.getAction();
   1395             if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
   1396                 boolean enabled = System.getInt(getContentResolver(),
   1397                         System.AIRPLANE_MODE_ON, 0) == 0;
   1398                 phone.setRadioPower(enabled);
   1399             } else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
   1400                 mBluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
   1401                                                             BluetoothHeadset.STATE_ERROR);
   1402                 if (VDBG) Log.d(LOG_TAG, "mReceiver: HEADSET_STATE_CHANGED_ACTION");
   1403                 if (VDBG) Log.d(LOG_TAG, "==> new state: " + mBluetoothHeadsetState);
   1404                 updateBluetoothIndication(true);  // Also update any visible UI if necessary
   1405             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
   1406                 mBluetoothHeadsetAudioState =
   1407                         intent.getIntExtra(BluetoothHeadset.EXTRA_AUDIO_STATE,
   1408                                            BluetoothHeadset.STATE_ERROR);
   1409                 if (VDBG) Log.d(LOG_TAG, "mReceiver: HEADSET_AUDIO_STATE_CHANGED_ACTION");
   1410                 if (VDBG) Log.d(LOG_TAG, "==> new state: " + mBluetoothHeadsetAudioState);
   1411                 updateBluetoothIndication(true);  // Also update any visible UI if necessary
   1412             } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
   1413                 if (VDBG) Log.d(LOG_TAG, "mReceiver: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED");
   1414                 if (VDBG) Log.d(LOG_TAG, "- state: " + intent.getStringExtra(Phone.STATE_KEY));
   1415                 if (VDBG) Log.d(LOG_TAG, "- reason: "
   1416                                 + intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY));
   1417 
   1418                 // The "data disconnected due to roaming" notification is
   1419                 // visible if you've lost data connectivity because you're
   1420                 // roaming and you have the "data roaming" feature turned off.
   1421                 boolean disconnectedDueToRoaming = false;
   1422                 if ("DISCONNECTED".equals(intent.getStringExtra(Phone.STATE_KEY))) {
   1423                     String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
   1424                     if (Phone.REASON_ROAMING_ON.equals(reason)) {
   1425                         // We just lost our data connection, and the reason
   1426                         // is that we started roaming.  This implies that
   1427                         // the user has data roaming turned off.
   1428                         disconnectedDueToRoaming = true;
   1429                     }
   1430                 }
   1431                 mHandler.sendEmptyMessage(disconnectedDueToRoaming
   1432                                           ? EVENT_DATA_ROAMING_DISCONNECTED
   1433                                           : EVENT_DATA_ROAMING_OK);
   1434             } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
   1435                 if (VDBG) Log.d(LOG_TAG, "mReceiver: ACTION_HEADSET_PLUG");
   1436                 if (VDBG) Log.d(LOG_TAG, "    state: " + intent.getIntExtra("state", 0));
   1437                 if (VDBG) Log.d(LOG_TAG, "    name: " + intent.getStringExtra("name"));
   1438                 mIsHeadsetPlugged = (intent.getIntExtra("state", 0) == 1);
   1439                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_WIRED_HEADSET_PLUG, 0));
   1440             } else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
   1441                 if (VDBG) Log.d(LOG_TAG, "mReceiver: ACTION_BATTERY_LOW");
   1442                 notifier.sendBatteryLow();  // Play a warning tone if in-call
   1443             } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) &&
   1444                     (mPUKEntryActivity != null)) {
   1445                 // if an attempt to un-PUK-lock the device was made, while we're
   1446                 // receiving this state change notification, notify the handler.
   1447                 // NOTE: This is ONLY triggered if an attempt to un-PUK-lock has
   1448                 // been attempted.
   1449                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED,
   1450                         intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE)));
   1451             } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) {
   1452                 String newPhone = intent.getStringExtra(Phone.PHONE_NAME_KEY);
   1453                 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " is active.");
   1454                 initForNewRadioTechnology();
   1455             } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
   1456                 handleServiceStateChanged(intent);
   1457             } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
   1458                 if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
   1459                     Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp.");
   1460                     // Start Emergency Callback Mode service
   1461                     if (intent.getBooleanExtra("phoneinECMState", false)) {
   1462                         context.startService(new Intent(context,
   1463                                 EmergencyCallbackModeService.class));
   1464                     }
   1465                 } else {
   1466                     Log.e(LOG_TAG, "Error! Emergency Callback Mode not supported for " +
   1467                             phone.getPhoneName() + " phones");
   1468                 }
   1469             } else if (action.equals(Intent.ACTION_DOCK_EVENT)) {
   1470                 mDockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
   1471                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
   1472                 if (VDBG) Log.d(LOG_TAG, "ACTION_DOCK_EVENT -> mDockState = " + mDockState);
   1473                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DOCK_STATE_CHANGED, 0));
   1474             } else if (action.equals(TtyIntent.TTY_PREFERRED_MODE_CHANGE_ACTION)) {
   1475                 mPreferredTtyMode = intent.getIntExtra(TtyIntent.TTY_PREFFERED_MODE,
   1476                                                        Phone.TTY_MODE_OFF);
   1477                 if (VDBG) Log.d(LOG_TAG, "mReceiver: TTY_PREFERRED_MODE_CHANGE_ACTION");
   1478                 if (VDBG) Log.d(LOG_TAG, "    mode: " + mPreferredTtyMode);
   1479                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0));
   1480             } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
   1481                 int ringerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE,
   1482                         AudioManager.RINGER_MODE_NORMAL);
   1483                 if(ringerMode == AudioManager.RINGER_MODE_SILENT) {
   1484                     notifier.silenceRinger();
   1485                 }
   1486             }
   1487         }
   1488     }
   1489 
   1490     /**
   1491      * Broadcast receiver for the ACTION_MEDIA_BUTTON broadcast intent.
   1492      *
   1493      * This functionality isn't lumped in with the other intents in
   1494      * PhoneAppBroadcastReceiver because we instantiate this as a totally
   1495      * separate BroadcastReceiver instance, since we need to manually
   1496      * adjust its IntentFilter's priority (to make sure we get these
   1497      * intents *before* the media player.)
   1498      */
   1499     private class MediaButtonBroadcastReceiver extends BroadcastReceiver {
   1500         @Override
   1501         public void onReceive(Context context, Intent intent) {
   1502             KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
   1503             if (VDBG) Log.d(LOG_TAG,
   1504                            "MediaButtonBroadcastReceiver.onReceive()...  event = " + event);
   1505             if ((event != null)
   1506                 && (event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) {
   1507                 if (VDBG) Log.d(LOG_TAG, "MediaButtonBroadcastReceiver: HEADSETHOOK");
   1508                 boolean consumed = PhoneUtils.handleHeadsetHook(phone, event);
   1509                 if (VDBG) Log.d(LOG_TAG, "==> handleHeadsetHook(): consumed = " + consumed);
   1510                 if (consumed) {
   1511                     // If a headset is attached and the press is consumed, also update
   1512                     // any UI items (such as an InCallScreen mute button) that may need to
   1513                     // be updated if their state changed.
   1514                     if (isShowingCallScreen()) {
   1515                         updateInCallScreenTouchUi();
   1516                     }
   1517                     abortBroadcast();
   1518                 }
   1519             } else {
   1520                 if (mCM.getState() != Phone.State.IDLE) {
   1521                     // If the phone is anything other than completely idle,
   1522                     // then we consume and ignore any media key events,
   1523                     // Otherwise it is too easy to accidentally start
   1524                     // playing music while a phone call is in progress.
   1525                     if (VDBG) Log.d(LOG_TAG, "MediaButtonBroadcastReceiver: consumed");
   1526                     abortBroadcast();
   1527                 }
   1528             }
   1529         }
   1530     }
   1531 
   1532     private void handleServiceStateChanged(Intent intent) {
   1533         /**
   1534          * This used to handle updating EriTextWidgetProvider this routine
   1535          * and and listening for ACTION_SERVICE_STATE_CHANGED intents could
   1536          * be removed. But leaving just in case it might be needed in the near
   1537          * future.
   1538          */
   1539 
   1540         // If service just returned, start sending out the queued messages
   1541         ServiceState ss = ServiceState.newFromBundle(intent.getExtras());
   1542 
   1543         boolean hasService = true;
   1544         boolean isCdma = false;
   1545         String eriText = "";
   1546 
   1547         if (ss != null) {
   1548             int state = ss.getState();
   1549             NotificationMgr.getDefault().updateNetworkSelection(state);
   1550             switch (state) {
   1551                 case ServiceState.STATE_OUT_OF_SERVICE:
   1552                 case ServiceState.STATE_POWER_OFF:
   1553                     hasService = false;
   1554                     break;
   1555             }
   1556         } else {
   1557             hasService = false;
   1558         }
   1559     }
   1560 
   1561     public boolean isOtaCallInActiveState() {
   1562         boolean otaCallActive = false;
   1563         if (mInCallScreen != null) {
   1564             otaCallActive = mInCallScreen.isOtaCallInActiveState();
   1565         }
   1566         if (VDBG) Log.d(LOG_TAG, "- isOtaCallInActiveState " + otaCallActive);
   1567         return otaCallActive;
   1568     }
   1569 
   1570     public boolean isOtaCallInEndState() {
   1571         boolean otaCallEnded = false;
   1572         if (mInCallScreen != null) {
   1573             otaCallEnded = mInCallScreen.isOtaCallInEndState();
   1574         }
   1575         if (VDBG) Log.d(LOG_TAG, "- isOtaCallInEndState " + otaCallEnded);
   1576         return otaCallEnded;
   1577     }
   1578 
   1579     // it is safe to call clearOtaState() even if the InCallScreen isn't active
   1580     public void clearOtaState() {
   1581         if (DBG) Log.d(LOG_TAG, "- clearOtaState ...");
   1582         if ((mInCallScreen != null)
   1583                 && (mInCallScreen.otaUtils != null)) {
   1584             mInCallScreen.otaUtils.cleanOtaScreen(true);
   1585             if (DBG) Log.d(LOG_TAG, "  - clearOtaState clears OTA screen");
   1586         }
   1587     }
   1588 
   1589     // it is safe to call dismissOtaDialogs() even if the InCallScreen isn't active
   1590     public void dismissOtaDialogs() {
   1591         if (DBG) Log.d(LOG_TAG, "- dismissOtaDialogs ...");
   1592         if ((mInCallScreen != null)
   1593                 && (mInCallScreen.otaUtils != null)) {
   1594             mInCallScreen.otaUtils.dismissAllOtaDialogs();
   1595             if (DBG) Log.d(LOG_TAG, "  - dismissOtaDialogs clears OTA dialogs");
   1596         }
   1597     }
   1598 
   1599     // it is safe to call clearInCallScreenMode() even if the InCallScreen isn't active
   1600     public void clearInCallScreenMode() {
   1601         if (DBG) Log.d(LOG_TAG, "- clearInCallScreenMode ...");
   1602         if (mInCallScreen != null) {
   1603             mInCallScreen.resetInCallScreenMode();
   1604         }
   1605     }
   1606 
   1607     // Update InCallScreen's touch UI. It is safe to call even if InCallScreen isn't active
   1608     public void updateInCallScreenTouchUi() {
   1609         if (DBG) Log.d(LOG_TAG, "- updateInCallScreenTouchUi ...");
   1610         if (mInCallScreen != null) {
   1611             mInCallScreen.requestUpdateTouchUi();
   1612         }
   1613     }
   1614 
   1615     private void handleQueryTTYModeResponse(Message msg) {
   1616         AsyncResult ar = (AsyncResult) msg.obj;
   1617         if (ar.exception != null) {
   1618             if (DBG) Log.d(LOG_TAG, "handleQueryTTYModeResponse: Error getting TTY state.");
   1619         } else {
   1620             if (DBG) Log.d(LOG_TAG,
   1621                            "handleQueryTTYModeResponse: TTY enable state successfully queried.");
   1622 
   1623             int ttymode = ((int[]) ar.result)[0];
   1624             if (DBG) Log.d(LOG_TAG, "handleQueryTTYModeResponse:ttymode=" + ttymode);
   1625 
   1626             Intent ttyModeChanged = new Intent(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
   1627             ttyModeChanged.putExtra("ttyEnabled", ttymode != Phone.TTY_MODE_OFF);
   1628             sendBroadcast(ttyModeChanged);
   1629 
   1630             String audioTtyMode;
   1631             switch (ttymode) {
   1632             case Phone.TTY_MODE_FULL:
   1633                 audioTtyMode = "tty_full";
   1634                 break;
   1635             case Phone.TTY_MODE_VCO:
   1636                 audioTtyMode = "tty_vco";
   1637                 break;
   1638             case Phone.TTY_MODE_HCO:
   1639                 audioTtyMode = "tty_hco";
   1640                 break;
   1641             case Phone.TTY_MODE_OFF:
   1642             default:
   1643                 audioTtyMode = "tty_off";
   1644                 break;
   1645             }
   1646             AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
   1647             audioManager.setParameters("tty_mode="+audioTtyMode);
   1648         }
   1649     }
   1650 
   1651     private void handleSetTTYModeResponse(Message msg) {
   1652         AsyncResult ar = (AsyncResult) msg.obj;
   1653 
   1654         if (ar.exception != null) {
   1655             if (DBG) Log.d (LOG_TAG,
   1656                     "handleSetTTYModeResponse: Error setting TTY mode, ar.exception"
   1657                     + ar.exception);
   1658         }
   1659         phone.queryTTYMode(mHandler.obtainMessage(EVENT_TTY_MODE_GET));
   1660     }
   1661 
   1662     /* package */ void clearUserActivityTimeout() {
   1663         try {
   1664             mPowerManagerService.clearUserActivityTimeout(SystemClock.uptimeMillis(),
   1665                     10*1000 /* 10 sec */);
   1666         } catch (RemoteException ex) {
   1667             // System process is dead.
   1668         }
   1669     }
   1670 }
   1671