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