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.KeyguardManager; 21 import android.app.PendingIntent; 22 import android.app.ProgressDialog; 23 import android.app.TaskStackBuilder; 24 import android.bluetooth.BluetoothAdapter; 25 import android.bluetooth.IBluetoothHeadsetPhone; 26 import android.content.ActivityNotFoundException; 27 import android.content.BroadcastReceiver; 28 import android.content.ComponentName; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.ContextWrapper; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.content.ServiceConnection; 35 import android.content.res.Configuration; 36 import android.media.AudioManager; 37 import android.net.Uri; 38 import android.os.AsyncResult; 39 import android.os.Binder; 40 import android.os.Handler; 41 import android.os.IBinder; 42 import android.os.IPowerManager; 43 import android.os.Message; 44 import android.os.PowerManager; 45 import android.os.RemoteException; 46 import android.os.ServiceManager; 47 import android.os.SystemClock; 48 import android.os.SystemProperties; 49 import android.os.UpdateLock; 50 import android.os.UserHandle; 51 import android.preference.PreferenceManager; 52 import android.provider.Settings.System; 53 import android.telephony.ServiceState; 54 import android.text.TextUtils; 55 import android.util.Log; 56 import android.util.Slog; 57 import android.view.KeyEvent; 58 59 import com.android.internal.telephony.Call; 60 import com.android.internal.telephony.CallManager; 61 import com.android.internal.telephony.IccCard; 62 import com.android.internal.telephony.IccCardConstants; 63 import com.android.internal.telephony.MmiCode; 64 import com.android.internal.telephony.Phone; 65 import com.android.internal.telephony.PhoneConstants; 66 import com.android.internal.telephony.PhoneFactory; 67 import com.android.internal.telephony.TelephonyCapabilities; 68 import com.android.internal.telephony.TelephonyIntents; 69 import com.android.internal.telephony.cdma.TtyIntent; 70 import com.android.phone.common.CallLogAsync; 71 import com.android.phone.OtaUtils.CdmaOtaScreenState; 72 import com.android.phone.WiredHeadsetManager.WiredHeadsetListener; 73 import com.android.server.sip.SipService; 74 import com.android.services.telephony.common.AudioMode; 75 76 /** 77 * Global state for the telephony subsystem when running in the primary 78 * phone process. 79 */ 80 public class PhoneGlobals extends ContextWrapper implements WiredHeadsetListener { 81 /* package */ static final String LOG_TAG = "PhoneApp"; 82 83 /** 84 * Phone app-wide debug level: 85 * 0 - no debug logging 86 * 1 - normal debug logging if ro.debuggable is set (which is true in 87 * "eng" and "userdebug" builds but not "user" builds) 88 * 2 - ultra-verbose debug logging 89 * 90 * Most individual classes in the phone app have a local DBG constant, 91 * typically set to 92 * (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1) 93 * or else 94 * (PhoneApp.DBG_LEVEL >= 2) 95 * depending on the desired verbosity. 96 * 97 * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 ************* 98 */ 99 /* package */ static final int DBG_LEVEL = 0; 100 101 private static final boolean DBG = 102 (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1); 103 private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2); 104 105 // Message codes; see mHandler below. 106 private static final int EVENT_SIM_NETWORK_LOCKED = 3; 107 private static final int EVENT_SIM_STATE_CHANGED = 8; 108 private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10; 109 private static final int EVENT_DATA_ROAMING_OK = 11; 110 private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12; 111 private static final int EVENT_DOCK_STATE_CHANGED = 13; 112 private static final int EVENT_TTY_PREFERRED_MODE_CHANGED = 14; 113 private static final int EVENT_TTY_MODE_GET = 15; 114 private static final int EVENT_TTY_MODE_SET = 16; 115 private static final int EVENT_START_SIP_SERVICE = 17; 116 117 // The MMI codes are also used by the InCallScreen. 118 public static final int MMI_INITIATE = 51; 119 public static final int MMI_COMPLETE = 52; 120 public static final int MMI_CANCEL = 53; 121 // Don't use message codes larger than 99 here; those are reserved for 122 // the individual Activities of the Phone UI. 123 124 /** 125 * Allowable values for the wake lock code. 126 * SLEEP means the device can be put to sleep. 127 * PARTIAL means wake the processor, but we display can be kept off. 128 * FULL means wake both the processor and the display. 129 */ 130 public enum WakeState { 131 SLEEP, 132 PARTIAL, 133 FULL 134 } 135 136 /** 137 * Intent Action used for hanging up the current call from Notification bar. This will 138 * choose first ringing call, first active call, or first background call (typically in 139 * HOLDING state). 140 */ 141 public static final String ACTION_HANG_UP_ONGOING_CALL = 142 "com.android.phone.ACTION_HANG_UP_ONGOING_CALL"; 143 144 /** 145 * Intent Action used for making a phone call from Notification bar. 146 * This is for missed call notifications. 147 */ 148 public static final String ACTION_CALL_BACK_FROM_NOTIFICATION = 149 "com.android.phone.ACTION_CALL_BACK_FROM_NOTIFICATION"; 150 151 /** 152 * Intent Action used for sending a SMS from notification bar. 153 * This is for missed call notifications. 154 */ 155 public static final String ACTION_SEND_SMS_FROM_NOTIFICATION = 156 "com.android.phone.ACTION_SEND_SMS_FROM_NOTIFICATION"; 157 158 private static PhoneGlobals sMe; 159 160 // A few important fields we expose to the rest of the package 161 // directly (rather than thru set/get methods) for efficiency. 162 CallController callController; 163 CallManager mCM; 164 CallNotifier notifier; 165 CallerInfoCache callerInfoCache; 166 NotificationMgr notificationMgr; 167 Phone phone; 168 PhoneInterfaceManager phoneMgr; 169 170 private AudioRouter audioRouter; 171 private BluetoothManager bluetoothManager; 172 private CallCommandService callCommandService; 173 private CallGatewayManager callGatewayManager; 174 private CallHandlerServiceProxy callHandlerServiceProxy; 175 private CallModeler callModeler; 176 private CallStateMonitor callStateMonitor; 177 private DTMFTonePlayer dtmfTonePlayer; 178 private IBluetoothHeadsetPhone mBluetoothPhone; 179 private Ringer ringer; 180 private WiredHeadsetManager wiredHeadsetManager; 181 182 static int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; 183 static boolean sVoiceCapable = true; 184 185 // Internal PhoneApp Call state tracker 186 CdmaPhoneCallState cdmaPhoneCallState; 187 188 // The currently-active PUK entry activity and progress dialog. 189 // Normally, these are the Emergency Dialer and the subsequent 190 // progress dialog. null if there is are no such objects in 191 // the foreground. 192 private Activity mPUKEntryActivity; 193 private ProgressDialog mPUKEntryProgressDialog; 194 195 private boolean mIsSimPinEnabled; 196 private String mCachedSimPin; 197 198 // True if we are beginning a call, but the phone state has not changed yet 199 private boolean mBeginningCall; 200 201 // Last phone state seen by updatePhoneState() 202 private PhoneConstants.State mLastPhoneState = PhoneConstants.State.IDLE; 203 204 private WakeState mWakeState = WakeState.SLEEP; 205 206 private PowerManager mPowerManager; 207 private IPowerManager mPowerManagerService; 208 private PowerManager.WakeLock mWakeLock; 209 private PowerManager.WakeLock mPartialWakeLock; 210 private KeyguardManager mKeyguardManager; 211 212 private UpdateLock mUpdateLock; 213 214 // Broadcast receiver for various intent broadcasts (see onCreate()) 215 private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver(); 216 217 // Broadcast receiver purely for ACTION_MEDIA_BUTTON broadcasts 218 private final BroadcastReceiver mMediaButtonReceiver = new MediaButtonBroadcastReceiver(); 219 220 /** boolean indicating restoring mute state on InCallScreen.onResume() */ 221 private boolean mShouldRestoreMuteOnInCallResume; 222 223 /** 224 * The singleton OtaUtils instance used for OTASP calls. 225 * 226 * The OtaUtils instance is created lazily the first time we need to 227 * make an OTASP call, regardless of whether it's an interactive or 228 * non-interactive OTASP call. 229 */ 230 public OtaUtils otaUtils; 231 232 // Following are the CDMA OTA information Objects used during OTA Call. 233 // cdmaOtaProvisionData object store static OTA information that needs 234 // to be maintained even during Slider open/close scenarios. 235 // cdmaOtaConfigData object stores configuration info to control visiblity 236 // of each OTA Screens. 237 // cdmaOtaScreenState object store OTA Screen State information. 238 public OtaUtils.CdmaOtaProvisionData cdmaOtaProvisionData; 239 public OtaUtils.CdmaOtaConfigData cdmaOtaConfigData; 240 public OtaUtils.CdmaOtaScreenState cdmaOtaScreenState; 241 public OtaUtils.CdmaOtaInCallScreenUiState cdmaOtaInCallScreenUiState; 242 243 // TTY feature enabled on this platform 244 private boolean mTtyEnabled; 245 // Current TTY operating mode selected by user 246 private int mPreferredTtyMode = Phone.TTY_MODE_OFF; 247 248 /** 249 * Set the restore mute state flag. Used when we are setting the mute state 250 * OUTSIDE of user interaction {@link PhoneUtils#startNewCall(Phone)} 251 */ 252 /*package*/void setRestoreMuteOnInCallResume (boolean mode) { 253 mShouldRestoreMuteOnInCallResume = mode; 254 } 255 256 Handler mHandler = new Handler() { 257 @Override 258 public void handleMessage(Message msg) { 259 PhoneConstants.State phoneState; 260 switch (msg.what) { 261 // Starts the SIP service. It's a no-op if SIP API is not supported 262 // on the deivce. 263 // TODO: Having the phone process host the SIP service is only 264 // temporary. Will move it to a persistent communication process 265 // later. 266 case EVENT_START_SIP_SERVICE: 267 SipService.start(getApplicationContext()); 268 break; 269 270 // TODO: This event should be handled by the lock screen, just 271 // like the "SIM missing" and "Sim locked" cases (bug 1804111). 272 case EVENT_SIM_NETWORK_LOCKED: 273 if (getResources().getBoolean(R.bool.ignore_sim_network_locked_events)) { 274 // Some products don't have the concept of a "SIM network lock" 275 Log.i(LOG_TAG, "Ignoring EVENT_SIM_NETWORK_LOCKED event; " 276 + "not showing 'SIM network unlock' PIN entry screen"); 277 } else { 278 // Normal case: show the "SIM network unlock" PIN entry screen. 279 // The user won't be able to do anything else until 280 // they enter a valid SIM network PIN. 281 Log.i(LOG_TAG, "show sim depersonal panel"); 282 IccNetworkDepersonalizationPanel ndpPanel = 283 new IccNetworkDepersonalizationPanel(PhoneGlobals.getInstance()); 284 ndpPanel.show(); 285 } 286 break; 287 288 case EVENT_DATA_ROAMING_DISCONNECTED: 289 notificationMgr.showDataDisconnectedRoaming(); 290 break; 291 292 case EVENT_DATA_ROAMING_OK: 293 notificationMgr.hideDataDisconnectedRoaming(); 294 break; 295 296 case MMI_COMPLETE: 297 onMMIComplete((AsyncResult) msg.obj); 298 break; 299 300 case MMI_CANCEL: 301 PhoneUtils.cancelMmiCode(phone); 302 break; 303 304 case EVENT_SIM_STATE_CHANGED: 305 // Marks the event where the SIM goes into ready state. 306 // Right now, this is only used for the PUK-unlocking 307 // process. 308 if (msg.obj.equals(IccCardConstants.INTENT_VALUE_ICC_READY)) { 309 // when the right event is triggered and there 310 // are UI objects in the foreground, we close 311 // them to display the lock panel. 312 if (mPUKEntryActivity != null) { 313 mPUKEntryActivity.finish(); 314 mPUKEntryActivity = null; 315 } 316 if (mPUKEntryProgressDialog != null) { 317 mPUKEntryProgressDialog.dismiss(); 318 mPUKEntryProgressDialog = null; 319 } 320 } 321 break; 322 323 case EVENT_UNSOL_CDMA_INFO_RECORD: 324 //TODO: handle message here; 325 break; 326 327 case EVENT_DOCK_STATE_CHANGED: 328 // If the phone is docked/undocked during a call, and no wired or BT headset 329 // is connected: turn on/off the speaker accordingly. 330 boolean inDockMode = false; 331 if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) { 332 inDockMode = true; 333 } 334 if (VDBG) Log.d(LOG_TAG, "received EVENT_DOCK_STATE_CHANGED. Phone inDock = " 335 + inDockMode); 336 337 phoneState = mCM.getState(); 338 if (phoneState == PhoneConstants.State.OFFHOOK && 339 !wiredHeadsetManager.isHeadsetPlugged() && 340 !bluetoothManager.isBluetoothHeadsetAudioOn()) { 341 audioRouter.setSpeaker(inDockMode); 342 343 PhoneUtils.turnOnSpeaker(getApplicationContext(), inDockMode, true); 344 } 345 break; 346 347 case EVENT_TTY_PREFERRED_MODE_CHANGED: 348 // TTY mode is only applied if a headset is connected 349 int ttyMode; 350 if (wiredHeadsetManager.isHeadsetPlugged()) { 351 ttyMode = mPreferredTtyMode; 352 } else { 353 ttyMode = Phone.TTY_MODE_OFF; 354 } 355 phone.setTTYMode(ttyMode, mHandler.obtainMessage(EVENT_TTY_MODE_SET)); 356 break; 357 358 case EVENT_TTY_MODE_GET: 359 handleQueryTTYModeResponse(msg); 360 break; 361 362 case EVENT_TTY_MODE_SET: 363 handleSetTTYModeResponse(msg); 364 break; 365 } 366 } 367 }; 368 369 public PhoneGlobals(Context context) { 370 super(context); 371 sMe = this; 372 } 373 374 public void onCreate() { 375 if (VDBG) Log.v(LOG_TAG, "onCreate()..."); 376 377 ContentResolver resolver = getContentResolver(); 378 379 // Cache the "voice capable" flag. 380 // This flag currently comes from a resource (which is 381 // overrideable on a per-product basis): 382 sVoiceCapable = 383 getResources().getBoolean(com.android.internal.R.bool.config_voice_capable); 384 // ...but this might eventually become a PackageManager "system 385 // feature" instead, in which case we'd do something like: 386 // sVoiceCapable = 387 // getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS); 388 389 if (phone == null) { 390 // Initialize the telephony framework 391 PhoneFactory.makeDefaultPhones(this); 392 393 // Get the default phone 394 phone = PhoneFactory.getDefaultPhone(); 395 396 // Start TelephonyDebugService After the default phone is created. 397 Intent intent = new Intent(this, TelephonyDebugService.class); 398 startService(intent); 399 400 mCM = CallManager.getInstance(); 401 mCM.registerPhone(phone); 402 403 // Create the NotificationMgr singleton, which is used to display 404 // status bar icons and control other status bar behavior. 405 notificationMgr = NotificationMgr.init(this); 406 407 mHandler.sendEmptyMessage(EVENT_START_SIP_SERVICE); 408 409 int phoneType = phone.getPhoneType(); 410 411 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { 412 // Create an instance of CdmaPhoneCallState and initialize it to IDLE 413 cdmaPhoneCallState = new CdmaPhoneCallState(); 414 cdmaPhoneCallState.CdmaPhoneCallStateInit(); 415 } 416 417 if (BluetoothAdapter.getDefaultAdapter() != null) { 418 // Start BluetoothPhoneService even if device is not voice capable. 419 // The device can still support VOIP. 420 startService(new Intent(this, BluetoothPhoneService.class)); 421 bindService(new Intent(this, BluetoothPhoneService.class), 422 mBluetoothPhoneConnection, 0); 423 } else { 424 // Device is not bluetooth capable 425 mBluetoothPhone = null; 426 } 427 428 // before registering for phone state changes 429 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 430 mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG); 431 // lock used to keep the processor awake, when we don't care for the display. 432 mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK 433 | PowerManager.ON_AFTER_RELEASE, LOG_TAG); 434 435 mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 436 437 // get a handle to the service so that we can use it later when we 438 // want to set the poke lock. 439 mPowerManagerService = IPowerManager.Stub.asInterface( 440 ServiceManager.getService("power")); 441 442 // Get UpdateLock to suppress system-update related events (e.g. dialog show-up) 443 // during phone calls. 444 mUpdateLock = new UpdateLock("phone"); 445 446 if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock); 447 448 CallLogger callLogger = new CallLogger(this, new CallLogAsync()); 449 450 callGatewayManager = CallGatewayManager.getInstance(); 451 452 // Create the CallController singleton, which is the interface 453 // to the telephony layer for user-initiated telephony functionality 454 // (like making outgoing calls.) 455 callController = CallController.init(this, callLogger, callGatewayManager); 456 457 // Create the CallerInfoCache singleton, which remembers custom ring tone and 458 // send-to-voicemail settings. 459 // 460 // The asynchronous caching will start just after this call. 461 callerInfoCache = CallerInfoCache.init(this); 462 463 // Monitors call activity from the telephony layer 464 callStateMonitor = new CallStateMonitor(mCM); 465 466 // Creates call models for use with CallHandlerService. 467 callModeler = new CallModeler(callStateMonitor, mCM, callGatewayManager); 468 469 // Plays DTMF Tones 470 dtmfTonePlayer = new DTMFTonePlayer(mCM, callModeler); 471 472 // Manages wired headset state 473 wiredHeadsetManager = new WiredHeadsetManager(this); 474 wiredHeadsetManager.addWiredHeadsetListener(this); 475 476 // Bluetooth manager 477 bluetoothManager = new BluetoothManager(this, mCM, callModeler); 478 479 ringer = Ringer.init(this, bluetoothManager); 480 481 // Audio router 482 audioRouter = new AudioRouter(this, bluetoothManager, wiredHeadsetManager, mCM); 483 484 // Service used by in-call UI to control calls 485 callCommandService = new CallCommandService(this, mCM, callModeler, dtmfTonePlayer, 486 audioRouter); 487 488 // Sends call state to the UI 489 callHandlerServiceProxy = new CallHandlerServiceProxy(this, callModeler, 490 callCommandService, audioRouter); 491 492 phoneMgr = PhoneInterfaceManager.init(this, phone, callHandlerServiceProxy, callModeler, 493 dtmfTonePlayer); 494 495 // Create the CallNotifer singleton, which handles 496 // asynchronous events from the telephony layer (like 497 // launching the incoming-call UI when an incoming call comes 498 // in.) 499 notifier = CallNotifier.init(this, phone, ringer, callLogger, callStateMonitor, 500 bluetoothManager, callModeler); 501 502 // register for ICC status 503 IccCard sim = phone.getIccCard(); 504 if (sim != null) { 505 if (VDBG) Log.v(LOG_TAG, "register for ICC status"); 506 sim.registerForNetworkLocked(mHandler, EVENT_SIM_NETWORK_LOCKED, null); 507 } 508 509 // register for MMI/USSD 510 mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null); 511 512 // register connection tracking to PhoneUtils 513 PhoneUtils.initializeConnectionHandler(mCM); 514 515 // Read platform settings for TTY feature 516 mTtyEnabled = getResources().getBoolean(R.bool.tty_enabled); 517 518 // Register for misc other intent broadcasts. 519 IntentFilter intentFilter = 520 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); 521 intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); 522 intentFilter.addAction(Intent.ACTION_DOCK_EVENT); 523 intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 524 intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED); 525 intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); 526 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 527 if (mTtyEnabled) { 528 intentFilter.addAction(TtyIntent.TTY_PREFERRED_MODE_CHANGE_ACTION); 529 } 530 intentFilter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 531 registerReceiver(mReceiver, intentFilter); 532 533 // Use a separate receiver for ACTION_MEDIA_BUTTON broadcasts, 534 // since we need to manually adjust its priority (to make sure 535 // we get these intents *before* the media player.) 536 IntentFilter mediaButtonIntentFilter = 537 new IntentFilter(Intent.ACTION_MEDIA_BUTTON); 538 // TODO verify the independent priority doesn't need to be handled thanks to the 539 // private intent handler registration 540 // Make sure we're higher priority than the media player's 541 // MediaButtonIntentReceiver (which currently has the default 542 // priority of zero; see apps/Music/AndroidManifest.xml.) 543 mediaButtonIntentFilter.setPriority(1); 544 // 545 registerReceiver(mMediaButtonReceiver, mediaButtonIntentFilter); 546 // register the component so it gets priority for calls 547 AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 548 am.registerMediaButtonEventReceiverForCalls(new ComponentName(this.getPackageName(), 549 MediaButtonBroadcastReceiver.class.getName())); 550 551 //set the default values for the preferences in the phone. 552 PreferenceManager.setDefaultValues(this, R.xml.network_setting, false); 553 554 PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false); 555 556 // Make sure the audio mode (along with some 557 // audio-mode-related state of our own) is initialized 558 // correctly, given the current state of the phone. 559 PhoneUtils.setAudioMode(mCM); 560 } 561 562 if (TelephonyCapabilities.supportsOtasp(phone)) { 563 cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData(); 564 cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData(); 565 cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState(); 566 cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState(); 567 } 568 569 // XXX pre-load the SimProvider so that it's ready 570 resolver.getType(Uri.parse("content://icc/adn")); 571 572 // start with the default value to set the mute state. 573 mShouldRestoreMuteOnInCallResume = false; 574 575 // TODO: Register for Cdma Information Records 576 // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null); 577 578 // Read TTY settings and store it into BP NV. 579 // AP owns (i.e. stores) the TTY setting in AP settings database and pushes the setting 580 // to BP at power up (BP does not need to make the TTY setting persistent storage). 581 // This way, there is a single owner (i.e AP) for the TTY setting in the phone. 582 if (mTtyEnabled) { 583 mPreferredTtyMode = android.provider.Settings.Secure.getInt( 584 phone.getContext().getContentResolver(), 585 android.provider.Settings.Secure.PREFERRED_TTY_MODE, 586 Phone.TTY_MODE_OFF); 587 mHandler.sendMessage(mHandler.obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0)); 588 } 589 // Read HAC settings and configure audio hardware 590 if (getResources().getBoolean(R.bool.hac_enabled)) { 591 int hac = android.provider.Settings.System.getInt(phone.getContext().getContentResolver(), 592 android.provider.Settings.System.HEARING_AID, 593 0); 594 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 595 audioManager.setParameter(CallFeaturesSetting.HAC_KEY, hac != 0 ? 596 CallFeaturesSetting.HAC_VAL_ON : 597 CallFeaturesSetting.HAC_VAL_OFF); 598 } 599 } 600 601 /** 602 * Returns the singleton instance of the PhoneApp. 603 */ 604 static PhoneGlobals getInstance() { 605 if (sMe == null) { 606 throw new IllegalStateException("No PhoneGlobals here!"); 607 } 608 return sMe; 609 } 610 611 /** 612 * Returns the singleton instance of the PhoneApp if running as the 613 * primary user, otherwise null. 614 */ 615 static PhoneGlobals getInstanceIfPrimary() { 616 return sMe; 617 } 618 619 /** 620 * Returns the Phone associated with this instance 621 */ 622 static Phone getPhone() { 623 return getInstance().phone; 624 } 625 626 Ringer getRinger() { 627 return ringer; 628 } 629 630 IBluetoothHeadsetPhone getBluetoothPhoneService() { 631 return mBluetoothPhone; 632 } 633 634 /* package */ BluetoothManager getBluetoothManager() { 635 return bluetoothManager; 636 } 637 638 /* package */ WiredHeadsetManager getWiredHeadsetManager() { 639 return wiredHeadsetManager; 640 } 641 642 /* package */ AudioRouter getAudioRouter() { 643 return audioRouter; 644 } 645 646 /* package */ CallModeler getCallModeler() { 647 return callModeler; 648 } 649 650 /* package */ CallManager getCallManager() { 651 return mCM; 652 } 653 654 /** 655 * Returns an Intent that can be used to go to the "Call log" 656 * UI (aka CallLogActivity) in the Contacts app. 657 * 658 * Watch out: there's no guarantee that the system has any activity to 659 * handle this intent. (In particular there may be no "Call log" at 660 * all on on non-voice-capable devices.) 661 */ 662 /* package */ static Intent createCallLogIntent() { 663 Intent intent = new Intent(Intent.ACTION_VIEW, null); 664 intent.setType("vnd.android.cursor.dir/calls"); 665 return intent; 666 } 667 668 /* package */static PendingIntent createPendingCallLogIntent(Context context) { 669 final Intent callLogIntent = PhoneGlobals.createCallLogIntent(); 670 final TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context); 671 taskStackBuilder.addNextIntent(callLogIntent); 672 return taskStackBuilder.getPendingIntent(0, 0); 673 } 674 675 /** 676 * Returns PendingIntent for hanging up ongoing phone call. This will typically be used from 677 * Notification context. 678 */ 679 /* package */ static PendingIntent createHangUpOngoingCallPendingIntent(Context context) { 680 Intent intent = new Intent(PhoneGlobals.ACTION_HANG_UP_ONGOING_CALL, null, 681 context, NotificationBroadcastReceiver.class); 682 return PendingIntent.getBroadcast(context, 0, intent, 0); 683 } 684 685 /* package */ static PendingIntent getCallBackPendingIntent(Context context, String number) { 686 Intent intent = new Intent(ACTION_CALL_BACK_FROM_NOTIFICATION, 687 Uri.fromParts(Constants.SCHEME_TEL, number, null), 688 context, NotificationBroadcastReceiver.class); 689 return PendingIntent.getBroadcast(context, 0, intent, 0); 690 } 691 692 /* package */ static PendingIntent getSendSmsFromNotificationPendingIntent( 693 Context context, String number) { 694 Intent intent = new Intent(ACTION_SEND_SMS_FROM_NOTIFICATION, 695 Uri.fromParts(Constants.SCHEME_SMSTO, number, null), 696 context, NotificationBroadcastReceiver.class); 697 return PendingIntent.getBroadcast(context, 0, intent, 0); 698 } 699 700 boolean isSimPinEnabled() { 701 return mIsSimPinEnabled; 702 } 703 704 boolean authenticateAgainstCachedSimPin(String pin) { 705 return (mCachedSimPin != null && mCachedSimPin.equals(pin)); 706 } 707 708 void setCachedSimPin(String pin) { 709 mCachedSimPin = pin; 710 } 711 712 /** 713 * Handles OTASP-related events from the telephony layer. 714 * 715 * While an OTASP call is active, the CallNotifier forwards 716 * OTASP-related telephony events to this method. 717 */ 718 void handleOtaspEvent(Message msg) { 719 if (DBG) Log.d(LOG_TAG, "handleOtaspEvent(message " + msg + ")..."); 720 721 if (otaUtils == null) { 722 // We shouldn't be getting OTASP events without ever 723 // having started the OTASP call in the first place! 724 Log.w(LOG_TAG, "handleOtaEvents: got an event but otaUtils is null! " 725 + "message = " + msg); 726 return; 727 } 728 729 otaUtils.onOtaProvisionStatusChanged((AsyncResult) msg.obj); 730 } 731 732 /** 733 * Similarly, handle the disconnect event of an OTASP call 734 * by forwarding it to the OtaUtils instance. 735 */ 736 /* package */ void handleOtaspDisconnect() { 737 if (DBG) Log.d(LOG_TAG, "handleOtaspDisconnect()..."); 738 739 if (otaUtils == null) { 740 // We shouldn't be getting OTASP events without ever 741 // having started the OTASP call in the first place! 742 Log.w(LOG_TAG, "handleOtaspDisconnect: otaUtils is null!"); 743 return; 744 } 745 746 otaUtils.onOtaspDisconnect(); 747 } 748 749 /** 750 * Sets the activity responsible for un-PUK-blocking the device 751 * so that we may close it when we receive a positive result. 752 * mPUKEntryActivity is also used to indicate to the device that 753 * we are trying to un-PUK-lock the phone. In other words, iff 754 * it is NOT null, then we are trying to unlock and waiting for 755 * the SIM to move to READY state. 756 * 757 * @param activity is the activity to close when PUK has 758 * finished unlocking. Can be set to null to indicate the unlock 759 * or SIM READYing process is over. 760 */ 761 void setPukEntryActivity(Activity activity) { 762 mPUKEntryActivity = activity; 763 } 764 765 Activity getPUKEntryActivity() { 766 return mPUKEntryActivity; 767 } 768 769 /** 770 * Sets the dialog responsible for notifying the user of un-PUK- 771 * blocking - SIM READYing progress, so that we may dismiss it 772 * when we receive a positive result. 773 * 774 * @param dialog indicates the progress dialog informing the user 775 * of the state of the device. Dismissed upon completion of 776 * READYing process 777 */ 778 void setPukEntryProgressDialog(ProgressDialog dialog) { 779 mPUKEntryProgressDialog = dialog; 780 } 781 782 ProgressDialog getPUKEntryProgressDialog() { 783 return mPUKEntryProgressDialog; 784 } 785 786 /** 787 * Controls whether or not the screen is allowed to sleep. 788 * 789 * Once sleep is allowed (WakeState is SLEEP), it will rely on the 790 * settings for the poke lock to determine when to timeout and let 791 * the device sleep {@link PhoneGlobals#setScreenTimeout}. 792 * 793 * @param ws tells the device to how to wake. 794 */ 795 /* package */ void requestWakeState(WakeState ws) { 796 if (VDBG) Log.d(LOG_TAG, "requestWakeState(" + ws + ")..."); 797 synchronized (this) { 798 if (mWakeState != ws) { 799 switch (ws) { 800 case PARTIAL: 801 // acquire the processor wake lock, and release the FULL 802 // lock if it is being held. 803 mPartialWakeLock.acquire(); 804 if (mWakeLock.isHeld()) { 805 mWakeLock.release(); 806 } 807 break; 808 case FULL: 809 // acquire the full wake lock, and release the PARTIAL 810 // lock if it is being held. 811 mWakeLock.acquire(); 812 if (mPartialWakeLock.isHeld()) { 813 mPartialWakeLock.release(); 814 } 815 break; 816 case SLEEP: 817 default: 818 // release both the PARTIAL and FULL locks. 819 if (mWakeLock.isHeld()) { 820 mWakeLock.release(); 821 } 822 if (mPartialWakeLock.isHeld()) { 823 mPartialWakeLock.release(); 824 } 825 break; 826 } 827 mWakeState = ws; 828 } 829 } 830 } 831 832 /** 833 * If we are not currently keeping the screen on, then poke the power 834 * manager to wake up the screen for the user activity timeout duration. 835 */ 836 /* package */ void wakeUpScreen() { 837 synchronized (this) { 838 if (mWakeState == WakeState.SLEEP) { 839 if (DBG) Log.d(LOG_TAG, "pulse screen lock"); 840 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 841 } 842 } 843 } 844 845 /** 846 * Sets the wake state and screen timeout based on the current state 847 * of the phone, and the current state of the in-call UI. 848 * 849 * This method is a "UI Policy" wrapper around 850 * {@link PhoneGlobals#requestWakeState} and {@link PhoneGlobals#setScreenTimeout}. 851 * 852 * It's safe to call this method regardless of the state of the Phone 853 * (e.g. whether or not it's idle), and regardless of the state of the 854 * Phone UI (e.g. whether or not the InCallScreen is active.) 855 */ 856 /* package */ void updateWakeState() { 857 PhoneConstants.State state = mCM.getState(); 858 859 // True if the speakerphone is in use. (If so, we *always* use 860 // the default timeout. Since the user is obviously not holding 861 // the phone up to his/her face, we don't need to worry about 862 // false touches, and thus don't need to turn the screen off so 863 // aggressively.) 864 // Note that we need to make a fresh call to this method any 865 // time the speaker state changes. (That happens in 866 // PhoneUtils.turnOnSpeaker().) 867 boolean isSpeakerInUse = (state == PhoneConstants.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this); 868 869 // TODO (bug 1440854): The screen timeout *might* also need to 870 // depend on the bluetooth state, but this isn't as clear-cut as 871 // the speaker state (since while using BT it's common for the 872 // user to put the phone straight into a pocket, in which case the 873 // timeout should probably still be short.) 874 875 // Decide whether to force the screen on or not. 876 // 877 // Force the screen to be on if the phone is ringing or dialing, 878 // or if we're displaying the "Call ended" UI for a connection in 879 // the "disconnected" state. 880 // However, if the phone is disconnected while the user is in the 881 // middle of selecting a quick response message, we should not force 882 // the screen to be on. 883 // 884 boolean isRinging = (state == PhoneConstants.State.RINGING); 885 boolean isDialing = (phone.getForegroundCall().getState() == Call.State.DIALING); 886 boolean keepScreenOn = isRinging || isDialing; 887 // keepScreenOn == true means we'll hold a full wake lock: 888 requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP); 889 } 890 891 /** 892 * Manually pokes the PowerManager's userActivity method. Since we 893 * set the {@link WindowManager.LayoutParams#INPUT_FEATURE_DISABLE_USER_ACTIVITY} 894 * flag while the InCallScreen is active when there is no proximity sensor, 895 * we need to do this for touch events that really do count as user activity 896 * (like pressing any onscreen UI elements.) 897 */ 898 /* package */ void pokeUserActivity() { 899 if (VDBG) Log.d(LOG_TAG, "pokeUserActivity()..."); 900 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 901 } 902 903 /** 904 * Notifies the phone app when the phone state changes. 905 * 906 * This method will updates various states inside Phone app (e.g. update-lock state, etc.) 907 */ 908 /* package */ void updatePhoneState(PhoneConstants.State state) { 909 if (state != mLastPhoneState) { 910 mLastPhoneState = state; 911 912 // Try to acquire or release UpdateLock. 913 // 914 // Watch out: we don't release the lock here when the screen is still in foreground. 915 // At that time InCallScreen will release it on onPause(). 916 if (state != PhoneConstants.State.IDLE) { 917 // UpdateLock is a recursive lock, while we may get "acquire" request twice and 918 // "release" request once for a single call (RINGING + OFFHOOK and IDLE). 919 // We need to manually ensure the lock is just acquired once for each (and this 920 // will prevent other possible buggy situations too). 921 if (!mUpdateLock.isHeld()) { 922 mUpdateLock.acquire(); 923 } 924 } else { 925 if (mUpdateLock.isHeld()) { 926 mUpdateLock.release(); 927 } 928 } 929 } 930 } 931 932 /* package */ PhoneConstants.State getPhoneState() { 933 return mLastPhoneState; 934 } 935 936 KeyguardManager getKeyguardManager() { 937 return mKeyguardManager; 938 } 939 940 private void onMMIComplete(AsyncResult r) { 941 if (VDBG) Log.d(LOG_TAG, "onMMIComplete()..."); 942 MmiCode mmiCode = (MmiCode) r.result; 943 PhoneUtils.displayMMIComplete(phone, getInstance(), mmiCode, null, null); 944 } 945 946 private void initForNewRadioTechnology() { 947 if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology..."); 948 949 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) { 950 // Create an instance of CdmaPhoneCallState and initialize it to IDLE 951 cdmaPhoneCallState = new CdmaPhoneCallState(); 952 cdmaPhoneCallState.CdmaPhoneCallStateInit(); 953 } 954 if (TelephonyCapabilities.supportsOtasp(phone)) { 955 //create instances of CDMA OTA data classes 956 if (cdmaOtaProvisionData == null) { 957 cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData(); 958 } 959 if (cdmaOtaConfigData == null) { 960 cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData(); 961 } 962 if (cdmaOtaScreenState == null) { 963 cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState(); 964 } 965 if (cdmaOtaInCallScreenUiState == null) { 966 cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState(); 967 } 968 } else { 969 //Clean up OTA data in GSM/UMTS. It is valid only for CDMA 970 clearOtaState(); 971 } 972 973 ringer.updateRingerContextAfterRadioTechnologyChange(this.phone); 974 notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange(); 975 callStateMonitor.updateAfterRadioTechnologyChange(); 976 977 if (mBluetoothPhone != null) { 978 try { 979 mBluetoothPhone.updateBtHandsfreeAfterRadioTechnologyChange(); 980 } catch (RemoteException e) { 981 Log.e(LOG_TAG, Log.getStackTraceString(new Throwable())); 982 } 983 } 984 985 // Update registration for ICC status after radio technology change 986 IccCard sim = phone.getIccCard(); 987 if (sim != null) { 988 if (DBG) Log.d(LOG_TAG, "Update registration for ICC status..."); 989 990 //Register all events new to the new active phone 991 sim.registerForNetworkLocked(mHandler, EVENT_SIM_NETWORK_LOCKED, null); 992 } 993 } 994 995 996 /** 997 * This is called when the wired headset state changes. 998 */ 999 @Override 1000 public void onWiredHeadsetConnection(boolean pluggedIn) { 1001 PhoneConstants.State phoneState = mCM.getState(); 1002 1003 // Force TTY state update according to new headset state 1004 if (mTtyEnabled) { 1005 mHandler.sendMessage(mHandler.obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0)); 1006 } 1007 } 1008 1009 /** 1010 * Receiver for misc intent broadcasts the Phone app cares about. 1011 */ 1012 private class PhoneAppBroadcastReceiver extends BroadcastReceiver { 1013 @Override 1014 public void onReceive(Context context, Intent intent) { 1015 String action = intent.getAction(); 1016 if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 1017 boolean enabled = System.getInt(getContentResolver(), 1018 System.AIRPLANE_MODE_ON, 0) == 0; 1019 phone.setRadioPower(enabled); 1020 } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { 1021 if (VDBG) Log.d(LOG_TAG, "mReceiver: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED"); 1022 if (VDBG) Log.d(LOG_TAG, "- state: " + intent.getStringExtra(PhoneConstants.STATE_KEY)); 1023 if (VDBG) Log.d(LOG_TAG, "- reason: " 1024 + intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY)); 1025 1026 // The "data disconnected due to roaming" notification is shown 1027 // if (a) you have the "data roaming" feature turned off, and 1028 // (b) you just lost data connectivity because you're roaming. 1029 boolean disconnectedDueToRoaming = 1030 !phone.getDataRoamingEnabled() 1031 && "DISCONNECTED".equals(intent.getStringExtra(PhoneConstants.STATE_KEY)) 1032 && Phone.REASON_ROAMING_ON.equals( 1033 intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY)); 1034 mHandler.sendEmptyMessage(disconnectedDueToRoaming 1035 ? EVENT_DATA_ROAMING_DISCONNECTED 1036 : EVENT_DATA_ROAMING_OK); 1037 } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) && 1038 (mPUKEntryActivity != null)) { 1039 // if an attempt to un-PUK-lock the device was made, while we're 1040 // receiving this state change notification, notify the handler. 1041 // NOTE: This is ONLY triggered if an attempt to un-PUK-lock has 1042 // been attempted. 1043 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED, 1044 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE))); 1045 } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) { 1046 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY); 1047 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " is active."); 1048 initForNewRadioTechnology(); 1049 } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) { 1050 handleServiceStateChanged(intent); 1051 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 1052 if (TelephonyCapabilities.supportsEcm(phone)) { 1053 Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp."); 1054 // Start Emergency Callback Mode service 1055 if (intent.getBooleanExtra("phoneinECMState", false)) { 1056 context.startService(new Intent(context, 1057 EmergencyCallbackModeService.class)); 1058 } 1059 } else { 1060 // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED 1061 // on a device that doesn't support ECM in the first place. 1062 Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, " 1063 + "but ECM isn't supported for phone: " + phone.getPhoneName()); 1064 } 1065 } else if (action.equals(Intent.ACTION_DOCK_EVENT)) { 1066 mDockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 1067 Intent.EXTRA_DOCK_STATE_UNDOCKED); 1068 if (VDBG) Log.d(LOG_TAG, "ACTION_DOCK_EVENT -> mDockState = " + mDockState); 1069 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DOCK_STATE_CHANGED, 0)); 1070 } else if (action.equals(TtyIntent.TTY_PREFERRED_MODE_CHANGE_ACTION)) { 1071 mPreferredTtyMode = intent.getIntExtra(TtyIntent.TTY_PREFFERED_MODE, 1072 Phone.TTY_MODE_OFF); 1073 if (VDBG) Log.d(LOG_TAG, "mReceiver: TTY_PREFERRED_MODE_CHANGE_ACTION"); 1074 if (VDBG) Log.d(LOG_TAG, " mode: " + mPreferredTtyMode); 1075 mHandler.sendMessage(mHandler.obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0)); 1076 } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 1077 int ringerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, 1078 AudioManager.RINGER_MODE_NORMAL); 1079 if (ringerMode == AudioManager.RINGER_MODE_SILENT) { 1080 notifier.silenceRinger(); 1081 } 1082 } 1083 } 1084 } 1085 1086 /** 1087 * Broadcast receiver for the ACTION_MEDIA_BUTTON broadcast intent. 1088 * 1089 * This functionality isn't lumped in with the other intents in 1090 * PhoneAppBroadcastReceiver because we instantiate this as a totally 1091 * separate BroadcastReceiver instance, since we need to manually 1092 * adjust its IntentFilter's priority (to make sure we get these 1093 * intents *before* the media player.) 1094 */ 1095 private class MediaButtonBroadcastReceiver extends BroadcastReceiver { 1096 @Override 1097 public void onReceive(Context context, Intent intent) { 1098 KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); 1099 if (VDBG) Log.d(LOG_TAG, 1100 "MediaButtonBroadcastReceiver.onReceive()... event = " + event); 1101 if ((event != null) 1102 && (event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) { 1103 if (VDBG) Log.d(LOG_TAG, "MediaButtonBroadcastReceiver: HEADSETHOOK"); 1104 boolean consumed = PhoneUtils.handleHeadsetHook(phone, event); 1105 if (VDBG) Log.d(LOG_TAG, "==> handleHeadsetHook(): consumed = " + consumed); 1106 if (consumed) { 1107 abortBroadcast(); 1108 } 1109 } else { 1110 if (mCM.getState() != PhoneConstants.State.IDLE) { 1111 // If the phone is anything other than completely idle, 1112 // then we consume and ignore any media key events, 1113 // Otherwise it is too easy to accidentally start 1114 // playing music while a phone call is in progress. 1115 if (VDBG) Log.d(LOG_TAG, "MediaButtonBroadcastReceiver: consumed"); 1116 abortBroadcast(); 1117 } 1118 } 1119 } 1120 } 1121 1122 /** 1123 * Accepts broadcast Intents which will be prepared by {@link NotificationMgr} and thus 1124 * sent from framework's notification mechanism (which is outside Phone context). 1125 * This should be visible from outside, but shouldn't be in "exported" state. 1126 * 1127 * TODO: If possible merge this into PhoneAppBroadcastReceiver. 1128 */ 1129 public static class NotificationBroadcastReceiver extends BroadcastReceiver { 1130 @Override 1131 public void onReceive(Context context, Intent intent) { 1132 String action = intent.getAction(); 1133 // TODO: use "if (VDBG)" here. 1134 Log.d(LOG_TAG, "Broadcast from Notification: " + action); 1135 1136 if (action.equals(ACTION_HANG_UP_ONGOING_CALL)) { 1137 PhoneUtils.hangup(PhoneGlobals.getInstance().mCM); 1138 } else if (action.equals(ACTION_CALL_BACK_FROM_NOTIFICATION)) { 1139 // Collapse the expanded notification and the notification item itself. 1140 closeSystemDialogs(context); 1141 clearMissedCallNotification(context); 1142 1143 Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, intent.getData()); 1144 callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1145 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 1146 context.startActivity(callIntent); 1147 } else if (action.equals(ACTION_SEND_SMS_FROM_NOTIFICATION)) { 1148 // Collapse the expanded notification and the notification item itself. 1149 closeSystemDialogs(context); 1150 clearMissedCallNotification(context); 1151 1152 Intent smsIntent = new Intent(Intent.ACTION_SENDTO, intent.getData()); 1153 smsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1154 context.startActivity(smsIntent); 1155 } else { 1156 Log.w(LOG_TAG, "Received hang-up request from notification," 1157 + " but there's no call the system can hang up."); 1158 } 1159 } 1160 1161 private void closeSystemDialogs(Context context) { 1162 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 1163 context.sendBroadcastAsUser(intent, UserHandle.ALL); 1164 } 1165 1166 private void clearMissedCallNotification(Context context) { 1167 Intent clearIntent = new Intent(context, ClearMissedCallsService.class); 1168 clearIntent.setAction(ClearMissedCallsService.ACTION_CLEAR_MISSED_CALLS); 1169 context.startService(clearIntent); 1170 } 1171 } 1172 1173 private void handleServiceStateChanged(Intent intent) { 1174 /** 1175 * This used to handle updating EriTextWidgetProvider this routine 1176 * and and listening for ACTION_SERVICE_STATE_CHANGED intents could 1177 * be removed. But leaving just in case it might be needed in the near 1178 * future. 1179 */ 1180 1181 // If service just returned, start sending out the queued messages 1182 ServiceState ss = ServiceState.newFromBundle(intent.getExtras()); 1183 1184 if (ss != null) { 1185 int state = ss.getState(); 1186 notificationMgr.updateNetworkSelection(state); 1187 } 1188 } 1189 1190 public boolean isOtaCallInActiveState() { 1191 boolean otaCallActive = false; 1192 if (VDBG) Log.d(LOG_TAG, "- isOtaCallInActiveState " + otaCallActive); 1193 return otaCallActive; 1194 } 1195 1196 public boolean isOtaCallInEndState() { 1197 boolean otaCallEnded = false; 1198 if (VDBG) Log.d(LOG_TAG, "- isOtaCallInEndState " + otaCallEnded); 1199 return otaCallEnded; 1200 } 1201 1202 // it is safe to call clearOtaState() even if the InCallScreen isn't active 1203 public void clearOtaState() { 1204 if (DBG) Log.d(LOG_TAG, "- clearOtaState ..."); 1205 if (otaUtils != null) { 1206 otaUtils.cleanOtaScreen(true); 1207 if (DBG) Log.d(LOG_TAG, " - clearOtaState clears OTA screen"); 1208 } 1209 } 1210 1211 // it is safe to call dismissOtaDialogs() even if the InCallScreen isn't active 1212 public void dismissOtaDialogs() { 1213 if (DBG) Log.d(LOG_TAG, "- dismissOtaDialogs ..."); 1214 if (otaUtils != null) { 1215 otaUtils.dismissAllOtaDialogs(); 1216 if (DBG) Log.d(LOG_TAG, " - dismissOtaDialogs clears OTA dialogs"); 1217 } 1218 } 1219 1220 private void handleQueryTTYModeResponse(Message msg) { 1221 AsyncResult ar = (AsyncResult) msg.obj; 1222 if (ar.exception != null) { 1223 if (DBG) Log.d(LOG_TAG, "handleQueryTTYModeResponse: Error getting TTY state."); 1224 } else { 1225 if (DBG) Log.d(LOG_TAG, 1226 "handleQueryTTYModeResponse: TTY enable state successfully queried."); 1227 1228 int ttymode = ((int[]) ar.result)[0]; 1229 if (DBG) Log.d(LOG_TAG, "handleQueryTTYModeResponse:ttymode=" + ttymode); 1230 1231 Intent ttyModeChanged = new Intent(TtyIntent.TTY_ENABLED_CHANGE_ACTION); 1232 ttyModeChanged.putExtra("ttyEnabled", ttymode != Phone.TTY_MODE_OFF); 1233 sendBroadcastAsUser(ttyModeChanged, UserHandle.ALL); 1234 1235 String audioTtyMode; 1236 switch (ttymode) { 1237 case Phone.TTY_MODE_FULL: 1238 audioTtyMode = "tty_full"; 1239 break; 1240 case Phone.TTY_MODE_VCO: 1241 audioTtyMode = "tty_vco"; 1242 break; 1243 case Phone.TTY_MODE_HCO: 1244 audioTtyMode = "tty_hco"; 1245 break; 1246 case Phone.TTY_MODE_OFF: 1247 default: 1248 audioTtyMode = "tty_off"; 1249 break; 1250 } 1251 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 1252 audioManager.setParameters("tty_mode="+audioTtyMode); 1253 } 1254 } 1255 1256 private void handleSetTTYModeResponse(Message msg) { 1257 AsyncResult ar = (AsyncResult) msg.obj; 1258 1259 if (ar.exception != null) { 1260 if (DBG) Log.d (LOG_TAG, 1261 "handleSetTTYModeResponse: Error setting TTY mode, ar.exception" 1262 + ar.exception); 1263 } 1264 phone.queryTTYMode(mHandler.obtainMessage(EVENT_TTY_MODE_GET)); 1265 } 1266 1267 /** 1268 * "Call origin" may be used by Contacts app to specify where the phone call comes from. 1269 * Currently, the only permitted value for this extra is {@link #ALLOWED_EXTRA_CALL_ORIGIN}. 1270 * Any other value will be ignored, to make sure that malicious apps can't trick the in-call 1271 * UI into launching some random other app after a call ends. 1272 * 1273 * TODO: make this more generic. Note that we should let the "origin" specify its package 1274 * while we are now assuming it is "com.android.contacts" 1275 */ 1276 public static final String EXTRA_CALL_ORIGIN = "com.android.phone.CALL_ORIGIN"; 1277 private static final String DEFAULT_CALL_ORIGIN_PACKAGE = "com.android.dialer"; 1278 private static final String ALLOWED_EXTRA_CALL_ORIGIN = 1279 "com.android.dialer.DialtactsActivity"; 1280 /** 1281 * Used to determine if the preserved call origin is fresh enough. 1282 */ 1283 private static final long CALL_ORIGIN_EXPIRATION_MILLIS = 30 * 1000; 1284 1285 /** Service connection */ 1286 private final ServiceConnection mBluetoothPhoneConnection = new ServiceConnection() { 1287 1288 /** Handle the task of binding the local object to the service */ 1289 public void onServiceConnected(ComponentName className, IBinder service) { 1290 Log.i(LOG_TAG, "Headset phone created, binding local service."); 1291 mBluetoothPhone = IBluetoothHeadsetPhone.Stub.asInterface(service); 1292 } 1293 1294 /** Handle the task of cleaning up the local binding */ 1295 public void onServiceDisconnected(ComponentName className) { 1296 Log.i(LOG_TAG, "Headset phone disconnected, cleaning local binding."); 1297 mBluetoothPhone = null; 1298 } 1299 }; 1300 1301 } 1302