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