CallManager.java revision e5468b6b0242c072d0b7eea7e6c75a536cb650df
1/* 2 * Copyright (C) 2010 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 17package com.android.internal.telephony; 18 19import com.android.internal.telephony.imsphone.ImsPhone; 20import com.android.internal.telephony.sip.SipPhone; 21 22import android.content.Context; 23import android.os.AsyncResult; 24import android.os.Handler; 25import android.os.Message; 26import android.os.RegistrantList; 27import android.os.Registrant; 28import android.telecom.VideoProfile; 29import android.telephony.PhoneNumberUtils; 30import android.telephony.TelephonyManager; 31import android.telephony.PhoneStateListener; 32import android.telephony.ServiceState; 33import android.telephony.Rlog; 34 35import java.util.ArrayList; 36import java.util.Collections; 37import java.util.HashMap; 38import java.util.List; 39 40 41 42/** 43 * @hide 44 * 45 * CallManager class provides an abstract layer for PhoneApp to access 46 * and control calls. It implements Phone interface. 47 * 48 * CallManager provides call and connection control as well as 49 * channel capability. 50 * 51 * There are three categories of APIs CallManager provided 52 * 53 * 1. Call control and operation, such as dial() and hangup() 54 * 2. Channel capabilities, such as CanConference() 55 * 3. Register notification 56 * 57 * 58 */ 59public class CallManager { 60 61 private static final String LOG_TAG ="CallManager"; 62 private static final boolean DBG = true; 63 private static final boolean VDBG = false; 64 65 private static final int EVENT_DISCONNECT = 100; 66 private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101; 67 private static final int EVENT_NEW_RINGING_CONNECTION = 102; 68 private static final int EVENT_UNKNOWN_CONNECTION = 103; 69 private static final int EVENT_INCOMING_RING = 104; 70 private static final int EVENT_RINGBACK_TONE = 105; 71 private static final int EVENT_IN_CALL_VOICE_PRIVACY_ON = 106; 72 private static final int EVENT_IN_CALL_VOICE_PRIVACY_OFF = 107; 73 private static final int EVENT_CALL_WAITING = 108; 74 private static final int EVENT_DISPLAY_INFO = 109; 75 private static final int EVENT_SIGNAL_INFO = 110; 76 private static final int EVENT_CDMA_OTA_STATUS_CHANGE = 111; 77 private static final int EVENT_RESEND_INCALL_MUTE = 112; 78 private static final int EVENT_MMI_INITIATE = 113; 79 private static final int EVENT_MMI_COMPLETE = 114; 80 private static final int EVENT_ECM_TIMER_RESET = 115; 81 private static final int EVENT_SUBSCRIPTION_INFO_READY = 116; 82 private static final int EVENT_SUPP_SERVICE_FAILED = 117; 83 private static final int EVENT_SERVICE_STATE_CHANGED = 118; 84 private static final int EVENT_POST_DIAL_CHARACTER = 119; 85 private static final int EVENT_ONHOLD_TONE = 120; 86 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 87 //private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 121; 88 private static final int EVENT_TTY_MODE_RECEIVED = 122; 89 90 // Singleton instance 91 private static final CallManager INSTANCE = new CallManager(); 92 93 // list of registered phones, which are Phone objs 94 private final ArrayList<Phone> mPhones; 95 96 // list of supported ringing calls 97 private final ArrayList<Call> mRingingCalls; 98 99 // list of supported background calls 100 private final ArrayList<Call> mBackgroundCalls; 101 102 // list of supported foreground calls 103 private final ArrayList<Call> mForegroundCalls; 104 105 // empty connection list 106 private final ArrayList<Connection> mEmptyConnections = new ArrayList<Connection>(); 107 108 // mapping of phones to registered handler instances used for callbacks from RIL 109 private final HashMap<Phone, CallManagerHandler> mHandlerMap = new HashMap<>(); 110 111 // default phone as the first phone registered, which is Phone obj 112 private Phone mDefaultPhone; 113 114 private boolean mSpeedUpAudioForMtCall = false; 115 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 116 //private boolean mIsEccDialing = false; 117 118 private Object mRegistrantidentifier = new Object(); 119 120 // state registrants 121 protected final RegistrantList mPreciseCallStateRegistrants 122 = new RegistrantList(); 123 124 protected final RegistrantList mNewRingingConnectionRegistrants 125 = new RegistrantList(); 126 127 protected final RegistrantList mIncomingRingRegistrants 128 = new RegistrantList(); 129 130 protected final RegistrantList mDisconnectRegistrants 131 = new RegistrantList(); 132 133 protected final RegistrantList mMmiRegistrants 134 = new RegistrantList(); 135 136 protected final RegistrantList mUnknownConnectionRegistrants 137 = new RegistrantList(); 138 139 protected final RegistrantList mRingbackToneRegistrants 140 = new RegistrantList(); 141 142 protected final RegistrantList mOnHoldToneRegistrants 143 = new RegistrantList(); 144 145 protected final RegistrantList mInCallVoicePrivacyOnRegistrants 146 = new RegistrantList(); 147 148 protected final RegistrantList mInCallVoicePrivacyOffRegistrants 149 = new RegistrantList(); 150 151 protected final RegistrantList mCallWaitingRegistrants 152 = new RegistrantList(); 153 154 protected final RegistrantList mDisplayInfoRegistrants 155 = new RegistrantList(); 156 157 protected final RegistrantList mSignalInfoRegistrants 158 = new RegistrantList(); 159 160 protected final RegistrantList mCdmaOtaStatusChangeRegistrants 161 = new RegistrantList(); 162 163 protected final RegistrantList mResendIncallMuteRegistrants 164 = new RegistrantList(); 165 166 protected final RegistrantList mMmiInitiateRegistrants 167 = new RegistrantList(); 168 169 protected final RegistrantList mMmiCompleteRegistrants 170 = new RegistrantList(); 171 172 protected final RegistrantList mEcmTimerResetRegistrants 173 = new RegistrantList(); 174 175 protected final RegistrantList mSubscriptionInfoReadyRegistrants 176 = new RegistrantList(); 177 178 protected final RegistrantList mSuppServiceFailedRegistrants 179 = new RegistrantList(); 180 181 protected final RegistrantList mServiceStateChangedRegistrants 182 = new RegistrantList(); 183 184 protected final RegistrantList mPostDialCharacterRegistrants 185 = new RegistrantList(); 186 187 protected final RegistrantList mTtyModeReceivedRegistrants 188 = new RegistrantList(); 189 190 private CallManager() { 191 mPhones = new ArrayList<Phone>(); 192 mRingingCalls = new ArrayList<Call>(); 193 mBackgroundCalls = new ArrayList<Call>(); 194 mForegroundCalls = new ArrayList<Call>(); 195 mDefaultPhone = null; 196 } 197 198 /** 199 * get singleton instance of CallManager 200 * @return CallManager 201 */ 202 public static CallManager getInstance() { 203 return INSTANCE; 204 } 205 206 /** 207 * Returns all the registered phone objects. 208 * @return all the registered phone objects. 209 */ 210 public List<Phone> getAllPhones() { 211 return Collections.unmodifiableList(mPhones); 212 } 213 214 /** 215 * get Phone object corresponds to subId 216 * @return Phone 217 */ 218 private Phone getPhone(int subId) { 219 Phone p = null; 220 for (Phone phone : mPhones) { 221 if (phone.getSubId() == subId && !(phone instanceof ImsPhone)) { 222 p = phone; 223 break; 224 } 225 } 226 return p; 227 } 228 229 /** 230 * Get current coarse-grained voice call state. 231 * If the Call Manager has an active call and call waiting occurs, 232 * then the phone state is RINGING not OFFHOOK 233 * 234 */ 235 public PhoneConstants.State getState() { 236 PhoneConstants.State s = PhoneConstants.State.IDLE; 237 238 for (Phone phone : mPhones) { 239 if (phone.getState() == PhoneConstants.State.RINGING) { 240 s = PhoneConstants.State.RINGING; 241 } else if (phone.getState() == PhoneConstants.State.OFFHOOK) { 242 if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK; 243 } 244 } 245 return s; 246 } 247 248 /** 249 * Get current coarse-grained voice call state on a subId. 250 * If the Call Manager has an active call and call waiting occurs, 251 * then the phone state is RINGING not OFFHOOK 252 * 253 */ 254 public PhoneConstants.State getState(int subId) { 255 PhoneConstants.State s = PhoneConstants.State.IDLE; 256 257 for (Phone phone : mPhones) { 258 if (phone.getSubId() == subId) { 259 if (phone.getState() == PhoneConstants.State.RINGING) { 260 s = PhoneConstants.State.RINGING; 261 } else if (phone.getState() == PhoneConstants.State.OFFHOOK) { 262 if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK; 263 } 264 } 265 } 266 return s; 267 } 268 269 /** 270 * @return the service state of CallManager, which represents the 271 * highest priority state of all the service states of phones 272 * 273 * The priority is defined as 274 * 275 * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF 276 * 277 */ 278 279 public int getServiceState() { 280 int resultState = ServiceState.STATE_OUT_OF_SERVICE; 281 282 for (Phone phone : mPhones) { 283 int serviceState = phone.getServiceState().getState(); 284 if (serviceState == ServiceState.STATE_IN_SERVICE) { 285 // IN_SERVICE has the highest priority 286 resultState = serviceState; 287 break; 288 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) { 289 // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF 290 // Note: EMERGENCY_ONLY is not in use at this moment 291 if ( resultState == ServiceState.STATE_EMERGENCY_ONLY || 292 resultState == ServiceState.STATE_POWER_OFF) { 293 resultState = serviceState; 294 } 295 } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) { 296 if (resultState == ServiceState.STATE_POWER_OFF) { 297 resultState = serviceState; 298 } 299 } 300 } 301 return resultState; 302 } 303 304 /** 305 * @return the Phone service state corresponds to subId 306 */ 307 public int getServiceState(int subId) { 308 int resultState = ServiceState.STATE_OUT_OF_SERVICE; 309 310 for (Phone phone : mPhones) { 311 if (phone.getSubId() == subId) { 312 int serviceState = phone.getServiceState().getState(); 313 if (serviceState == ServiceState.STATE_IN_SERVICE) { 314 // IN_SERVICE has the highest priority 315 resultState = serviceState; 316 break; 317 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) { 318 // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF 319 // Note: EMERGENCY_ONLY is not in use at this moment 320 if ( resultState == ServiceState.STATE_EMERGENCY_ONLY || 321 resultState == ServiceState.STATE_POWER_OFF) { 322 resultState = serviceState; 323 } 324 } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) { 325 if (resultState == ServiceState.STATE_POWER_OFF) { 326 resultState = serviceState; 327 } 328 } 329 } 330 } 331 return resultState; 332 } 333 334 /** 335 * @return the phone associated with any call 336 */ 337 public Phone getPhoneInCall() { 338 Phone phone = null; 339 if (!getFirstActiveRingingCall().isIdle()) { 340 phone = getFirstActiveRingingCall().getPhone(); 341 } else if (!getActiveFgCall().isIdle()) { 342 phone = getActiveFgCall().getPhone(); 343 } else { 344 // If BG call is idle, we return default phone 345 phone = getFirstActiveBgCall().getPhone(); 346 } 347 return phone; 348 } 349 350 public Phone getPhoneInCall(int subId) { 351 Phone phone = null; 352 if (!getFirstActiveRingingCall(subId).isIdle()) { 353 phone = getFirstActiveRingingCall(subId).getPhone(); 354 } else if (!getActiveFgCall(subId).isIdle()) { 355 phone = getActiveFgCall(subId).getPhone(); 356 } else { 357 // If BG call is idle, we return default phone 358 phone = getFirstActiveBgCall(subId).getPhone(); 359 } 360 return phone; 361 } 362 363 /** 364 * Register phone to CallManager 365 * @param phone to be registered 366 * @return true if register successfully 367 */ 368 public boolean registerPhone(Phone phone) { 369 if (phone != null && !mPhones.contains(phone)) { 370 371 if (DBG) { 372 Rlog.d(LOG_TAG, "registerPhone(" + 373 phone.getPhoneName() + " " + phone + ")"); 374 } 375 376 if (mPhones.isEmpty()) { 377 mDefaultPhone = phone; 378 } 379 mPhones.add(phone); 380 mRingingCalls.add(phone.getRingingCall()); 381 mBackgroundCalls.add(phone.getBackgroundCall()); 382 mForegroundCalls.add(phone.getForegroundCall()); 383 registerForPhoneStates(phone); 384 return true; 385 } 386 return false; 387 } 388 389 /** 390 * unregister phone from CallManager 391 * @param phone to be unregistered 392 */ 393 public void unregisterPhone(Phone phone) { 394 if (phone != null && mPhones.contains(phone)) { 395 396 if (DBG) { 397 Rlog.d(LOG_TAG, "unregisterPhone(" + 398 phone.getPhoneName() + " " + phone + ")"); 399 } 400 401 Phone imsPhone = phone.getImsPhone(); 402 if (imsPhone != null) { 403 unregisterPhone(imsPhone); 404 } 405 406 mPhones.remove(phone); 407 mRingingCalls.remove(phone.getRingingCall()); 408 mBackgroundCalls.remove(phone.getBackgroundCall()); 409 mForegroundCalls.remove(phone.getForegroundCall()); 410 unregisterForPhoneStates(phone); 411 if (phone == mDefaultPhone) { 412 if (mPhones.isEmpty()) { 413 mDefaultPhone = null; 414 } else { 415 mDefaultPhone = mPhones.get(0); 416 } 417 } 418 } 419 } 420 421 /** 422 * return the default phone or null if no phone available 423 */ 424 public Phone getDefaultPhone() { 425 return mDefaultPhone; 426 } 427 428 /** 429 * @return the phone associated with the foreground call 430 */ 431 public Phone getFgPhone() { 432 return getActiveFgCall().getPhone(); 433 } 434 435 /** 436 * @return the phone associated with the foreground call 437 * of a particular subId 438 */ 439 public Phone getFgPhone(int subId) { 440 return getActiveFgCall(subId).getPhone(); 441 } 442 443 /** 444 * @return the phone associated with the background call 445 */ 446 public Phone getBgPhone() { 447 return getFirstActiveBgCall().getPhone(); 448 } 449 450 /** 451 * @return the phone associated with the background call 452 * of a particular subId 453 */ 454 public Phone getBgPhone(int subId) { 455 return getFirstActiveBgCall(subId).getPhone(); 456 } 457 458 /** 459 * @return the phone associated with the ringing call 460 */ 461 public Phone getRingingPhone() { 462 return getFirstActiveRingingCall().getPhone(); 463 } 464 465 /** 466 * @return the phone associated with the ringing call 467 * of a particular subId 468 */ 469 public Phone getRingingPhone(int subId) { 470 return getFirstActiveRingingCall(subId).getPhone(); 471 } 472 473 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 474 public void setAudioMode() { 475 Context context = getContext(); 476 if (context == null) return; 477 AudioManager audioManager = (AudioManager) 478 context.getSystemService(Context.AUDIO_SERVICE); 479 480 if (!isServiceStateInService() && !mIsEccDialing) { 481 if (audioManager.getMode() != AudioManager.MODE_NORMAL) { 482 if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus"); 483 // abandon audio focus after the mode has been set back to normal 484 audioManager.abandonAudioFocusForCall(); 485 audioManager.setMode(AudioManager.MODE_NORMAL); 486 } 487 return; 488 } 489 490 // change the audio mode and request/abandon audio focus according to phone state, 491 // but only on audio mode transitions 492 switch (getState()) { 493 case RINGING: 494 int curAudioMode = audioManager.getMode(); 495 if (curAudioMode != AudioManager.MODE_RINGTONE) { 496 if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_RING"); 497 audioManager.requestAudioFocusForCall(AudioManager.STREAM_RING, 498 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 499 if(!mSpeedUpAudioForMtCall) { 500 audioManager.setMode(AudioManager.MODE_RINGTONE); 501 } 502 } 503 504 if (mSpeedUpAudioForMtCall && (curAudioMode != AudioManager.MODE_IN_CALL)) { 505 audioManager.setMode(AudioManager.MODE_IN_CALL); 506 } 507 break; 508 case OFFHOOK: 509 Phone offhookPhone = getFgPhone(); 510 if (getActiveFgCallState() == Call.State.IDLE) { 511 // There is no active Fg calls, the OFFHOOK state 512 // is set by the Bg call. So set the phone to bgPhone. 513 offhookPhone = getBgPhone(); 514 } 515 516 int newAudioMode = AudioManager.MODE_IN_CALL; 517 if (offhookPhone instanceof SipPhone) { 518 Rlog.d(LOG_TAG, "setAudioMode Set audio mode for SIP call!"); 519 // enable IN_COMMUNICATION audio mode instead for sipPhone 520 newAudioMode = AudioManager.MODE_IN_COMMUNICATION; 521 } 522 int currMode = audioManager.getMode(); 523 if (currMode != newAudioMode || mSpeedUpAudioForMtCall) { 524 // request audio focus before setting the new mode 525 if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_VOICE_CALL"); 526 audioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, 527 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 528 Rlog.d(LOG_TAG, "setAudioMode Setting audio mode from " 529 + currMode + " to " + newAudioMode); 530 audioManager.setMode(newAudioMode); 531 } 532 mSpeedUpAudioForMtCall = false; 533 break; 534 case IDLE: 535 if (audioManager.getMode() != AudioManager.MODE_NORMAL) { 536 audioManager.setMode(AudioManager.MODE_NORMAL); 537 if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus"); 538 // abandon audio focus after the mode has been set back to normal 539 audioManager.abandonAudioFocusForCall(); 540 } 541 mSpeedUpAudioForMtCall = false; 542 break; 543 } 544 Rlog.d(LOG_TAG, "setAudioMode state = " + getState()); 545 } 546 */ 547 548 private Context getContext() { 549 Phone defaultPhone = getDefaultPhone(); 550 return ((defaultPhone == null) ? null : defaultPhone.getContext()); 551 } 552 553 public Object getRegistrantIdentifier() { 554 return mRegistrantidentifier; 555 } 556 557 private void registerForPhoneStates(Phone phone) { 558 // We need to keep a mapping of handler to Phone for proper unregistration. 559 // TODO: Clean up this solution as it is just a work around for each Phone instance 560 // using the same Handler to register with the RIL. When time permits, we should consider 561 // moving the handler (or the reference ot the handler) into the Phone object. 562 // See b/17414427. 563 CallManagerHandler handler = mHandlerMap.get(phone); 564 if (handler != null) { 565 Rlog.d(LOG_TAG, "This phone has already been registered."); 566 return; 567 } 568 569 // New registration, create a new handler instance and register the phone. 570 handler = new CallManagerHandler(); 571 mHandlerMap.put(phone, handler); 572 573 // for common events supported by all phones 574 // The mRegistrantIdentifier passed here, is to identify in the Phone 575 // that the registrants are coming from the CallManager. 576 phone.registerForPreciseCallStateChanged(handler, EVENT_PRECISE_CALL_STATE_CHANGED, 577 mRegistrantidentifier); 578 phone.registerForDisconnect(handler, EVENT_DISCONNECT, 579 mRegistrantidentifier); 580 phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION, 581 mRegistrantidentifier); 582 phone.registerForUnknownConnection(handler, EVENT_UNKNOWN_CONNECTION, 583 mRegistrantidentifier); 584 phone.registerForIncomingRing(handler, EVENT_INCOMING_RING, 585 mRegistrantidentifier); 586 phone.registerForRingbackTone(handler, EVENT_RINGBACK_TONE, 587 mRegistrantidentifier); 588 phone.registerForInCallVoicePrivacyOn(handler, EVENT_IN_CALL_VOICE_PRIVACY_ON, 589 mRegistrantidentifier); 590 phone.registerForInCallVoicePrivacyOff(handler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, 591 mRegistrantidentifier); 592 phone.registerForDisplayInfo(handler, EVENT_DISPLAY_INFO, 593 mRegistrantidentifier); 594 phone.registerForSignalInfo(handler, EVENT_SIGNAL_INFO, 595 mRegistrantidentifier); 596 phone.registerForResendIncallMute(handler, EVENT_RESEND_INCALL_MUTE, 597 mRegistrantidentifier); 598 phone.registerForMmiInitiate(handler, EVENT_MMI_INITIATE, 599 mRegistrantidentifier); 600 phone.registerForMmiComplete(handler, EVENT_MMI_COMPLETE, 601 mRegistrantidentifier); 602 phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, 603 mRegistrantidentifier); 604 phone.registerForServiceStateChanged(handler, EVENT_SERVICE_STATE_CHANGED, 605 mRegistrantidentifier); 606 607 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 608 //phone.registerForRadioOffOrNotAvailable(handler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 609 610 // for events supported only by GSM, CDMA and IMS phone 611 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM || 612 phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA || 613 phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 614 phone.setOnPostDialCharacter(handler, EVENT_POST_DIAL_CHARACTER, null); 615 } 616 617 // for events supported only by CDMA phone 618 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){ 619 phone.registerForCdmaOtaStatusChange(handler, EVENT_CDMA_OTA_STATUS_CHANGE, null); 620 phone.registerForSubscriptionInfoReady(handler, EVENT_SUBSCRIPTION_INFO_READY, null); 621 phone.registerForCallWaiting(handler, EVENT_CALL_WAITING, null); 622 phone.registerForEcmTimerReset(handler, EVENT_ECM_TIMER_RESET, null); 623 } 624 625 // for events supported only by IMS phone 626 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 627 phone.registerForOnHoldTone(handler, EVENT_ONHOLD_TONE, null); 628 phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, null); 629 phone.registerForTtyModeReceived(handler, EVENT_TTY_MODE_RECEIVED, null); 630 } 631 } 632 633 private void unregisterForPhoneStates(Phone phone) { 634 // Make sure that we clean up our map of handlers to Phones. 635 CallManagerHandler handler = mHandlerMap.get(phone); 636 if (handler != null) { 637 Rlog.e(LOG_TAG, "Could not find Phone handler for unregistration"); 638 return; 639 } 640 mHandlerMap.remove(phone); 641 642 // for common events supported by all phones 643 phone.unregisterForPreciseCallStateChanged(handler); 644 phone.unregisterForDisconnect(handler); 645 phone.unregisterForNewRingingConnection(handler); 646 phone.unregisterForUnknownConnection(handler); 647 phone.unregisterForIncomingRing(handler); 648 phone.unregisterForRingbackTone(handler); 649 phone.unregisterForInCallVoicePrivacyOn(handler); 650 phone.unregisterForInCallVoicePrivacyOff(handler); 651 phone.unregisterForDisplayInfo(handler); 652 phone.unregisterForSignalInfo(handler); 653 phone.unregisterForResendIncallMute(handler); 654 phone.unregisterForMmiInitiate(handler); 655 phone.unregisterForMmiComplete(handler); 656 phone.unregisterForSuppServiceFailed(handler); 657 phone.unregisterForServiceStateChanged(handler); 658 phone.unregisterForTtyModeReceived(handler); 659 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 660 //phone.unregisterForRadioOffOrNotAvailable(handler); 661 662 // for events supported only by GSM, CDMA and IMS phone 663 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM || 664 phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA || 665 phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 666 phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null); 667 } 668 669 // for events supported only by CDMA phone 670 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){ 671 phone.unregisterForCdmaOtaStatusChange(handler); 672 phone.unregisterForSubscriptionInfoReady(handler); 673 phone.unregisterForCallWaiting(handler); 674 phone.unregisterForEcmTimerReset(handler); 675 } 676 677 // for events supported only by IMS phone 678 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) { 679 phone.unregisterForOnHoldTone(handler); 680 phone.unregisterForSuppServiceFailed(handler); 681 } 682 } 683 684 /** 685 * Answers a ringing or waiting call. 686 * 687 * Active call, if any, go on hold. 688 * If active call can't be held, i.e., a background call of the same channel exists, 689 * the active call will be hang up. 690 * 691 * Answering occurs asynchronously, and final notification occurs via 692 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 693 * java.lang.Object) registerForPreciseCallStateChanged()}. 694 * 695 * @exception CallStateException when call is not ringing or waiting 696 */ 697 public void acceptCall(Call ringingCall) throws CallStateException { 698 Phone ringingPhone = ringingCall.getPhone(); 699 700 if (VDBG) { 701 Rlog.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")"); 702 Rlog.d(LOG_TAG, toString()); 703 } 704 705 if ( hasActiveFgCall() ) { 706 Phone activePhone = getActiveFgCall().getPhone(); 707 boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle()); 708 boolean sameChannel = (activePhone == ringingPhone); 709 710 if (VDBG) { 711 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel); 712 } 713 714 if (sameChannel && hasBgCall) { 715 getActiveFgCall().hangup(); 716 } else if (!sameChannel && !hasBgCall) { 717 activePhone.switchHoldingAndActive(); 718 } else if (!sameChannel && hasBgCall) { 719 getActiveFgCall().hangup(); 720 } 721 } 722 723 // We only support the AUDIO_ONLY video state in this scenario. 724 ringingPhone.acceptCall(VideoProfile.STATE_AUDIO_ONLY); 725 726 if (VDBG) { 727 Rlog.d(LOG_TAG, "End acceptCall(" +ringingCall + ")"); 728 Rlog.d(LOG_TAG, toString()); 729 } 730 } 731 732 /** 733 * Reject (ignore) a ringing call. In GSM, this means UDUB 734 * (User Determined User Busy). Reject occurs asynchronously, 735 * and final notification occurs via 736 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 737 * java.lang.Object) registerForPreciseCallStateChanged()}. 738 * 739 * @exception CallStateException when no call is ringing or waiting 740 */ 741 public void rejectCall(Call ringingCall) throws CallStateException { 742 if (VDBG) { 743 Rlog.d(LOG_TAG, "rejectCall(" +ringingCall + ")"); 744 Rlog.d(LOG_TAG, toString()); 745 } 746 747 Phone ringingPhone = ringingCall.getPhone(); 748 749 ringingPhone.rejectCall(); 750 751 if (VDBG) { 752 Rlog.d(LOG_TAG, "End rejectCall(" +ringingCall + ")"); 753 Rlog.d(LOG_TAG, toString()); 754 } 755 } 756 757 /** 758 * Places active call on hold, and makes held call active. 759 * Switch occurs asynchronously and may fail. 760 * 761 * There are 4 scenarios 762 * 1. only active call but no held call, aka, hold 763 * 2. no active call but only held call, aka, unhold 764 * 3. both active and held calls from same phone, aka, swap 765 * 4. active and held calls from different phones, aka, phone swap 766 * 767 * Final notification occurs via 768 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 769 * java.lang.Object) registerForPreciseCallStateChanged()}. 770 * 771 * @exception CallStateException if active call is ringing, waiting, or 772 * dialing/alerting, or heldCall can't be active. 773 * In these cases, this operation may not be performed. 774 */ 775 public void switchHoldingAndActive(Call heldCall) throws CallStateException { 776 Phone activePhone = null; 777 Phone heldPhone = null; 778 779 if (VDBG) { 780 Rlog.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")"); 781 Rlog.d(LOG_TAG, toString()); 782 } 783 784 if (hasActiveFgCall()) { 785 activePhone = getActiveFgCall().getPhone(); 786 } 787 788 if (heldCall != null) { 789 heldPhone = heldCall.getPhone(); 790 } 791 792 if (activePhone != null) { 793 activePhone.switchHoldingAndActive(); 794 } 795 796 if (heldPhone != null && heldPhone != activePhone) { 797 heldPhone.switchHoldingAndActive(); 798 } 799 800 if (VDBG) { 801 Rlog.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")"); 802 Rlog.d(LOG_TAG, toString()); 803 } 804 } 805 806 /** 807 * Hangup foreground call and resume the specific background call 808 * 809 * Note: this is noop if there is no foreground call or the heldCall is null 810 * 811 * @param heldCall to become foreground 812 * @throws CallStateException 813 */ 814 public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException { 815 Phone foregroundPhone = null; 816 Phone backgroundPhone = null; 817 818 if (VDBG) { 819 Rlog.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")"); 820 Rlog.d(LOG_TAG, toString()); 821 } 822 823 if (hasActiveFgCall()) { 824 foregroundPhone = getFgPhone(); 825 if (heldCall != null) { 826 backgroundPhone = heldCall.getPhone(); 827 if (foregroundPhone == backgroundPhone) { 828 getActiveFgCall().hangup(); 829 } else { 830 // the call to be hangup and resumed belongs to different phones 831 getActiveFgCall().hangup(); 832 switchHoldingAndActive(heldCall); 833 } 834 } 835 } 836 837 if (VDBG) { 838 Rlog.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")"); 839 Rlog.d(LOG_TAG, toString()); 840 } 841 } 842 843 /** 844 * Whether or not the phone can conference in the current phone 845 * state--that is, one call holding and one call active. 846 * @return true if the phone can conference; false otherwise. 847 */ 848 public boolean canConference(Call heldCall) { 849 Phone activePhone = null; 850 Phone heldPhone = null; 851 852 if (hasActiveFgCall()) { 853 activePhone = getActiveFgCall().getPhone(); 854 } 855 856 if (heldCall != null) { 857 heldPhone = heldCall.getPhone(); 858 } 859 860 return heldPhone.getClass().equals(activePhone.getClass()); 861 } 862 863 /** 864 * Whether or not the phone can conference in the current phone 865 * state--that is, one call holding and one call active. 866 * This method consider the phone object which is specific 867 * to the provided subId. 868 * @return true if the phone can conference; false otherwise. 869 */ 870 public boolean canConference(Call heldCall, int subId) { 871 Phone activePhone = null; 872 Phone heldPhone = null; 873 874 if (hasActiveFgCall(subId)) { 875 activePhone = getActiveFgCall(subId).getPhone(); 876 } 877 878 if (heldCall != null) { 879 heldPhone = heldCall.getPhone(); 880 } 881 882 return heldPhone.getClass().equals(activePhone.getClass()); 883 } 884 885 /** 886 * Conferences holding and active. Conference occurs asynchronously 887 * and may fail. Final notification occurs via 888 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 889 * java.lang.Object) registerForPreciseCallStateChanged()}. 890 * 891 * @exception CallStateException if canConference() would return false. 892 * In these cases, this operation may not be performed. 893 */ 894 public void conference(Call heldCall) throws CallStateException { 895 int subId = heldCall.getPhone().getSubId(); 896 897 if (VDBG) { 898 Rlog.d(LOG_TAG, "conference(" +heldCall + ")"); 899 Rlog.d(LOG_TAG, toString()); 900 } 901 902 Phone fgPhone = getFgPhone(subId); 903 if (fgPhone != null) { 904 if (fgPhone instanceof SipPhone) { 905 ((SipPhone) fgPhone).conference(heldCall); 906 } else if (canConference(heldCall)) { 907 fgPhone.conference(); 908 } else { 909 throw(new CallStateException("Can't conference foreground and selected background call")); 910 } 911 } else { 912 Rlog.d(LOG_TAG, "conference: fgPhone=null"); 913 } 914 915 if (VDBG) { 916 Rlog.d(LOG_TAG, "End conference(" +heldCall + ")"); 917 Rlog.d(LOG_TAG, toString()); 918 } 919 920 } 921 922 /** 923 * Initiate a new voice connection. This happens asynchronously, so you 924 * cannot assume the audio path is connected (or a call index has been 925 * assigned) until PhoneStateChanged notification has occurred. 926 * 927 * @exception CallStateException if a new outgoing call is not currently 928 * possible because no more call slots exist or a call exists that is 929 * dialing, alerting, ringing, or waiting. Other errors are 930 * handled asynchronously. 931 */ 932 public Connection dial(Phone phone, String dialString, int videoState) 933 throws CallStateException { 934 int subId = phone.getSubId(); 935 Connection result; 936 937 if (VDBG) { 938 Rlog.d(LOG_TAG, " dial(" + phone + ", "+ dialString + ")" + 939 " subId = " + subId); 940 Rlog.d(LOG_TAG, toString()); 941 } 942 943 if (!canDial(phone)) { 944 /* 945 * canDial function only checks whether the phone can make a new call. 946 * InCall MMI commmands are basically supplementary services 947 * within a call eg: call hold, call deflection, explicit call transfer etc. 948 */ 949 String newDialString = PhoneNumberUtils.stripSeparators(dialString); 950 if (phone.handleInCallMmiCommands(newDialString)) { 951 return null; 952 } else { 953 throw new CallStateException("cannot dial in current state"); 954 } 955 } 956 957 if ( hasActiveFgCall(subId) ) { 958 Phone activePhone = getActiveFgCall(subId).getPhone(); 959 boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle()); 960 961 if (DBG) { 962 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == phone)); 963 } 964 965 // Manipulation between IMS phone and its owner 966 // will be treated in GSM/CDMA phone. 967 Phone imsPhone = phone.getImsPhone(); 968 if (activePhone != phone 969 && (imsPhone == null || imsPhone != activePhone)) { 970 if (hasBgCall) { 971 Rlog.d(LOG_TAG, "Hangup"); 972 getActiveFgCall(subId).hangup(); 973 } else { 974 Rlog.d(LOG_TAG, "Switch"); 975 activePhone.switchHoldingAndActive(); 976 } 977 } 978 } 979 980 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 981 //mIsEccDialing = PhoneNumberUtils.isEmergencyNumber(dialString); 982 983 result = phone.dial(dialString, videoState); 984 985 if (VDBG) { 986 Rlog.d(LOG_TAG, "End dial(" + phone + ", "+ dialString + ")"); 987 Rlog.d(LOG_TAG, toString()); 988 } 989 990 return result; 991 } 992 993 /** 994 * Initiate a new voice connection. This happens asynchronously, so you 995 * cannot assume the audio path is connected (or a call index has been 996 * assigned) until PhoneStateChanged notification has occurred. 997 * 998 * @exception CallStateException if a new outgoing call is not currently 999 * possible because no more call slots exist or a call exists that is 1000 * dialing, alerting, ringing, or waiting. Other errors are 1001 * handled asynchronously. 1002 */ 1003 public Connection dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState) 1004 throws CallStateException { 1005 return phone.dial(dialString, uusInfo, videoState, null); 1006 } 1007 1008 /** 1009 * clear disconnect connection for each phone 1010 */ 1011 public void clearDisconnected() { 1012 for(Phone phone : mPhones) { 1013 phone.clearDisconnected(); 1014 } 1015 } 1016 1017 /** 1018 * clear disconnect connection for a phone specific 1019 * to the provided subId 1020 */ 1021 public void clearDisconnected(int subId) { 1022 for(Phone phone : mPhones) { 1023 if (phone.getSubId() == subId) { 1024 phone.clearDisconnected(); 1025 } 1026 } 1027 } 1028 1029 /** 1030 * Phone can make a call only if ALL of the following are true: 1031 * - Phone is not powered off 1032 * - There's no incoming or waiting call 1033 * - The foreground call is ACTIVE or IDLE or DISCONNECTED. 1034 * (We mainly need to make sure it *isn't* DIALING or ALERTING.) 1035 * @param phone 1036 * @return true if the phone can make a new call 1037 */ 1038 private boolean canDial(Phone phone) { 1039 int serviceState = phone.getServiceState().getState(); 1040 int subId = phone.getSubId(); 1041 boolean hasRingingCall = hasActiveRingingCall(); 1042 Call.State fgCallState = getActiveFgCallState(subId); 1043 1044 boolean result = (serviceState != ServiceState.STATE_POWER_OFF 1045 && !hasRingingCall 1046 && ((fgCallState == Call.State.ACTIVE) 1047 || (fgCallState == Call.State.IDLE) 1048 || (fgCallState == Call.State.DISCONNECTED) 1049 /*As per 3GPP TS 51.010-1 section 31.13.1.4 1050 call should be alowed when the foreground 1051 call is in ALERTING state*/ 1052 || (fgCallState == Call.State.ALERTING))); 1053 1054 if (result == false) { 1055 Rlog.d(LOG_TAG, "canDial serviceState=" + serviceState 1056 + " hasRingingCall=" + hasRingingCall 1057 + " fgCallState=" + fgCallState); 1058 } 1059 return result; 1060 } 1061 1062 /** 1063 * Whether or not the phone can do explicit call transfer in the current 1064 * phone state--that is, one call holding and one call active. 1065 * @return true if the phone can do explicit call transfer; false otherwise. 1066 */ 1067 public boolean canTransfer(Call heldCall) { 1068 Phone activePhone = null; 1069 Phone heldPhone = null; 1070 1071 if (hasActiveFgCall()) { 1072 activePhone = getActiveFgCall().getPhone(); 1073 } 1074 1075 if (heldCall != null) { 1076 heldPhone = heldCall.getPhone(); 1077 } 1078 1079 return (heldPhone == activePhone && activePhone.canTransfer()); 1080 } 1081 1082 /** 1083 * Whether or not the phone specific to subId can do explicit call transfer 1084 * in the current phone state--that is, one call holding and one call active. 1085 * @return true if the phone can do explicit call transfer; false otherwise. 1086 */ 1087 public boolean canTransfer(Call heldCall, int subId) { 1088 Phone activePhone = null; 1089 Phone heldPhone = null; 1090 1091 if (hasActiveFgCall(subId)) { 1092 activePhone = getActiveFgCall(subId).getPhone(); 1093 } 1094 1095 if (heldCall != null) { 1096 heldPhone = heldCall.getPhone(); 1097 } 1098 1099 return (heldPhone == activePhone && activePhone.canTransfer()); 1100 } 1101 1102 /** 1103 * Connects the held call and active call 1104 * Disconnects the subscriber from both calls 1105 * 1106 * Explicit Call Transfer occurs asynchronously 1107 * and may fail. Final notification occurs via 1108 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 1109 * java.lang.Object) registerForPreciseCallStateChanged()}. 1110 * 1111 * @exception CallStateException if canTransfer() would return false. 1112 * In these cases, this operation may not be performed. 1113 */ 1114 public void explicitCallTransfer(Call heldCall) throws CallStateException { 1115 if (VDBG) { 1116 Rlog.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")"); 1117 Rlog.d(LOG_TAG, toString()); 1118 } 1119 1120 if (canTransfer(heldCall)) { 1121 heldCall.getPhone().explicitCallTransfer(); 1122 } 1123 1124 if (VDBG) { 1125 Rlog.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")"); 1126 Rlog.d(LOG_TAG, toString()); 1127 } 1128 1129 } 1130 1131 /** 1132 * Returns a list of MMI codes that are pending for a phone. (They have initiated 1133 * but have not yet completed). 1134 * Presently there is only ever one. 1135 * 1136 * Use <code>registerForMmiInitiate</code> 1137 * and <code>registerForMmiComplete</code> for change notification. 1138 * @return null if phone doesn't have or support mmi code 1139 */ 1140 public List<? extends MmiCode> getPendingMmiCodes(Phone phone) { 1141 Rlog.e(LOG_TAG, "getPendingMmiCodes not implemented"); 1142 return null; 1143 } 1144 1145 /** 1146 * Sends user response to a USSD REQUEST message. An MmiCode instance 1147 * representing this response is sent to handlers registered with 1148 * registerForMmiInitiate. 1149 * 1150 * @param ussdMessge Message to send in the response. 1151 * @return false if phone doesn't support ussd service 1152 */ 1153 public boolean sendUssdResponse(Phone phone, String ussdMessge) { 1154 Rlog.e(LOG_TAG, "sendUssdResponse not implemented"); 1155 return false; 1156 } 1157 1158 /** 1159 * Mutes or unmutes the microphone for the active call. The microphone 1160 * is automatically unmuted if a call is answered, dialed, or resumed 1161 * from a holding state. 1162 * 1163 * @param muted true to mute the microphone, 1164 * false to activate the microphone. 1165 */ 1166 1167 public void setMute(boolean muted) { 1168 if (VDBG) { 1169 Rlog.d(LOG_TAG, " setMute(" + muted + ")"); 1170 Rlog.d(LOG_TAG, toString()); 1171 } 1172 1173 if (hasActiveFgCall()) { 1174 getActiveFgCall().getPhone().setMute(muted); 1175 } 1176 1177 if (VDBG) { 1178 Rlog.d(LOG_TAG, "End setMute(" + muted + ")"); 1179 Rlog.d(LOG_TAG, toString()); 1180 } 1181 } 1182 1183 /** 1184 * Gets current mute status. Use 1185 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 1186 * java.lang.Object) registerForPreciseCallStateChanged()} 1187 * as a change notifcation, although presently phone state changed is not 1188 * fired when setMute() is called. 1189 * 1190 * @return true is muting, false is unmuting 1191 */ 1192 public boolean getMute() { 1193 if (hasActiveFgCall()) { 1194 return getActiveFgCall().getPhone().getMute(); 1195 } else if (hasActiveBgCall()) { 1196 return getFirstActiveBgCall().getPhone().getMute(); 1197 } 1198 return false; 1199 } 1200 1201 /** 1202 * Enables or disables echo suppression. 1203 */ 1204 public void setEchoSuppressionEnabled() { 1205 if (VDBG) { 1206 Rlog.d(LOG_TAG, " setEchoSuppression()"); 1207 Rlog.d(LOG_TAG, toString()); 1208 } 1209 1210 if (hasActiveFgCall()) { 1211 getActiveFgCall().getPhone().setEchoSuppressionEnabled(); 1212 } 1213 1214 if (VDBG) { 1215 Rlog.d(LOG_TAG, "End setEchoSuppression()"); 1216 Rlog.d(LOG_TAG, toString()); 1217 } 1218 } 1219 1220 /** 1221 * Play a DTMF tone on the active call. 1222 * 1223 * @param c should be one of 0-9, '*' or '#'. Other values will be 1224 * silently ignored. 1225 * @return false if no active call or the active call doesn't support 1226 * dtmf tone 1227 */ 1228 public boolean sendDtmf(char c) { 1229 boolean result = false; 1230 1231 if (VDBG) { 1232 Rlog.d(LOG_TAG, " sendDtmf(" + c + ")"); 1233 Rlog.d(LOG_TAG, toString()); 1234 } 1235 1236 if (hasActiveFgCall()) { 1237 getActiveFgCall().getPhone().sendDtmf(c); 1238 result = true; 1239 } 1240 1241 if (VDBG) { 1242 Rlog.d(LOG_TAG, "End sendDtmf(" + c + ")"); 1243 Rlog.d(LOG_TAG, toString()); 1244 } 1245 return result; 1246 } 1247 1248 /** 1249 * Start to paly a DTMF tone on the active call. 1250 * or there is a playing DTMF tone. 1251 * @param c should be one of 0-9, '*' or '#'. Other values will be 1252 * silently ignored. 1253 * 1254 * @return false if no active call or the active call doesn't support 1255 * dtmf tone 1256 */ 1257 public boolean startDtmf(char c) { 1258 boolean result = false; 1259 1260 if (VDBG) { 1261 Rlog.d(LOG_TAG, " startDtmf(" + c + ")"); 1262 Rlog.d(LOG_TAG, toString()); 1263 } 1264 1265 if (hasActiveFgCall()) { 1266 getActiveFgCall().getPhone().startDtmf(c); 1267 result = true; 1268 } 1269 1270 if (VDBG) { 1271 Rlog.d(LOG_TAG, "End startDtmf(" + c + ")"); 1272 Rlog.d(LOG_TAG, toString()); 1273 } 1274 1275 return result; 1276 } 1277 1278 /** 1279 * Stop the playing DTMF tone. Ignored if there is no playing DTMF 1280 * tone or no active call. 1281 */ 1282 public void stopDtmf() { 1283 if (VDBG) { 1284 Rlog.d(LOG_TAG, " stopDtmf()" ); 1285 Rlog.d(LOG_TAG, toString()); 1286 } 1287 1288 if (hasActiveFgCall()) getFgPhone().stopDtmf(); 1289 1290 if (VDBG) { 1291 Rlog.d(LOG_TAG, "End stopDtmf()"); 1292 Rlog.d(LOG_TAG, toString()); 1293 } 1294 } 1295 1296 /** 1297 * send burst DTMF tone, it can send the string as single character or multiple character 1298 * ignore if there is no active call or not valid digits string. 1299 * Valid digit means only includes characters ISO-LATIN characters 0-9, *, # 1300 * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character, 1301 * this api can send single character and multiple character, also, this api has response 1302 * back to caller. 1303 * 1304 * @param dtmfString is string representing the dialing digit(s) in the active call 1305 * @param on the DTMF ON length in milliseconds, or 0 for default 1306 * @param off the DTMF OFF length in milliseconds, or 0 for default 1307 * @param onComplete is the callback message when the action is processed by BP 1308 * 1309 */ 1310 public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 1311 if (hasActiveFgCall()) { 1312 getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete); 1313 return true; 1314 } 1315 return false; 1316 } 1317 1318 /** 1319 * Notifies when a voice connection has disconnected, either due to local 1320 * or remote hangup or error. 1321 * 1322 * Messages received from this will have the following members:<p> 1323 * <ul><li>Message.obj will be an AsyncResult</li> 1324 * <li>AsyncResult.userObj = obj</li> 1325 * <li>AsyncResult.result = a Connection object that is 1326 * no longer connected.</li></ul> 1327 */ 1328 public void registerForDisconnect(Handler h, int what, Object obj) { 1329 mDisconnectRegistrants.addUnique(h, what, obj); 1330 } 1331 1332 /** 1333 * Unregisters for voice disconnection notification. 1334 * Extraneous calls are tolerated silently 1335 */ 1336 public void unregisterForDisconnect(Handler h){ 1337 mDisconnectRegistrants.remove(h); 1338 } 1339 1340 /** 1341 * Register for getting notifications for change in the Call State {@link Call.State} 1342 * This is called PreciseCallState because the call state is more precise than what 1343 * can be obtained using the {@link PhoneStateListener} 1344 * 1345 * Resulting events will have an AsyncResult in <code>Message.obj</code>. 1346 * AsyncResult.userData will be set to the obj argument here. 1347 * The <em>h</em> parameter is held only by a weak reference. 1348 */ 1349 public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){ 1350 mPreciseCallStateRegistrants.addUnique(h, what, obj); 1351 } 1352 1353 /** 1354 * Unregisters for voice call state change notifications. 1355 * Extraneous calls are tolerated silently. 1356 */ 1357 public void unregisterForPreciseCallStateChanged(Handler h){ 1358 mPreciseCallStateRegistrants.remove(h); 1359 } 1360 1361 /** 1362 * Notifies when a previously untracked non-ringing/waiting connection has appeared. 1363 * This is likely due to some other entity (eg, SIM card application) initiating a call. 1364 */ 1365 public void registerForUnknownConnection(Handler h, int what, Object obj){ 1366 mUnknownConnectionRegistrants.addUnique(h, what, obj); 1367 } 1368 1369 /** 1370 * Unregisters for unknown connection notifications. 1371 */ 1372 public void unregisterForUnknownConnection(Handler h){ 1373 mUnknownConnectionRegistrants.remove(h); 1374 } 1375 1376 1377 /** 1378 * Notifies when a new ringing or waiting connection has appeared.<p> 1379 * 1380 * Messages received from this: 1381 * Message.obj will be an AsyncResult 1382 * AsyncResult.userObj = obj 1383 * AsyncResult.result = a Connection. <p> 1384 * Please check Connection.isRinging() to make sure the Connection 1385 * has not dropped since this message was posted. 1386 * If Connection.isRinging() is true, then 1387 * Connection.getCall() == Phone.getRingingCall() 1388 */ 1389 public void registerForNewRingingConnection(Handler h, int what, Object obj){ 1390 mNewRingingConnectionRegistrants.addUnique(h, what, obj); 1391 } 1392 1393 /** 1394 * Unregisters for new ringing connection notification. 1395 * Extraneous calls are tolerated silently 1396 */ 1397 1398 public void unregisterForNewRingingConnection(Handler h){ 1399 mNewRingingConnectionRegistrants.remove(h); 1400 } 1401 1402 /** 1403 * Notifies when an incoming call rings.<p> 1404 * 1405 * Messages received from this: 1406 * Message.obj will be an AsyncResult 1407 * AsyncResult.userObj = obj 1408 * AsyncResult.result = a Connection. <p> 1409 */ 1410 public void registerForIncomingRing(Handler h, int what, Object obj){ 1411 mIncomingRingRegistrants.addUnique(h, what, obj); 1412 } 1413 1414 /** 1415 * Unregisters for ring notification. 1416 * Extraneous calls are tolerated silently 1417 */ 1418 1419 public void unregisterForIncomingRing(Handler h){ 1420 mIncomingRingRegistrants.remove(h); 1421 } 1422 1423 /** 1424 * Notifies when out-band ringback tone is needed.<p> 1425 * 1426 * Messages received from this: 1427 * Message.obj will be an AsyncResult 1428 * AsyncResult.userObj = obj 1429 * AsyncResult.result = boolean, true to start play ringback tone 1430 * and false to stop. <p> 1431 */ 1432 public void registerForRingbackTone(Handler h, int what, Object obj){ 1433 mRingbackToneRegistrants.addUnique(h, what, obj); 1434 } 1435 1436 /** 1437 * Unregisters for ringback tone notification. 1438 */ 1439 1440 public void unregisterForRingbackTone(Handler h){ 1441 mRingbackToneRegistrants.remove(h); 1442 } 1443 1444 /** 1445 * Notifies when out-band on-hold tone is needed.<p> 1446 * 1447 * Messages received from this: 1448 * Message.obj will be an AsyncResult 1449 * AsyncResult.userObj = obj 1450 * AsyncResult.result = boolean, true to start play on-hold tone 1451 * and false to stop. <p> 1452 */ 1453 public void registerForOnHoldTone(Handler h, int what, Object obj){ 1454 mOnHoldToneRegistrants.addUnique(h, what, obj); 1455 } 1456 1457 /** 1458 * Unregisters for on-hold tone notification. 1459 */ 1460 1461 public void unregisterForOnHoldTone(Handler h){ 1462 mOnHoldToneRegistrants.remove(h); 1463 } 1464 1465 /** 1466 * Registers the handler to reset the uplink mute state to get 1467 * uplink audio. 1468 */ 1469 public void registerForResendIncallMute(Handler h, int what, Object obj){ 1470 mResendIncallMuteRegistrants.addUnique(h, what, obj); 1471 } 1472 1473 /** 1474 * Unregisters for resend incall mute notifications. 1475 */ 1476 public void unregisterForResendIncallMute(Handler h){ 1477 mResendIncallMuteRegistrants.remove(h); 1478 } 1479 1480 /** 1481 * Register for notifications of initiation of a new MMI code request. 1482 * MMI codes for GSM are discussed in 3GPP TS 22.030.<p> 1483 * 1484 * Example: If Phone.dial is called with "*#31#", then the app will 1485 * be notified here.<p> 1486 * 1487 * The returned <code>Message.obj</code> will contain an AsyncResult. 1488 * 1489 * <code>obj.result</code> will be an "MmiCode" object. 1490 */ 1491 public void registerForMmiInitiate(Handler h, int what, Object obj){ 1492 mMmiInitiateRegistrants.addUnique(h, what, obj); 1493 } 1494 1495 /** 1496 * Unregisters for new MMI initiate notification. 1497 * Extraneous calls are tolerated silently 1498 */ 1499 public void unregisterForMmiInitiate(Handler h){ 1500 mMmiInitiateRegistrants.remove(h); 1501 } 1502 1503 /** 1504 * Register for notifications that an MMI request has completed 1505 * its network activity and is in its final state. This may mean a state 1506 * of COMPLETE, FAILED, or CANCELLED. 1507 * 1508 * <code>Message.obj</code> will contain an AsyncResult. 1509 * <code>obj.result</code> will be an "MmiCode" object 1510 */ 1511 public void registerForMmiComplete(Handler h, int what, Object obj){ 1512 mMmiCompleteRegistrants.addUnique(h, what, obj); 1513 } 1514 1515 /** 1516 * Unregisters for MMI complete notification. 1517 * Extraneous calls are tolerated silently 1518 */ 1519 public void unregisterForMmiComplete(Handler h){ 1520 mMmiCompleteRegistrants.remove(h); 1521 } 1522 1523 /** 1524 * Registration point for Ecm timer reset 1525 * @param h handler to notify 1526 * @param what user-defined message code 1527 * @param obj placed in Message.obj 1528 */ 1529 public void registerForEcmTimerReset(Handler h, int what, Object obj){ 1530 mEcmTimerResetRegistrants.addUnique(h, what, obj); 1531 } 1532 1533 /** 1534 * Unregister for notification for Ecm timer reset 1535 * @param h Handler to be removed from the registrant list. 1536 */ 1537 public void unregisterForEcmTimerReset(Handler h){ 1538 mEcmTimerResetRegistrants.remove(h); 1539 } 1540 1541 /** 1542 * Register for ServiceState changed. 1543 * Message.obj will contain an AsyncResult. 1544 * AsyncResult.result will be a ServiceState instance 1545 */ 1546 public void registerForServiceStateChanged(Handler h, int what, Object obj){ 1547 mServiceStateChangedRegistrants.addUnique(h, what, obj); 1548 } 1549 1550 /** 1551 * Unregisters for ServiceStateChange notification. 1552 * Extraneous calls are tolerated silently 1553 */ 1554 public void unregisterForServiceStateChanged(Handler h){ 1555 mServiceStateChangedRegistrants.remove(h); 1556 } 1557 1558 /** 1559 * Register for notifications when a supplementary service attempt fails. 1560 * Message.obj will contain an AsyncResult. 1561 * 1562 * @param h Handler that receives the notification message. 1563 * @param what User-defined message code. 1564 * @param obj User object. 1565 */ 1566 public void registerForSuppServiceFailed(Handler h, int what, Object obj){ 1567 mSuppServiceFailedRegistrants.addUnique(h, what, obj); 1568 } 1569 1570 /** 1571 * Unregister for notifications when a supplementary service attempt fails. 1572 * Extraneous calls are tolerated silently 1573 * 1574 * @param h Handler to be removed from the registrant list. 1575 */ 1576 public void unregisterForSuppServiceFailed(Handler h){ 1577 mSuppServiceFailedRegistrants.remove(h); 1578 } 1579 1580 /** 1581 * Register for notifications when a sInCall VoicePrivacy is enabled 1582 * 1583 * @param h Handler that receives the notification message. 1584 * @param what User-defined message code. 1585 * @param obj User object. 1586 */ 1587 public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){ 1588 mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj); 1589 } 1590 1591 /** 1592 * Unregister for notifications when a sInCall VoicePrivacy is enabled 1593 * 1594 * @param h Handler to be removed from the registrant list. 1595 */ 1596 public void unregisterForInCallVoicePrivacyOn(Handler h){ 1597 mInCallVoicePrivacyOnRegistrants.remove(h); 1598 } 1599 1600 /** 1601 * Register for notifications when a sInCall VoicePrivacy is disabled 1602 * 1603 * @param h Handler that receives the notification message. 1604 * @param what User-defined message code. 1605 * @param obj User object. 1606 */ 1607 public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){ 1608 mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj); 1609 } 1610 1611 /** 1612 * Unregister for notifications when a sInCall VoicePrivacy is disabled 1613 * 1614 * @param h Handler to be removed from the registrant list. 1615 */ 1616 public void unregisterForInCallVoicePrivacyOff(Handler h){ 1617 mInCallVoicePrivacyOffRegistrants.remove(h); 1618 } 1619 1620 /** 1621 * Register for notifications when CDMA call waiting comes 1622 * 1623 * @param h Handler that receives the notification message. 1624 * @param what User-defined message code. 1625 * @param obj User object. 1626 */ 1627 public void registerForCallWaiting(Handler h, int what, Object obj){ 1628 mCallWaitingRegistrants.addUnique(h, what, obj); 1629 } 1630 1631 /** 1632 * Unregister for notifications when CDMA Call waiting comes 1633 * @param h Handler to be removed from the registrant list. 1634 */ 1635 public void unregisterForCallWaiting(Handler h){ 1636 mCallWaitingRegistrants.remove(h); 1637 } 1638 1639 1640 /** 1641 * Register for signal information notifications from the network. 1642 * Message.obj will contain an AsyncResult. 1643 * AsyncResult.result will be a SuppServiceNotification instance. 1644 * 1645 * @param h Handler that receives the notification message. 1646 * @param what User-defined message code. 1647 * @param obj User object. 1648 */ 1649 1650 public void registerForSignalInfo(Handler h, int what, Object obj){ 1651 mSignalInfoRegistrants.addUnique(h, what, obj); 1652 } 1653 1654 /** 1655 * Unregisters for signal information notifications. 1656 * Extraneous calls are tolerated silently 1657 * 1658 * @param h Handler to be removed from the registrant list. 1659 */ 1660 public void unregisterForSignalInfo(Handler h){ 1661 mSignalInfoRegistrants.remove(h); 1662 } 1663 1664 /** 1665 * Register for display information notifications from the network. 1666 * Message.obj will contain an AsyncResult. 1667 * AsyncResult.result will be a SuppServiceNotification instance. 1668 * 1669 * @param h Handler that receives the notification message. 1670 * @param what User-defined message code. 1671 * @param obj User object. 1672 */ 1673 public void registerForDisplayInfo(Handler h, int what, Object obj){ 1674 mDisplayInfoRegistrants.addUnique(h, what, obj); 1675 } 1676 1677 /** 1678 * Unregisters for display information notifications. 1679 * Extraneous calls are tolerated silently 1680 * 1681 * @param h Handler to be removed from the registrant list. 1682 */ 1683 public void unregisterForDisplayInfo(Handler h) { 1684 mDisplayInfoRegistrants.remove(h); 1685 } 1686 1687 /** 1688 * Register for notifications when CDMA OTA Provision status change 1689 * 1690 * @param h Handler that receives the notification message. 1691 * @param what User-defined message code. 1692 * @param obj User object. 1693 */ 1694 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){ 1695 mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj); 1696 } 1697 1698 /** 1699 * Unregister for notifications when CDMA OTA Provision status change 1700 * @param h Handler to be removed from the registrant list. 1701 */ 1702 public void unregisterForCdmaOtaStatusChange(Handler h){ 1703 mCdmaOtaStatusChangeRegistrants.remove(h); 1704 } 1705 1706 /** 1707 * Registration point for subscription info ready 1708 * @param h handler to notify 1709 * @param what what code of message when delivered 1710 * @param obj placed in Message.obj 1711 */ 1712 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){ 1713 mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj); 1714 } 1715 1716 /** 1717 * Unregister for notifications for subscription info 1718 * @param h Handler to be removed from the registrant list. 1719 */ 1720 public void unregisterForSubscriptionInfoReady(Handler h){ 1721 mSubscriptionInfoReadyRegistrants.remove(h); 1722 } 1723 1724 /** 1725 * Sets an event to be fired when the telephony system processes 1726 * a post-dial character on an outgoing call.<p> 1727 * 1728 * Messages of type <code>what</code> will be sent to <code>h</code>. 1729 * The <code>obj</code> field of these Message's will be instances of 1730 * <code>AsyncResult</code>. <code>Message.obj.result</code> will be 1731 * a Connection object.<p> 1732 * 1733 * Message.arg1 will be the post dial character being processed, 1734 * or 0 ('\0') if end of string.<p> 1735 * 1736 * If Connection.getPostDialState() == WAIT, 1737 * the application must call 1738 * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar() 1739 * Connection.proceedAfterWaitChar()} or 1740 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1741 * Connection.cancelPostDial()} 1742 * for the telephony system to continue playing the post-dial 1743 * DTMF sequence.<p> 1744 * 1745 * If Connection.getPostDialState() == WILD, 1746 * the application must call 1747 * {@link com.android.internal.telephony.Connection#proceedAfterWildChar 1748 * Connection.proceedAfterWildChar()} 1749 * or 1750 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1751 * Connection.cancelPostDial()} 1752 * for the telephony system to continue playing the 1753 * post-dial DTMF sequence.<p> 1754 * 1755 */ 1756 public void registerForPostDialCharacter(Handler h, int what, Object obj){ 1757 mPostDialCharacterRegistrants.addUnique(h, what, obj); 1758 } 1759 1760 public void unregisterForPostDialCharacter(Handler h){ 1761 mPostDialCharacterRegistrants.remove(h); 1762 } 1763 1764 /** 1765 * Register for TTY mode change notifications from the network. 1766 * Message.obj will contain an AsyncResult. 1767 * AsyncResult.result will be an Integer containing new mode. 1768 * 1769 * @param h Handler that receives the notification message. 1770 * @param what User-defined message code. 1771 * @param obj User object. 1772 */ 1773 public void registerForTtyModeReceived(Handler h, int what, Object obj){ 1774 mTtyModeReceivedRegistrants.addUnique(h, what, obj); 1775 } 1776 1777 /** 1778 * Unregisters for TTY mode change notifications. 1779 * Extraneous calls are tolerated silently 1780 * 1781 * @param h Handler to be removed from the registrant list. 1782 */ 1783 public void unregisterForTtyModeReceived(Handler h) { 1784 mTtyModeReceivedRegistrants.remove(h); 1785 } 1786 1787 /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls 1788 * 1. APIs to access list of calls 1789 * 2. APIs to check if any active call, which has connection other than 1790 * disconnected ones, pleaser refer to Call.isIdle() 1791 * 3. APIs to return first active call 1792 * 4. APIs to return the connections of first active call 1793 * 5. APIs to return other property of first active call 1794 */ 1795 1796 /** 1797 * @return list of all ringing calls 1798 */ 1799 public List<Call> getRingingCalls() { 1800 return Collections.unmodifiableList(mRingingCalls); 1801 } 1802 1803 /** 1804 * @return list of all foreground calls 1805 */ 1806 public List<Call> getForegroundCalls() { 1807 return Collections.unmodifiableList(mForegroundCalls); 1808 } 1809 1810 /** 1811 * @return list of all background calls 1812 */ 1813 public List<Call> getBackgroundCalls() { 1814 return Collections.unmodifiableList(mBackgroundCalls); 1815 } 1816 1817 /** 1818 * Return true if there is at least one active foreground call 1819 */ 1820 public boolean hasActiveFgCall() { 1821 return (getFirstActiveCall(mForegroundCalls) != null); 1822 } 1823 1824 /** 1825 * Return true if there is at least one active foreground call 1826 * on a particular subId or an active sip call 1827 */ 1828 public boolean hasActiveFgCall(int subId) { 1829 return (getFirstActiveCall(mForegroundCalls, subId) != null); 1830 } 1831 1832 /** 1833 * Return true if there is at least one active background call 1834 */ 1835 public boolean hasActiveBgCall() { 1836 // TODO since hasActiveBgCall may get called often 1837 // better to cache it to improve performance 1838 return (getFirstActiveCall(mBackgroundCalls) != null); 1839 } 1840 1841 /** 1842 * Return true if there is at least one active background call 1843 * on a particular subId or an active sip call 1844 */ 1845 public boolean hasActiveBgCall(int subId) { 1846 // TODO since hasActiveBgCall may get called often 1847 // better to cache it to improve performance 1848 return (getFirstActiveCall(mBackgroundCalls, subId) != null); 1849 } 1850 1851 /** 1852 * Return true if there is at least one active ringing call 1853 * 1854 */ 1855 public boolean hasActiveRingingCall() { 1856 return (getFirstActiveCall(mRingingCalls) != null); 1857 } 1858 1859 /** 1860 * Return true if there is at least one active ringing call 1861 */ 1862 public boolean hasActiveRingingCall(int subId) { 1863 return (getFirstActiveCall(mRingingCalls, subId) != null); 1864 } 1865 1866 /** 1867 * return the active foreground call from foreground calls 1868 * 1869 * Active call means the call is NOT in Call.State.IDLE 1870 * 1871 * 1. If there is active foreground call, return it 1872 * 2. If there is no active foreground call, return the 1873 * foreground call associated with default phone, which state is IDLE. 1874 * 3. If there is no phone registered at all, return null. 1875 * 1876 */ 1877 public Call getActiveFgCall() { 1878 Call call = getFirstNonIdleCall(mForegroundCalls); 1879 if (call == null) { 1880 call = (mDefaultPhone == null) 1881 ? null 1882 : mDefaultPhone.getForegroundCall(); 1883 } 1884 return call; 1885 } 1886 1887 public Call getActiveFgCall(int subId) { 1888 Call call = getFirstNonIdleCall(mForegroundCalls, subId); 1889 if (call == null) { 1890 Phone phone = getPhone(subId); 1891 call = (phone == null) 1892 ? null 1893 : phone.getForegroundCall(); 1894 } 1895 return call; 1896 } 1897 1898 // Returns the first call that is not in IDLE state. If both active calls 1899 // and disconnecting/disconnected calls exist, return the first active call. 1900 private Call getFirstNonIdleCall(List<Call> calls) { 1901 Call result = null; 1902 for (Call call : calls) { 1903 if (!call.isIdle()) { 1904 return call; 1905 } else if (call.getState() != Call.State.IDLE) { 1906 if (result == null) result = call; 1907 } 1908 } 1909 return result; 1910 } 1911 1912 // Returns the first call that is not in IDLE state. If both active calls 1913 // and disconnecting/disconnected calls exist, return the first active call. 1914 private Call getFirstNonIdleCall(List<Call> calls, int subId) { 1915 Call result = null; 1916 for (Call call : calls) { 1917 if ((call.getPhone().getSubId() == subId) || 1918 (call.getPhone() instanceof SipPhone)) { 1919 if (!call.isIdle()) { 1920 return call; 1921 } else if (call.getState() != Call.State.IDLE) { 1922 if (result == null) result = call; 1923 } 1924 } 1925 } 1926 return result; 1927 } 1928 1929 /** 1930 * return one active background call from background calls 1931 * 1932 * Active call means the call is NOT idle defined by Call.isIdle() 1933 * 1934 * 1. If there is only one active background call, return it 1935 * 2. If there is more than one active background call, return the first one 1936 * 3. If there is no active background call, return the background call 1937 * associated with default phone, which state is IDLE. 1938 * 4. If there is no background call at all, return null. 1939 * 1940 * Complete background calls list can be get by getBackgroundCalls() 1941 */ 1942 public Call getFirstActiveBgCall() { 1943 Call call = getFirstNonIdleCall(mBackgroundCalls); 1944 if (call == null) { 1945 call = (mDefaultPhone == null) 1946 ? null 1947 : mDefaultPhone.getBackgroundCall(); 1948 } 1949 return call; 1950 } 1951 1952 /** 1953 * return one active background call from background calls of the 1954 * requested subId. 1955 * 1956 * Active call means the call is NOT idle defined by Call.isIdle() 1957 * 1958 * 1. If there is only one active background call on given sub or 1959 * on SIP Phone, return it 1960 * 2. If there is more than one active background call, return the background call 1961 * associated with the active sub. 1962 * 3. If there is no background call at all, return null. 1963 * 1964 * Complete background calls list can be get by getBackgroundCalls() 1965 */ 1966 public Call getFirstActiveBgCall(int subId) { 1967 Phone phone = getPhone(subId); 1968 if (hasMoreThanOneHoldingCall(subId)) { 1969 return phone.getBackgroundCall(); 1970 } else { 1971 Call call = getFirstNonIdleCall(mBackgroundCalls, subId); 1972 if (call == null) { 1973 call = (phone == null) 1974 ? null 1975 : phone.getBackgroundCall(); 1976 } 1977 return call; 1978 } 1979 } 1980 1981 /** 1982 * return one active ringing call from ringing calls 1983 * 1984 * Active call means the call is NOT idle defined by Call.isIdle() 1985 * 1986 * 1. If there is only one active ringing call, return it 1987 * 2. If there is more than one active ringing call, return the first one 1988 * 3. If there is no active ringing call, return the ringing call 1989 * associated with default phone, which state is IDLE. 1990 * 4. If there is no ringing call at all, return null. 1991 * 1992 * Complete ringing calls list can be get by getRingingCalls() 1993 */ 1994 public Call getFirstActiveRingingCall() { 1995 Call call = getFirstNonIdleCall(mRingingCalls); 1996 if (call == null) { 1997 call = (mDefaultPhone == null) 1998 ? null 1999 : mDefaultPhone.getRingingCall(); 2000 } 2001 return call; 2002 } 2003 2004 public Call getFirstActiveRingingCall(int subId) { 2005 Phone phone = getPhone(subId); 2006 Call call = getFirstNonIdleCall(mRingingCalls, subId); 2007 if (call == null) { 2008 call = (phone == null) 2009 ? null 2010 : phone.getRingingCall(); 2011 } 2012 return call; 2013 } 2014 2015 /** 2016 * @return the state of active foreground call 2017 * return IDLE if there is no active foreground call 2018 */ 2019 public Call.State getActiveFgCallState() { 2020 Call fgCall = getActiveFgCall(); 2021 2022 if (fgCall != null) { 2023 return fgCall.getState(); 2024 } 2025 2026 return Call.State.IDLE; 2027 } 2028 2029 public Call.State getActiveFgCallState(int subId) { 2030 Call fgCall = getActiveFgCall(subId); 2031 2032 if (fgCall != null) { 2033 return fgCall.getState(); 2034 } 2035 2036 return Call.State.IDLE; 2037 } 2038 2039 /** 2040 * @return the connections of active foreground call 2041 * return empty list if there is no active foreground call 2042 */ 2043 public List<Connection> getFgCallConnections() { 2044 Call fgCall = getActiveFgCall(); 2045 if ( fgCall != null) { 2046 return fgCall.getConnections(); 2047 } 2048 return mEmptyConnections; 2049 } 2050 2051 /** 2052 * @return the connections of active foreground call 2053 * return empty list if there is no active foreground call 2054 */ 2055 public List<Connection> getFgCallConnections(int subId) { 2056 Call fgCall = getActiveFgCall(subId); 2057 if ( fgCall != null) { 2058 return fgCall.getConnections(); 2059 } 2060 return mEmptyConnections; 2061 } 2062 2063 /** 2064 * @return the connections of active background call 2065 * return empty list if there is no active background call 2066 */ 2067 public List<Connection> getBgCallConnections() { 2068 Call bgCall = getFirstActiveBgCall(); 2069 if ( bgCall != null) { 2070 return bgCall.getConnections(); 2071 } 2072 return mEmptyConnections; 2073 } 2074 2075 /** 2076 * @return the connections of active background call 2077 * return empty list if there is no active background call 2078 */ 2079 public List<Connection> getBgCallConnections(int subId) { 2080 Call bgCall = getFirstActiveBgCall(subId); 2081 if ( bgCall != null) { 2082 return bgCall.getConnections(); 2083 } 2084 return mEmptyConnections; 2085 } 2086 2087 /** 2088 * @return the latest connection of active foreground call 2089 * return null if there is no active foreground call 2090 */ 2091 public Connection getFgCallLatestConnection() { 2092 Call fgCall = getActiveFgCall(); 2093 if ( fgCall != null) { 2094 return fgCall.getLatestConnection(); 2095 } 2096 return null; 2097 } 2098 2099 /** 2100 * @return the latest connection of active foreground call 2101 * return null if there is no active foreground call 2102 */ 2103 public Connection getFgCallLatestConnection(int subId) { 2104 Call fgCall = getActiveFgCall(subId); 2105 if ( fgCall != null) { 2106 return fgCall.getLatestConnection(); 2107 } 2108 return null; 2109 } 2110 2111 /** 2112 * @return true if there is at least one Foreground call in disconnected state 2113 */ 2114 public boolean hasDisconnectedFgCall() { 2115 return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null); 2116 } 2117 2118 /** 2119 * @return true if there is at least one Foreground call in disconnected state 2120 */ 2121 public boolean hasDisconnectedFgCall(int subId) { 2122 return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED, 2123 subId) != null); 2124 } 2125 2126 /** 2127 * @return true if there is at least one background call in disconnected state 2128 */ 2129 public boolean hasDisconnectedBgCall() { 2130 return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null); 2131 } 2132 2133 /** 2134 * @return true if there is at least one background call in disconnected state 2135 */ 2136 public boolean hasDisconnectedBgCall(int subId) { 2137 return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED, 2138 subId) != null); 2139 } 2140 2141 2142 /** 2143 * @return the first active call from a call list 2144 */ 2145 private Call getFirstActiveCall(ArrayList<Call> calls) { 2146 for (Call call : calls) { 2147 if (!call.isIdle()) { 2148 return call; 2149 } 2150 } 2151 return null; 2152 } 2153 2154 /** 2155 * @return the first active call from a call list 2156 */ 2157 private Call getFirstActiveCall(ArrayList<Call> calls, int subId) { 2158 for (Call call : calls) { 2159 if ((!call.isIdle()) && ((call.getPhone().getSubId() == subId) || 2160 (call.getPhone() instanceof SipPhone))) { 2161 return call; 2162 } 2163 } 2164 return null; 2165 } 2166 2167 /** 2168 * @return the first call in a the Call.state from a call list 2169 */ 2170 private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) { 2171 for (Call call : calls) { 2172 if (call.getState() == state) { 2173 return call; 2174 } 2175 } 2176 return null; 2177 } 2178 2179 /** 2180 * @return the first call in a the Call.state from a call list 2181 */ 2182 private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state, 2183 int subId) { 2184 for (Call call : calls) { 2185 if ((call.getState() == state) || 2186 ((call.getPhone().getSubId() == subId) || 2187 (call.getPhone() instanceof SipPhone))) { 2188 return call; 2189 } 2190 } 2191 return null; 2192 } 2193 2194 private boolean hasMoreThanOneRingingCall() { 2195 int count = 0; 2196 for (Call call : mRingingCalls) { 2197 if (call.getState().isRinging()) { 2198 if (++count > 1) return true; 2199 } 2200 } 2201 return false; 2202 } 2203 2204 /** 2205 * @return true if more than one active ringing call exists on 2206 * the active subId. 2207 * This checks for the active calls on provided 2208 * subId and also active calls on SIP Phone. 2209 * 2210 */ 2211 private boolean hasMoreThanOneRingingCall(int subId) { 2212 int count = 0; 2213 for (Call call : mRingingCalls) { 2214 if ((call.getState().isRinging()) && 2215 ((call.getPhone().getSubId() == subId) || 2216 (call.getPhone() instanceof SipPhone))) { 2217 if (++count > 1) return true; 2218 } 2219 } 2220 return false; 2221 } 2222 2223 /** 2224 * @return true if more than one active background call exists on 2225 * the provided subId. 2226 * This checks for the background calls on provided 2227 * subId and also background calls on SIP Phone. 2228 * 2229 */ 2230 private boolean hasMoreThanOneHoldingCall(int subId) { 2231 int count = 0; 2232 for (Call call : mBackgroundCalls) { 2233 if ((call.getState() == Call.State.HOLDING) && 2234 ((call.getPhone().getSubId() == subId) || 2235 (call.getPhone() instanceof SipPhone))) { 2236 if (++count > 1) return true; 2237 } 2238 } 2239 return false; 2240 } 2241 2242 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 2243 private boolean isServiceStateInService() { 2244 boolean bInService = false; 2245 2246 for (Phone phone : mPhones) { 2247 bInService = (phone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE); 2248 if (bInService) { 2249 break; 2250 } 2251 } 2252 2253 if (VDBG) Rlog.d(LOG_TAG, "[isServiceStateInService] bInService = " + bInService); 2254 return bInService; 2255 } 2256 */ 2257 2258 private class CallManagerHandler extends Handler { 2259 @Override 2260 public void handleMessage(Message msg) { 2261 2262 switch (msg.what) { 2263 case EVENT_DISCONNECT: 2264 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)"); 2265 mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2266 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 2267 //mIsEccDialing = false; 2268 break; 2269 case EVENT_PRECISE_CALL_STATE_CHANGED: 2270 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)"); 2271 mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2272 break; 2273 case EVENT_NEW_RINGING_CONNECTION: 2274 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)"); 2275 Connection c = (Connection) ((AsyncResult) msg.obj).result; 2276 int subId = c.getCall().getPhone().getSubId(); 2277 if (getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall()) { 2278 try { 2279 Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall()); 2280 c.getCall().hangup(); 2281 } catch (CallStateException e) { 2282 Rlog.w(LOG_TAG, "new ringing connection", e); 2283 } 2284 } else { 2285 mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2286 } 2287 break; 2288 case EVENT_UNKNOWN_CONNECTION: 2289 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)"); 2290 mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2291 break; 2292 case EVENT_INCOMING_RING: 2293 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)"); 2294 // The event may come from RIL who's not aware of an ongoing fg call 2295 if (!hasActiveFgCall()) { 2296 mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2297 } 2298 break; 2299 case EVENT_RINGBACK_TONE: 2300 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)"); 2301 mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2302 break; 2303 case EVENT_IN_CALL_VOICE_PRIVACY_ON: 2304 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)"); 2305 mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2306 break; 2307 case EVENT_IN_CALL_VOICE_PRIVACY_OFF: 2308 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)"); 2309 mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2310 break; 2311 case EVENT_CALL_WAITING: 2312 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)"); 2313 mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2314 break; 2315 case EVENT_DISPLAY_INFO: 2316 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)"); 2317 mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2318 break; 2319 case EVENT_SIGNAL_INFO: 2320 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)"); 2321 mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2322 break; 2323 case EVENT_CDMA_OTA_STATUS_CHANGE: 2324 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)"); 2325 mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2326 break; 2327 case EVENT_RESEND_INCALL_MUTE: 2328 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)"); 2329 mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2330 break; 2331 case EVENT_MMI_INITIATE: 2332 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)"); 2333 mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2334 break; 2335 case EVENT_MMI_COMPLETE: 2336 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)"); 2337 mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2338 break; 2339 case EVENT_ECM_TIMER_RESET: 2340 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)"); 2341 mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2342 break; 2343 case EVENT_SUBSCRIPTION_INFO_READY: 2344 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)"); 2345 mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2346 break; 2347 case EVENT_SUPP_SERVICE_FAILED: 2348 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)"); 2349 mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2350 break; 2351 case EVENT_SERVICE_STATE_CHANGED: 2352 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)"); 2353 mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2354 // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 2355 //setAudioMode(); 2356 break; 2357 case EVENT_POST_DIAL_CHARACTER: 2358 // we need send the character that is being processed in msg.arg1 2359 // so can't use notifyRegistrants() 2360 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)"); 2361 for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) { 2362 Message notifyMsg; 2363 notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant(); 2364 notifyMsg.obj = msg.obj; 2365 notifyMsg.arg1 = msg.arg1; 2366 notifyMsg.sendToTarget(); 2367 } 2368 break; 2369 case EVENT_ONHOLD_TONE: 2370 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ONHOLD_TONE)"); 2371 mOnHoldToneRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2372 break; 2373 case EVENT_TTY_MODE_RECEIVED: 2374 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_TTY_MODE_RECEIVED)"); 2375 mTtyModeReceivedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 2376 break; 2377 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L. 2378 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 2379 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RADIO_OFF_OR_NOT_AVAILABLE)"); 2380 setAudioMode(); 2381 break; 2382 */ 2383 } 2384 } 2385 }; 2386 2387 @Override 2388 public String toString() { 2389 Call call; 2390 StringBuilder b = new StringBuilder(); 2391 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) { 2392 b.append("CallManager {"); 2393 b.append("\nstate = " + getState(i)); 2394 call = getActiveFgCall(i); 2395 if (call != null) { 2396 b.append("\n- Foreground: " + getActiveFgCallState(i)); 2397 b.append(" from " + call.getPhone()); 2398 b.append("\n Conn: ").append(getFgCallConnections(i)); 2399 } 2400 call = getFirstActiveBgCall(i); 2401 if (call != null) { 2402 b.append("\n- Background: " + call.getState()); 2403 b.append(" from " + call.getPhone()); 2404 b.append("\n Conn: ").append(getBgCallConnections(i)); 2405 } 2406 call = getFirstActiveRingingCall(i); 2407 if (call != null) { 2408 b.append("\n- Ringing: " +call.getState()); 2409 b.append(" from " + call.getPhone()); 2410 } 2411 } 2412 2413 for (Phone phone : getAllPhones()) { 2414 if (phone != null) { 2415 b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName() 2416 + ", state = " + phone.getState()); 2417 call = phone.getForegroundCall(); 2418 if (call != null) { 2419 b.append("\n- Foreground: ").append(call); 2420 } 2421 call = phone.getBackgroundCall(); 2422 if (call != null) { 2423 b.append(" Background: ").append(call); 2424 } 2425 call = phone.getRingingCall(); 2426 if (call != null) { 2427 b.append(" Ringing: ").append(call); 2428 } 2429 } 2430 } 2431 b.append("\n}"); 2432 return b.toString(); 2433 } 2434} 2435