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