1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import com.android.internal.telephony.sip.SipPhone; 20 21 import android.content.Context; 22 import android.media.AudioManager; 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.telephony.PhoneStateListener; 29 import android.telephony.ServiceState; 30 import android.telephony.Rlog; 31 32 import java.util.ArrayList; 33 import java.util.Collections; 34 import java.util.List; 35 36 37 38 /** 39 * @hide 40 * 41 * CallManager class provides an abstract layer for PhoneApp to access 42 * and control calls. It implements Phone interface. 43 * 44 * CallManager provides call and connection control as well as 45 * channel capability. 46 * 47 * There are three categories of APIs CallManager provided 48 * 49 * 1. Call control and operation, such as dial() and hangup() 50 * 2. Channel capabilities, such as CanConference() 51 * 3. Register notification 52 * 53 * 54 */ 55 public final class CallManager { 56 57 private static final String LOG_TAG ="CallManager"; 58 private static final boolean DBG = true; 59 private static final boolean VDBG = false; 60 61 private static final int EVENT_DISCONNECT = 100; 62 private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101; 63 private static final int EVENT_NEW_RINGING_CONNECTION = 102; 64 private static final int EVENT_UNKNOWN_CONNECTION = 103; 65 private static final int EVENT_INCOMING_RING = 104; 66 private static final int EVENT_RINGBACK_TONE = 105; 67 private static final int EVENT_IN_CALL_VOICE_PRIVACY_ON = 106; 68 private static final int EVENT_IN_CALL_VOICE_PRIVACY_OFF = 107; 69 private static final int EVENT_CALL_WAITING = 108; 70 private static final int EVENT_DISPLAY_INFO = 109; 71 private static final int EVENT_SIGNAL_INFO = 110; 72 private static final int EVENT_CDMA_OTA_STATUS_CHANGE = 111; 73 private static final int EVENT_RESEND_INCALL_MUTE = 112; 74 private static final int EVENT_MMI_INITIATE = 113; 75 private static final int EVENT_MMI_COMPLETE = 114; 76 private static final int EVENT_ECM_TIMER_RESET = 115; 77 private static final int EVENT_SUBSCRIPTION_INFO_READY = 116; 78 private static final int EVENT_SUPP_SERVICE_FAILED = 117; 79 private static final int EVENT_SERVICE_STATE_CHANGED = 118; 80 private static final int EVENT_POST_DIAL_CHARACTER = 119; 81 82 // Singleton instance 83 private static final CallManager INSTANCE = new CallManager(); 84 85 // list of registered phones, which are PhoneBase objs 86 private final ArrayList<Phone> mPhones; 87 88 // list of supported ringing calls 89 private final ArrayList<Call> mRingingCalls; 90 91 // list of supported background calls 92 private final ArrayList<Call> mBackgroundCalls; 93 94 // list of supported foreground calls 95 private final ArrayList<Call> mForegroundCalls; 96 97 // empty connection list 98 private final ArrayList<Connection> mEmptyConnections = new ArrayList<Connection>(); 99 100 // default phone as the first phone registered, which is PhoneBase obj 101 private Phone mDefaultPhone; 102 103 private boolean mSpeedUpAudioForMtCall = false; 104 105 // state registrants 106 protected final RegistrantList mPreciseCallStateRegistrants 107 = new RegistrantList(); 108 109 protected final RegistrantList mNewRingingConnectionRegistrants 110 = new RegistrantList(); 111 112 protected final RegistrantList mIncomingRingRegistrants 113 = new RegistrantList(); 114 115 protected final RegistrantList mDisconnectRegistrants 116 = new RegistrantList(); 117 118 protected final RegistrantList mMmiRegistrants 119 = new RegistrantList(); 120 121 protected final RegistrantList mUnknownConnectionRegistrants 122 = new RegistrantList(); 123 124 protected final RegistrantList mRingbackToneRegistrants 125 = new RegistrantList(); 126 127 protected final RegistrantList mInCallVoicePrivacyOnRegistrants 128 = new RegistrantList(); 129 130 protected final RegistrantList mInCallVoicePrivacyOffRegistrants 131 = new RegistrantList(); 132 133 protected final RegistrantList mCallWaitingRegistrants 134 = new RegistrantList(); 135 136 protected final RegistrantList mDisplayInfoRegistrants 137 = new RegistrantList(); 138 139 protected final RegistrantList mSignalInfoRegistrants 140 = new RegistrantList(); 141 142 protected final RegistrantList mCdmaOtaStatusChangeRegistrants 143 = new RegistrantList(); 144 145 protected final RegistrantList mResendIncallMuteRegistrants 146 = new RegistrantList(); 147 148 protected final RegistrantList mMmiInitiateRegistrants 149 = new RegistrantList(); 150 151 protected final RegistrantList mMmiCompleteRegistrants 152 = new RegistrantList(); 153 154 protected final RegistrantList mEcmTimerResetRegistrants 155 = new RegistrantList(); 156 157 protected final RegistrantList mSubscriptionInfoReadyRegistrants 158 = new RegistrantList(); 159 160 protected final RegistrantList mSuppServiceFailedRegistrants 161 = new RegistrantList(); 162 163 protected final RegistrantList mServiceStateChangedRegistrants 164 = new RegistrantList(); 165 166 protected final RegistrantList mPostDialCharacterRegistrants 167 = new RegistrantList(); 168 169 private CallManager() { 170 mPhones = new ArrayList<Phone>(); 171 mRingingCalls = new ArrayList<Call>(); 172 mBackgroundCalls = new ArrayList<Call>(); 173 mForegroundCalls = new ArrayList<Call>(); 174 mDefaultPhone = null; 175 } 176 177 /** 178 * get singleton instance of CallManager 179 * @return CallManager 180 */ 181 public static CallManager getInstance() { 182 return INSTANCE; 183 } 184 185 /** 186 * Get the corresponding PhoneBase obj 187 * 188 * @param phone a Phone object 189 * @return the corresponding PhoneBase obj in Phone if Phone 190 * is a PhoneProxy obj 191 * or the Phone itself if Phone is not a PhoneProxy obj 192 */ 193 private static Phone getPhoneBase(Phone phone) { 194 if (phone instanceof PhoneProxy) { 195 return phone.getForegroundCall().getPhone(); 196 } 197 return phone; 198 } 199 200 /** 201 * Check if two phones refer to the same PhoneBase obj 202 * 203 * Note: PhoneBase, not PhoneProxy, is to be used inside of CallManager 204 * 205 * Both PhoneBase and PhoneProxy implement Phone interface, so 206 * they have same phone APIs, such as dial(). The real implementation, for 207 * example in GSM, is in GSMPhone as extend from PhoneBase, so that 208 * foregroundCall.getPhone() returns GSMPhone obj. On the other hand, 209 * PhoneFactory.getDefaultPhone() returns PhoneProxy obj, which has a class 210 * member of GSMPhone. 211 * 212 * So for phone returned by PhoneFacotry, which is used by PhoneApp, 213 * phone.getForegroundCall().getPhone() != phone 214 * but 215 * isSamePhone(phone, phone.getForegroundCall().getPhone()) == true 216 * 217 * @param p1 is the first Phone obj 218 * @param p2 is the second Phone obj 219 * @return true if p1 and p2 refer to the same phone 220 */ 221 public static boolean isSamePhone(Phone p1, Phone p2) { 222 return (getPhoneBase(p1) == getPhoneBase(p2)); 223 } 224 225 /** 226 * Returns all the registered phone objects. 227 * @return all the registered phone objects. 228 */ 229 public List<Phone> getAllPhones() { 230 return Collections.unmodifiableList(mPhones); 231 } 232 233 /** 234 * Get current coarse-grained voice call state. 235 * If the Call Manager has an active call and call waiting occurs, 236 * then the phone state is RINGING not OFFHOOK 237 * 238 */ 239 public PhoneConstants.State getState() { 240 PhoneConstants.State s = PhoneConstants.State.IDLE; 241 242 for (Phone phone : mPhones) { 243 if (phone.getState() == PhoneConstants.State.RINGING) { 244 s = PhoneConstants.State.RINGING; 245 } else if (phone.getState() == PhoneConstants.State.OFFHOOK) { 246 if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK; 247 } 248 } 249 return s; 250 } 251 252 /** 253 * @return the service state of CallManager, which represents the 254 * highest priority state of all the service states of phones 255 * 256 * The priority is defined as 257 * 258 * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF 259 * 260 */ 261 262 public int getServiceState() { 263 int resultState = ServiceState.STATE_OUT_OF_SERVICE; 264 265 for (Phone phone : mPhones) { 266 int serviceState = phone.getServiceState().getState(); 267 if (serviceState == ServiceState.STATE_IN_SERVICE) { 268 // IN_SERVICE has the highest priority 269 resultState = serviceState; 270 break; 271 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) { 272 // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF 273 // Note: EMERGENCY_ONLY is not in use at this moment 274 if ( resultState == ServiceState.STATE_EMERGENCY_ONLY || 275 resultState == ServiceState.STATE_POWER_OFF) { 276 resultState = serviceState; 277 } 278 } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) { 279 if (resultState == ServiceState.STATE_POWER_OFF) { 280 resultState = serviceState; 281 } 282 } 283 } 284 return resultState; 285 } 286 287 /** 288 * Register phone to CallManager 289 * @param phone to be registered 290 * @return true if register successfully 291 */ 292 public boolean registerPhone(Phone phone) { 293 Phone basePhone = getPhoneBase(phone); 294 295 if (basePhone != null && !mPhones.contains(basePhone)) { 296 297 if (DBG) { 298 Rlog.d(LOG_TAG, "registerPhone(" + 299 phone.getPhoneName() + " " + phone + ")"); 300 } 301 302 if (mPhones.isEmpty()) { 303 mDefaultPhone = basePhone; 304 } 305 mPhones.add(basePhone); 306 mRingingCalls.add(basePhone.getRingingCall()); 307 mBackgroundCalls.add(basePhone.getBackgroundCall()); 308 mForegroundCalls.add(basePhone.getForegroundCall()); 309 registerForPhoneStates(basePhone); 310 return true; 311 } 312 return false; 313 } 314 315 /** 316 * unregister phone from CallManager 317 * @param phone to be unregistered 318 */ 319 public void unregisterPhone(Phone phone) { 320 Phone basePhone = getPhoneBase(phone); 321 322 if (basePhone != null && mPhones.contains(basePhone)) { 323 324 if (DBG) { 325 Rlog.d(LOG_TAG, "unregisterPhone(" + 326 phone.getPhoneName() + " " + phone + ")"); 327 } 328 329 mPhones.remove(basePhone); 330 mRingingCalls.remove(basePhone.getRingingCall()); 331 mBackgroundCalls.remove(basePhone.getBackgroundCall()); 332 mForegroundCalls.remove(basePhone.getForegroundCall()); 333 unregisterForPhoneStates(basePhone); 334 if (basePhone == mDefaultPhone) { 335 if (mPhones.isEmpty()) { 336 mDefaultPhone = null; 337 } else { 338 mDefaultPhone = mPhones.get(0); 339 } 340 } 341 } 342 } 343 344 /** 345 * return the default phone or null if no phone available 346 */ 347 public Phone getDefaultPhone() { 348 return mDefaultPhone; 349 } 350 351 /** 352 * @return the phone associated with the foreground call 353 */ 354 public Phone getFgPhone() { 355 return getActiveFgCall().getPhone(); 356 } 357 358 /** 359 * @return the phone associated with the background call 360 */ 361 public Phone getBgPhone() { 362 return getFirstActiveBgCall().getPhone(); 363 } 364 365 /** 366 * @return the phone associated with the ringing call 367 */ 368 public Phone getRingingPhone() { 369 return getFirstActiveRingingCall().getPhone(); 370 } 371 372 public void setAudioMode() { 373 Context context = getContext(); 374 if (context == null) return; 375 AudioManager audioManager = (AudioManager) 376 context.getSystemService(Context.AUDIO_SERVICE); 377 378 // change the audio mode and request/abandon audio focus according to phone state, 379 // but only on audio mode transitions 380 switch (getState()) { 381 case RINGING: 382 int curAudioMode = audioManager.getMode(); 383 if (curAudioMode != AudioManager.MODE_RINGTONE) { 384 // only request audio focus if the ringtone is going to be heard 385 if (audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0) { 386 if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_RING"); 387 audioManager.requestAudioFocusForCall(AudioManager.STREAM_RING, 388 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 389 } 390 if(!mSpeedUpAudioForMtCall) { 391 audioManager.setMode(AudioManager.MODE_RINGTONE); 392 } 393 } 394 395 if (mSpeedUpAudioForMtCall && (curAudioMode != AudioManager.MODE_IN_CALL)) { 396 audioManager.setMode(AudioManager.MODE_IN_CALL); 397 } 398 break; 399 case OFFHOOK: 400 Phone offhookPhone = getFgPhone(); 401 if (getActiveFgCallState() == Call.State.IDLE) { 402 // There is no active Fg calls, the OFFHOOK state 403 // is set by the Bg call. So set the phone to bgPhone. 404 offhookPhone = getBgPhone(); 405 } 406 407 int newAudioMode = AudioManager.MODE_IN_CALL; 408 if (offhookPhone instanceof SipPhone) { 409 // enable IN_COMMUNICATION audio mode instead for sipPhone 410 newAudioMode = AudioManager.MODE_IN_COMMUNICATION; 411 } 412 if (audioManager.getMode() != newAudioMode || mSpeedUpAudioForMtCall) { 413 // request audio focus before setting the new mode 414 if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_VOICE_CALL"); 415 audioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, 416 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 417 audioManager.setMode(newAudioMode); 418 } 419 mSpeedUpAudioForMtCall = false; 420 break; 421 case IDLE: 422 if (audioManager.getMode() != AudioManager.MODE_NORMAL) { 423 audioManager.setMode(AudioManager.MODE_NORMAL); 424 if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus"); 425 // abandon audio focus after the mode has been set back to normal 426 audioManager.abandonAudioFocusForCall(); 427 } 428 mSpeedUpAudioForMtCall = false; 429 break; 430 } 431 } 432 433 private Context getContext() { 434 Phone defaultPhone = getDefaultPhone(); 435 return ((defaultPhone == null) ? null : defaultPhone.getContext()); 436 } 437 438 private void registerForPhoneStates(Phone phone) { 439 // for common events supported by all phones 440 phone.registerForPreciseCallStateChanged(mHandler, EVENT_PRECISE_CALL_STATE_CHANGED, null); 441 phone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null); 442 phone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null); 443 phone.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION, null); 444 phone.registerForIncomingRing(mHandler, EVENT_INCOMING_RING, null); 445 phone.registerForRingbackTone(mHandler, EVENT_RINGBACK_TONE, null); 446 phone.registerForInCallVoicePrivacyOn(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_ON, null); 447 phone.registerForInCallVoicePrivacyOff(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, null); 448 phone.registerForDisplayInfo(mHandler, EVENT_DISPLAY_INFO, null); 449 phone.registerForSignalInfo(mHandler, EVENT_SIGNAL_INFO, null); 450 phone.registerForResendIncallMute(mHandler, EVENT_RESEND_INCALL_MUTE, null); 451 phone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null); 452 phone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null); 453 phone.registerForSuppServiceFailed(mHandler, EVENT_SUPP_SERVICE_FAILED, null); 454 phone.registerForServiceStateChanged(mHandler, EVENT_SERVICE_STATE_CHANGED, null); 455 456 // for events supported only by GSM and CDMA phone 457 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM || 458 phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) { 459 phone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL_CHARACTER, null); 460 } 461 462 // for events supported only by CDMA phone 463 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){ 464 phone.registerForCdmaOtaStatusChange(mHandler, EVENT_CDMA_OTA_STATUS_CHANGE, null); 465 phone.registerForSubscriptionInfoReady(mHandler, EVENT_SUBSCRIPTION_INFO_READY, null); 466 phone.registerForCallWaiting(mHandler, EVENT_CALL_WAITING, null); 467 phone.registerForEcmTimerReset(mHandler, EVENT_ECM_TIMER_RESET, null); 468 } 469 } 470 471 private void unregisterForPhoneStates(Phone phone) { 472 // for common events supported by all phones 473 phone.unregisterForPreciseCallStateChanged(mHandler); 474 phone.unregisterForDisconnect(mHandler); 475 phone.unregisterForNewRingingConnection(mHandler); 476 phone.unregisterForUnknownConnection(mHandler); 477 phone.unregisterForIncomingRing(mHandler); 478 phone.unregisterForRingbackTone(mHandler); 479 phone.unregisterForInCallVoicePrivacyOn(mHandler); 480 phone.unregisterForInCallVoicePrivacyOff(mHandler); 481 phone.unregisterForDisplayInfo(mHandler); 482 phone.unregisterForSignalInfo(mHandler); 483 phone.unregisterForResendIncallMute(mHandler); 484 phone.unregisterForMmiInitiate(mHandler); 485 phone.unregisterForMmiComplete(mHandler); 486 phone.unregisterForSuppServiceFailed(mHandler); 487 phone.unregisterForServiceStateChanged(mHandler); 488 489 // for events supported only by GSM and CDMA phone 490 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM || 491 phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) { 492 phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null); 493 } 494 495 // for events supported only by CDMA phone 496 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){ 497 phone.unregisterForCdmaOtaStatusChange(mHandler); 498 phone.unregisterForSubscriptionInfoReady(mHandler); 499 phone.unregisterForCallWaiting(mHandler); 500 phone.unregisterForEcmTimerReset(mHandler); 501 } 502 } 503 504 /** 505 * Answers a ringing or waiting call. 506 * 507 * Active call, if any, go on hold. 508 * If active call can't be held, i.e., a background call of the same channel exists, 509 * the active call will be hang up. 510 * 511 * Answering occurs asynchronously, and final notification occurs via 512 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 513 * java.lang.Object) registerForPreciseCallStateChanged()}. 514 * 515 * @exception CallStateException when call is not ringing or waiting 516 */ 517 public void acceptCall(Call ringingCall) throws CallStateException { 518 Phone ringingPhone = ringingCall.getPhone(); 519 520 if (VDBG) { 521 Rlog.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")"); 522 Rlog.d(LOG_TAG, toString()); 523 } 524 525 if ( hasActiveFgCall() ) { 526 Phone activePhone = getActiveFgCall().getPhone(); 527 boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle()); 528 boolean sameChannel = (activePhone == ringingPhone); 529 530 if (VDBG) { 531 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel); 532 } 533 534 if (sameChannel && hasBgCall) { 535 getActiveFgCall().hangup(); 536 } else if (!sameChannel && !hasBgCall) { 537 activePhone.switchHoldingAndActive(); 538 } else if (!sameChannel && hasBgCall) { 539 getActiveFgCall().hangup(); 540 } 541 } 542 543 Context context = getContext(); 544 if (context == null) { 545 Rlog.d(LOG_TAG, "Speedup Audio Path enhancement: Context is null"); 546 } else if (context.getResources().getBoolean( 547 com.android.internal.R.bool.config_speed_up_audio_on_mt_calls)) { 548 Rlog.d(LOG_TAG, "Speedup Audio Path enhancement"); 549 AudioManager audioManager = (AudioManager) 550 context.getSystemService(Context.AUDIO_SERVICE); 551 int currMode = audioManager.getMode(); 552 if ((currMode != AudioManager.MODE_IN_CALL) && !(ringingPhone instanceof SipPhone)) { 553 Rlog.d(LOG_TAG, "setAudioMode Setting audio mode from " + 554 currMode + " to " + AudioManager.MODE_IN_CALL); 555 audioManager.setMode(AudioManager.MODE_IN_CALL); 556 mSpeedUpAudioForMtCall = true; 557 } 558 } 559 560 ringingPhone.acceptCall(); 561 562 if (VDBG) { 563 Rlog.d(LOG_TAG, "End acceptCall(" +ringingCall + ")"); 564 Rlog.d(LOG_TAG, toString()); 565 } 566 } 567 568 /** 569 * Reject (ignore) a ringing call. In GSM, this means UDUB 570 * (User Determined User Busy). Reject occurs asynchronously, 571 * and final notification occurs via 572 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 573 * java.lang.Object) registerForPreciseCallStateChanged()}. 574 * 575 * @exception CallStateException when no call is ringing or waiting 576 */ 577 public void rejectCall(Call ringingCall) throws CallStateException { 578 if (VDBG) { 579 Rlog.d(LOG_TAG, "rejectCall(" +ringingCall + ")"); 580 Rlog.d(LOG_TAG, toString()); 581 } 582 583 Phone ringingPhone = ringingCall.getPhone(); 584 585 ringingPhone.rejectCall(); 586 587 if (VDBG) { 588 Rlog.d(LOG_TAG, "End rejectCall(" +ringingCall + ")"); 589 Rlog.d(LOG_TAG, toString()); 590 } 591 } 592 593 /** 594 * Places active call on hold, and makes held call active. 595 * Switch occurs asynchronously and may fail. 596 * 597 * There are 4 scenarios 598 * 1. only active call but no held call, aka, hold 599 * 2. no active call but only held call, aka, unhold 600 * 3. both active and held calls from same phone, aka, swap 601 * 4. active and held calls from different phones, aka, phone swap 602 * 603 * Final notification occurs via 604 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 605 * java.lang.Object) registerForPreciseCallStateChanged()}. 606 * 607 * @exception CallStateException if active call is ringing, waiting, or 608 * dialing/alerting, or heldCall can't be active. 609 * In these cases, this operation may not be performed. 610 */ 611 public void switchHoldingAndActive(Call heldCall) throws CallStateException { 612 Phone activePhone = null; 613 Phone heldPhone = null; 614 615 if (VDBG) { 616 Rlog.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")"); 617 Rlog.d(LOG_TAG, toString()); 618 } 619 620 if (hasActiveFgCall()) { 621 activePhone = getActiveFgCall().getPhone(); 622 } 623 624 if (heldCall != null) { 625 heldPhone = heldCall.getPhone(); 626 } 627 628 if (activePhone != null) { 629 activePhone.switchHoldingAndActive(); 630 } 631 632 if (heldPhone != null && heldPhone != activePhone) { 633 heldPhone.switchHoldingAndActive(); 634 } 635 636 if (VDBG) { 637 Rlog.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")"); 638 Rlog.d(LOG_TAG, toString()); 639 } 640 } 641 642 /** 643 * Hangup foreground call and resume the specific background call 644 * 645 * Note: this is noop if there is no foreground call or the heldCall is null 646 * 647 * @param heldCall to become foreground 648 * @throws CallStateException 649 */ 650 public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException { 651 Phone foregroundPhone = null; 652 Phone backgroundPhone = null; 653 654 if (VDBG) { 655 Rlog.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")"); 656 Rlog.d(LOG_TAG, toString()); 657 } 658 659 if (hasActiveFgCall()) { 660 foregroundPhone = getFgPhone(); 661 if (heldCall != null) { 662 backgroundPhone = heldCall.getPhone(); 663 if (foregroundPhone == backgroundPhone) { 664 getActiveFgCall().hangup(); 665 } else { 666 // the call to be hangup and resumed belongs to different phones 667 getActiveFgCall().hangup(); 668 switchHoldingAndActive(heldCall); 669 } 670 } 671 } 672 673 if (VDBG) { 674 Rlog.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")"); 675 Rlog.d(LOG_TAG, toString()); 676 } 677 } 678 679 /** 680 * Whether or not the phone can conference in the current phone 681 * state--that is, one call holding and one call active. 682 * @return true if the phone can conference; false otherwise. 683 */ 684 public boolean canConference(Call heldCall) { 685 Phone activePhone = null; 686 Phone heldPhone = null; 687 688 if (hasActiveFgCall()) { 689 activePhone = getActiveFgCall().getPhone(); 690 } 691 692 if (heldCall != null) { 693 heldPhone = heldCall.getPhone(); 694 } 695 696 return heldPhone.getClass().equals(activePhone.getClass()); 697 } 698 699 /** 700 * Conferences holding and active. Conference occurs asynchronously 701 * and may fail. Final notification occurs via 702 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 703 * java.lang.Object) registerForPreciseCallStateChanged()}. 704 * 705 * @exception CallStateException if canConference() would return false. 706 * In these cases, this operation may not be performed. 707 */ 708 public void conference(Call heldCall) throws CallStateException { 709 710 if (VDBG) { 711 Rlog.d(LOG_TAG, "conference(" +heldCall + ")"); 712 Rlog.d(LOG_TAG, toString()); 713 } 714 715 716 Phone fgPhone = getFgPhone(); 717 if (fgPhone instanceof SipPhone) { 718 ((SipPhone) fgPhone).conference(heldCall); 719 } else if (canConference(heldCall)) { 720 fgPhone.conference(); 721 } else { 722 throw(new CallStateException("Can't conference foreground and selected background call")); 723 } 724 725 if (VDBG) { 726 Rlog.d(LOG_TAG, "End conference(" +heldCall + ")"); 727 Rlog.d(LOG_TAG, toString()); 728 } 729 730 } 731 732 /** 733 * Initiate a new voice connection. This happens asynchronously, so you 734 * cannot assume the audio path is connected (or a call index has been 735 * assigned) until PhoneStateChanged notification has occurred. 736 * 737 * @exception CallStateException if a new outgoing call is not currently 738 * possible because no more call slots exist or a call exists that is 739 * dialing, alerting, ringing, or waiting. Other errors are 740 * handled asynchronously. 741 */ 742 public Connection dial(Phone phone, String dialString) throws CallStateException { 743 Phone basePhone = getPhoneBase(phone); 744 Connection result; 745 746 if (VDBG) { 747 Rlog.d(LOG_TAG, " dial(" + basePhone + ", "+ dialString + ")"); 748 Rlog.d(LOG_TAG, toString()); 749 } 750 751 if (!canDial(phone)) { 752 throw new CallStateException("cannot dial in current state"); 753 } 754 755 if ( hasActiveFgCall() ) { 756 Phone activePhone = getActiveFgCall().getPhone(); 757 boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle()); 758 759 if (DBG) { 760 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == basePhone)); 761 } 762 763 if (activePhone != basePhone) { 764 if (hasBgCall) { 765 Rlog.d(LOG_TAG, "Hangup"); 766 getActiveFgCall().hangup(); 767 } else { 768 Rlog.d(LOG_TAG, "Switch"); 769 activePhone.switchHoldingAndActive(); 770 } 771 } 772 } 773 774 result = basePhone.dial(dialString); 775 776 if (VDBG) { 777 Rlog.d(LOG_TAG, "End dial(" + basePhone + ", "+ dialString + ")"); 778 Rlog.d(LOG_TAG, toString()); 779 } 780 781 return result; 782 } 783 784 /** 785 * Initiate a new voice connection. This happens asynchronously, so you 786 * cannot assume the audio path is connected (or a call index has been 787 * assigned) until PhoneStateChanged notification has occurred. 788 * 789 * @exception CallStateException if a new outgoing call is not currently 790 * possible because no more call slots exist or a call exists that is 791 * dialing, alerting, ringing, or waiting. Other errors are 792 * handled asynchronously. 793 */ 794 public Connection dial(Phone phone, String dialString, UUSInfo uusInfo) throws CallStateException { 795 return phone.dial(dialString, uusInfo); 796 } 797 798 /** 799 * clear disconnect connection for each phone 800 */ 801 public void clearDisconnected() { 802 for(Phone phone : mPhones) { 803 phone.clearDisconnected(); 804 } 805 } 806 807 /** 808 * Phone can make a call only if ALL of the following are true: 809 * - Phone is not powered off 810 * - There's no incoming or waiting call 811 * - There's available call slot in either foreground or background 812 * - The foreground call is ACTIVE or IDLE or DISCONNECTED. 813 * (We mainly need to make sure it *isn't* DIALING or ALERTING.) 814 * @param phone 815 * @return true if the phone can make a new call 816 */ 817 private boolean canDial(Phone phone) { 818 int serviceState = phone.getServiceState().getState(); 819 boolean hasRingingCall = hasActiveRingingCall(); 820 boolean hasActiveCall = hasActiveFgCall(); 821 boolean hasHoldingCall = hasActiveBgCall(); 822 boolean allLinesTaken = hasActiveCall && hasHoldingCall; 823 Call.State fgCallState = getActiveFgCallState(); 824 825 boolean result = (serviceState != ServiceState.STATE_POWER_OFF 826 && !hasRingingCall 827 && !allLinesTaken 828 && ((fgCallState == Call.State.ACTIVE) 829 || (fgCallState == Call.State.IDLE) 830 || (fgCallState == Call.State.DISCONNECTED))); 831 832 if (result == false) { 833 Rlog.d(LOG_TAG, "canDial serviceState=" + serviceState 834 + " hasRingingCall=" + hasRingingCall 835 + " hasActiveCall=" + hasActiveCall 836 + " hasHoldingCall=" + hasHoldingCall 837 + " allLinesTaken=" + allLinesTaken 838 + " fgCallState=" + fgCallState); 839 } 840 return result; 841 } 842 843 /** 844 * Whether or not the phone can do explicit call transfer in the current 845 * phone state--that is, one call holding and one call active. 846 * @return true if the phone can do explicit call transfer; false otherwise. 847 */ 848 public boolean canTransfer(Call heldCall) { 849 Phone activePhone = null; 850 Phone heldPhone = null; 851 852 if (hasActiveFgCall()) { 853 activePhone = getActiveFgCall().getPhone(); 854 } 855 856 if (heldCall != null) { 857 heldPhone = heldCall.getPhone(); 858 } 859 860 return (heldPhone == activePhone && activePhone.canTransfer()); 861 } 862 863 /** 864 * Connects the held call and active call 865 * Disconnects the subscriber from both calls 866 * 867 * Explicit Call Transfer occurs asynchronously 868 * and may fail. Final notification occurs via 869 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 870 * java.lang.Object) registerForPreciseCallStateChanged()}. 871 * 872 * @exception CallStateException if canTransfer() would return false. 873 * In these cases, this operation may not be performed. 874 */ 875 public void explicitCallTransfer(Call heldCall) throws CallStateException { 876 if (VDBG) { 877 Rlog.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")"); 878 Rlog.d(LOG_TAG, toString()); 879 } 880 881 if (canTransfer(heldCall)) { 882 heldCall.getPhone().explicitCallTransfer(); 883 } 884 885 if (VDBG) { 886 Rlog.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")"); 887 Rlog.d(LOG_TAG, toString()); 888 } 889 890 } 891 892 /** 893 * Returns a list of MMI codes that are pending for a phone. (They have initiated 894 * but have not yet completed). 895 * Presently there is only ever one. 896 * 897 * Use <code>registerForMmiInitiate</code> 898 * and <code>registerForMmiComplete</code> for change notification. 899 * @return null if phone doesn't have or support mmi code 900 */ 901 public List<? extends MmiCode> getPendingMmiCodes(Phone phone) { 902 Rlog.e(LOG_TAG, "getPendingMmiCodes not implemented"); 903 return null; 904 } 905 906 /** 907 * Sends user response to a USSD REQUEST message. An MmiCode instance 908 * representing this response is sent to handlers registered with 909 * registerForMmiInitiate. 910 * 911 * @param ussdMessge Message to send in the response. 912 * @return false if phone doesn't support ussd service 913 */ 914 public boolean sendUssdResponse(Phone phone, String ussdMessge) { 915 Rlog.e(LOG_TAG, "sendUssdResponse not implemented"); 916 return false; 917 } 918 919 /** 920 * Mutes or unmutes the microphone for the active call. The microphone 921 * is automatically unmuted if a call is answered, dialed, or resumed 922 * from a holding state. 923 * 924 * @param muted true to mute the microphone, 925 * false to activate the microphone. 926 */ 927 928 public void setMute(boolean muted) { 929 if (VDBG) { 930 Rlog.d(LOG_TAG, " setMute(" + muted + ")"); 931 Rlog.d(LOG_TAG, toString()); 932 } 933 934 if (hasActiveFgCall()) { 935 getActiveFgCall().getPhone().setMute(muted); 936 } 937 938 if (VDBG) { 939 Rlog.d(LOG_TAG, "End setMute(" + muted + ")"); 940 Rlog.d(LOG_TAG, toString()); 941 } 942 } 943 944 /** 945 * Gets current mute status. Use 946 * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, 947 * java.lang.Object) registerForPreciseCallStateChanged()} 948 * as a change notifcation, although presently phone state changed is not 949 * fired when setMute() is called. 950 * 951 * @return true is muting, false is unmuting 952 */ 953 public boolean getMute() { 954 if (hasActiveFgCall()) { 955 return getActiveFgCall().getPhone().getMute(); 956 } else if (hasActiveBgCall()) { 957 return getFirstActiveBgCall().getPhone().getMute(); 958 } 959 return false; 960 } 961 962 /** 963 * Enables or disables echo suppression. 964 */ 965 public void setEchoSuppressionEnabled(boolean enabled) { 966 if (VDBG) { 967 Rlog.d(LOG_TAG, " setEchoSuppression(" + enabled + ")"); 968 Rlog.d(LOG_TAG, toString()); 969 } 970 971 if (hasActiveFgCall()) { 972 getActiveFgCall().getPhone().setEchoSuppressionEnabled(enabled); 973 } 974 975 if (VDBG) { 976 Rlog.d(LOG_TAG, "End setEchoSuppression(" + enabled + ")"); 977 Rlog.d(LOG_TAG, toString()); 978 } 979 } 980 981 /** 982 * Play a DTMF tone on the active call. 983 * 984 * @param c should be one of 0-9, '*' or '#'. Other values will be 985 * silently ignored. 986 * @return false if no active call or the active call doesn't support 987 * dtmf tone 988 */ 989 public boolean sendDtmf(char c) { 990 boolean result = false; 991 992 if (VDBG) { 993 Rlog.d(LOG_TAG, " sendDtmf(" + c + ")"); 994 Rlog.d(LOG_TAG, toString()); 995 } 996 997 if (hasActiveFgCall()) { 998 getActiveFgCall().getPhone().sendDtmf(c); 999 result = true; 1000 } 1001 1002 if (VDBG) { 1003 Rlog.d(LOG_TAG, "End sendDtmf(" + c + ")"); 1004 Rlog.d(LOG_TAG, toString()); 1005 } 1006 return result; 1007 } 1008 1009 /** 1010 * Start to paly a DTMF tone on the active call. 1011 * or there is a playing DTMF tone. 1012 * @param c should be one of 0-9, '*' or '#'. Other values will be 1013 * silently ignored. 1014 * 1015 * @return false if no active call or the active call doesn't support 1016 * dtmf tone 1017 */ 1018 public boolean startDtmf(char c) { 1019 boolean result = false; 1020 1021 if (VDBG) { 1022 Rlog.d(LOG_TAG, " startDtmf(" + c + ")"); 1023 Rlog.d(LOG_TAG, toString()); 1024 } 1025 1026 if (hasActiveFgCall()) { 1027 getActiveFgCall().getPhone().startDtmf(c); 1028 result = true; 1029 } 1030 1031 if (VDBG) { 1032 Rlog.d(LOG_TAG, "End startDtmf(" + c + ")"); 1033 Rlog.d(LOG_TAG, toString()); 1034 } 1035 1036 return result; 1037 } 1038 1039 /** 1040 * Stop the playing DTMF tone. Ignored if there is no playing DTMF 1041 * tone or no active call. 1042 */ 1043 public void stopDtmf() { 1044 if (VDBG) { 1045 Rlog.d(LOG_TAG, " stopDtmf()" ); 1046 Rlog.d(LOG_TAG, toString()); 1047 } 1048 1049 if (hasActiveFgCall()) getFgPhone().stopDtmf(); 1050 1051 if (VDBG) { 1052 Rlog.d(LOG_TAG, "End stopDtmf()"); 1053 Rlog.d(LOG_TAG, toString()); 1054 } 1055 } 1056 1057 /** 1058 * send burst DTMF tone, it can send the string as single character or multiple character 1059 * ignore if there is no active call or not valid digits string. 1060 * Valid digit means only includes characters ISO-LATIN characters 0-9, *, # 1061 * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character, 1062 * this api can send single character and multiple character, also, this api has response 1063 * back to caller. 1064 * 1065 * @param dtmfString is string representing the dialing digit(s) in the active call 1066 * @param on the DTMF ON length in milliseconds, or 0 for default 1067 * @param off the DTMF OFF length in milliseconds, or 0 for default 1068 * @param onComplete is the callback message when the action is processed by BP 1069 * 1070 */ 1071 public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 1072 if (hasActiveFgCall()) { 1073 getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete); 1074 return true; 1075 } 1076 return false; 1077 } 1078 1079 /** 1080 * Notifies when a voice connection has disconnected, either due to local 1081 * or remote hangup or error. 1082 * 1083 * Messages received from this will have the following members:<p> 1084 * <ul><li>Message.obj will be an AsyncResult</li> 1085 * <li>AsyncResult.userObj = obj</li> 1086 * <li>AsyncResult.result = a Connection object that is 1087 * no longer connected.</li></ul> 1088 */ 1089 public void registerForDisconnect(Handler h, int what, Object obj) { 1090 mDisconnectRegistrants.addUnique(h, what, obj); 1091 } 1092 1093 /** 1094 * Unregisters for voice disconnection notification. 1095 * Extraneous calls are tolerated silently 1096 */ 1097 public void unregisterForDisconnect(Handler h){ 1098 mDisconnectRegistrants.remove(h); 1099 } 1100 1101 /** 1102 * Register for getting notifications for change in the Call State {@link Call.State} 1103 * This is called PreciseCallState because the call state is more precise than what 1104 * can be obtained using the {@link PhoneStateListener} 1105 * 1106 * Resulting events will have an AsyncResult in <code>Message.obj</code>. 1107 * AsyncResult.userData will be set to the obj argument here. 1108 * The <em>h</em> parameter is held only by a weak reference. 1109 */ 1110 public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){ 1111 mPreciseCallStateRegistrants.addUnique(h, what, obj); 1112 } 1113 1114 /** 1115 * Unregisters for voice call state change notifications. 1116 * Extraneous calls are tolerated silently. 1117 */ 1118 public void unregisterForPreciseCallStateChanged(Handler h){ 1119 mPreciseCallStateRegistrants.remove(h); 1120 } 1121 1122 /** 1123 * Notifies when a previously untracked non-ringing/waiting connection has appeared. 1124 * This is likely due to some other entity (eg, SIM card application) initiating a call. 1125 */ 1126 public void registerForUnknownConnection(Handler h, int what, Object obj){ 1127 mUnknownConnectionRegistrants.addUnique(h, what, obj); 1128 } 1129 1130 /** 1131 * Unregisters for unknown connection notifications. 1132 */ 1133 public void unregisterForUnknownConnection(Handler h){ 1134 mUnknownConnectionRegistrants.remove(h); 1135 } 1136 1137 1138 /** 1139 * Notifies when a new ringing or waiting connection has appeared.<p> 1140 * 1141 * Messages received from this: 1142 * Message.obj will be an AsyncResult 1143 * AsyncResult.userObj = obj 1144 * AsyncResult.result = a Connection. <p> 1145 * Please check Connection.isRinging() to make sure the Connection 1146 * has not dropped since this message was posted. 1147 * If Connection.isRinging() is true, then 1148 * Connection.getCall() == Phone.getRingingCall() 1149 */ 1150 public void registerForNewRingingConnection(Handler h, int what, Object obj){ 1151 mNewRingingConnectionRegistrants.addUnique(h, what, obj); 1152 } 1153 1154 /** 1155 * Unregisters for new ringing connection notification. 1156 * Extraneous calls are tolerated silently 1157 */ 1158 1159 public void unregisterForNewRingingConnection(Handler h){ 1160 mNewRingingConnectionRegistrants.remove(h); 1161 } 1162 1163 /** 1164 * Notifies when an incoming call rings.<p> 1165 * 1166 * Messages received from this: 1167 * Message.obj will be an AsyncResult 1168 * AsyncResult.userObj = obj 1169 * AsyncResult.result = a Connection. <p> 1170 */ 1171 public void registerForIncomingRing(Handler h, int what, Object obj){ 1172 mIncomingRingRegistrants.addUnique(h, what, obj); 1173 } 1174 1175 /** 1176 * Unregisters for ring notification. 1177 * Extraneous calls are tolerated silently 1178 */ 1179 1180 public void unregisterForIncomingRing(Handler h){ 1181 mIncomingRingRegistrants.remove(h); 1182 } 1183 1184 /** 1185 * Notifies when out-band ringback tone is needed.<p> 1186 * 1187 * Messages received from this: 1188 * Message.obj will be an AsyncResult 1189 * AsyncResult.userObj = obj 1190 * AsyncResult.result = boolean, true to start play ringback tone 1191 * and false to stop. <p> 1192 */ 1193 public void registerForRingbackTone(Handler h, int what, Object obj){ 1194 mRingbackToneRegistrants.addUnique(h, what, obj); 1195 } 1196 1197 /** 1198 * Unregisters for ringback tone notification. 1199 */ 1200 1201 public void unregisterForRingbackTone(Handler h){ 1202 mRingbackToneRegistrants.remove(h); 1203 } 1204 1205 /** 1206 * Registers the handler to reset the uplink mute state to get 1207 * uplink audio. 1208 */ 1209 public void registerForResendIncallMute(Handler h, int what, Object obj){ 1210 mResendIncallMuteRegistrants.addUnique(h, what, obj); 1211 } 1212 1213 /** 1214 * Unregisters for resend incall mute notifications. 1215 */ 1216 public void unregisterForResendIncallMute(Handler h){ 1217 mResendIncallMuteRegistrants.remove(h); 1218 } 1219 1220 /** 1221 * Register for notifications of initiation of a new MMI code request. 1222 * MMI codes for GSM are discussed in 3GPP TS 22.030.<p> 1223 * 1224 * Example: If Phone.dial is called with "*#31#", then the app will 1225 * be notified here.<p> 1226 * 1227 * The returned <code>Message.obj</code> will contain an AsyncResult. 1228 * 1229 * <code>obj.result</code> will be an "MmiCode" object. 1230 */ 1231 public void registerForMmiInitiate(Handler h, int what, Object obj){ 1232 mMmiInitiateRegistrants.addUnique(h, what, obj); 1233 } 1234 1235 /** 1236 * Unregisters for new MMI initiate notification. 1237 * Extraneous calls are tolerated silently 1238 */ 1239 public void unregisterForMmiInitiate(Handler h){ 1240 mMmiInitiateRegistrants.remove(h); 1241 } 1242 1243 /** 1244 * Register for notifications that an MMI request has completed 1245 * its network activity and is in its final state. This may mean a state 1246 * of COMPLETE, FAILED, or CANCELLED. 1247 * 1248 * <code>Message.obj</code> will contain an AsyncResult. 1249 * <code>obj.result</code> will be an "MmiCode" object 1250 */ 1251 public void registerForMmiComplete(Handler h, int what, Object obj){ 1252 mMmiCompleteRegistrants.addUnique(h, what, obj); 1253 } 1254 1255 /** 1256 * Unregisters for MMI complete notification. 1257 * Extraneous calls are tolerated silently 1258 */ 1259 public void unregisterForMmiComplete(Handler h){ 1260 mMmiCompleteRegistrants.remove(h); 1261 } 1262 1263 /** 1264 * Registration point for Ecm timer reset 1265 * @param h handler to notify 1266 * @param what user-defined message code 1267 * @param obj placed in Message.obj 1268 */ 1269 public void registerForEcmTimerReset(Handler h, int what, Object obj){ 1270 mEcmTimerResetRegistrants.addUnique(h, what, obj); 1271 } 1272 1273 /** 1274 * Unregister for notification for Ecm timer reset 1275 * @param h Handler to be removed from the registrant list. 1276 */ 1277 public void unregisterForEcmTimerReset(Handler h){ 1278 mEcmTimerResetRegistrants.remove(h); 1279 } 1280 1281 /** 1282 * Register for ServiceState changed. 1283 * Message.obj will contain an AsyncResult. 1284 * AsyncResult.result will be a ServiceState instance 1285 */ 1286 public void registerForServiceStateChanged(Handler h, int what, Object obj){ 1287 mServiceStateChangedRegistrants.addUnique(h, what, obj); 1288 } 1289 1290 /** 1291 * Unregisters for ServiceStateChange notification. 1292 * Extraneous calls are tolerated silently 1293 */ 1294 public void unregisterForServiceStateChanged(Handler h){ 1295 mServiceStateChangedRegistrants.remove(h); 1296 } 1297 1298 /** 1299 * Register for notifications when a supplementary service attempt fails. 1300 * Message.obj will contain an AsyncResult. 1301 * 1302 * @param h Handler that receives the notification message. 1303 * @param what User-defined message code. 1304 * @param obj User object. 1305 */ 1306 public void registerForSuppServiceFailed(Handler h, int what, Object obj){ 1307 mSuppServiceFailedRegistrants.addUnique(h, what, obj); 1308 } 1309 1310 /** 1311 * Unregister for notifications when a supplementary service attempt fails. 1312 * Extraneous calls are tolerated silently 1313 * 1314 * @param h Handler to be removed from the registrant list. 1315 */ 1316 public void unregisterForSuppServiceFailed(Handler h){ 1317 mSuppServiceFailedRegistrants.remove(h); 1318 } 1319 1320 /** 1321 * Register for notifications when a sInCall VoicePrivacy is enabled 1322 * 1323 * @param h Handler that receives the notification message. 1324 * @param what User-defined message code. 1325 * @param obj User object. 1326 */ 1327 public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){ 1328 mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj); 1329 } 1330 1331 /** 1332 * Unregister for notifications when a sInCall VoicePrivacy is enabled 1333 * 1334 * @param h Handler to be removed from the registrant list. 1335 */ 1336 public void unregisterForInCallVoicePrivacyOn(Handler h){ 1337 mInCallVoicePrivacyOnRegistrants.remove(h); 1338 } 1339 1340 /** 1341 * Register for notifications when a sInCall VoicePrivacy is disabled 1342 * 1343 * @param h Handler that receives the notification message. 1344 * @param what User-defined message code. 1345 * @param obj User object. 1346 */ 1347 public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){ 1348 mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj); 1349 } 1350 1351 /** 1352 * Unregister for notifications when a sInCall VoicePrivacy is disabled 1353 * 1354 * @param h Handler to be removed from the registrant list. 1355 */ 1356 public void unregisterForInCallVoicePrivacyOff(Handler h){ 1357 mInCallVoicePrivacyOffRegistrants.remove(h); 1358 } 1359 1360 /** 1361 * Register for notifications when CDMA call waiting comes 1362 * 1363 * @param h Handler that receives the notification message. 1364 * @param what User-defined message code. 1365 * @param obj User object. 1366 */ 1367 public void registerForCallWaiting(Handler h, int what, Object obj){ 1368 mCallWaitingRegistrants.addUnique(h, what, obj); 1369 } 1370 1371 /** 1372 * Unregister for notifications when CDMA Call waiting comes 1373 * @param h Handler to be removed from the registrant list. 1374 */ 1375 public void unregisterForCallWaiting(Handler h){ 1376 mCallWaitingRegistrants.remove(h); 1377 } 1378 1379 1380 /** 1381 * Register for signal information notifications from the network. 1382 * Message.obj will contain an AsyncResult. 1383 * AsyncResult.result will be a SuppServiceNotification instance. 1384 * 1385 * @param h Handler that receives the notification message. 1386 * @param what User-defined message code. 1387 * @param obj User object. 1388 */ 1389 1390 public void registerForSignalInfo(Handler h, int what, Object obj){ 1391 mSignalInfoRegistrants.addUnique(h, what, obj); 1392 } 1393 1394 /** 1395 * Unregisters for signal information notifications. 1396 * Extraneous calls are tolerated silently 1397 * 1398 * @param h Handler to be removed from the registrant list. 1399 */ 1400 public void unregisterForSignalInfo(Handler h){ 1401 mSignalInfoRegistrants.remove(h); 1402 } 1403 1404 /** 1405 * Register for display information notifications from the network. 1406 * Message.obj will contain an AsyncResult. 1407 * AsyncResult.result will be a SuppServiceNotification instance. 1408 * 1409 * @param h Handler that receives the notification message. 1410 * @param what User-defined message code. 1411 * @param obj User object. 1412 */ 1413 public void registerForDisplayInfo(Handler h, int what, Object obj){ 1414 mDisplayInfoRegistrants.addUnique(h, what, obj); 1415 } 1416 1417 /** 1418 * Unregisters for display information notifications. 1419 * Extraneous calls are tolerated silently 1420 * 1421 * @param h Handler to be removed from the registrant list. 1422 */ 1423 public void unregisterForDisplayInfo(Handler h) { 1424 mDisplayInfoRegistrants.remove(h); 1425 } 1426 1427 /** 1428 * Register for notifications when CDMA OTA Provision status change 1429 * 1430 * @param h Handler that receives the notification message. 1431 * @param what User-defined message code. 1432 * @param obj User object. 1433 */ 1434 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){ 1435 mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj); 1436 } 1437 1438 /** 1439 * Unregister for notifications when CDMA OTA Provision status change 1440 * @param h Handler to be removed from the registrant list. 1441 */ 1442 public void unregisterForCdmaOtaStatusChange(Handler h){ 1443 mCdmaOtaStatusChangeRegistrants.remove(h); 1444 } 1445 1446 /** 1447 * Registration point for subscription info ready 1448 * @param h handler to notify 1449 * @param what what code of message when delivered 1450 * @param obj placed in Message.obj 1451 */ 1452 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){ 1453 mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj); 1454 } 1455 1456 /** 1457 * Unregister for notifications for subscription info 1458 * @param h Handler to be removed from the registrant list. 1459 */ 1460 public void unregisterForSubscriptionInfoReady(Handler h){ 1461 mSubscriptionInfoReadyRegistrants.remove(h); 1462 } 1463 1464 /** 1465 * Sets an event to be fired when the telephony system processes 1466 * a post-dial character on an outgoing call.<p> 1467 * 1468 * Messages of type <code>what</code> will be sent to <code>h</code>. 1469 * The <code>obj</code> field of these Message's will be instances of 1470 * <code>AsyncResult</code>. <code>Message.obj.result</code> will be 1471 * a Connection object.<p> 1472 * 1473 * Message.arg1 will be the post dial character being processed, 1474 * or 0 ('\0') if end of string.<p> 1475 * 1476 * If Connection.getPostDialState() == WAIT, 1477 * the application must call 1478 * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar() 1479 * Connection.proceedAfterWaitChar()} or 1480 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1481 * Connection.cancelPostDial()} 1482 * for the telephony system to continue playing the post-dial 1483 * DTMF sequence.<p> 1484 * 1485 * If Connection.getPostDialState() == WILD, 1486 * the application must call 1487 * {@link com.android.internal.telephony.Connection#proceedAfterWildChar 1488 * Connection.proceedAfterWildChar()} 1489 * or 1490 * {@link com.android.internal.telephony.Connection#cancelPostDial() 1491 * Connection.cancelPostDial()} 1492 * for the telephony system to continue playing the 1493 * post-dial DTMF sequence.<p> 1494 * 1495 */ 1496 public void registerForPostDialCharacter(Handler h, int what, Object obj){ 1497 mPostDialCharacterRegistrants.addUnique(h, what, obj); 1498 } 1499 1500 public void unregisterForPostDialCharacter(Handler h){ 1501 mPostDialCharacterRegistrants.remove(h); 1502 } 1503 1504 /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls 1505 * 1. APIs to access list of calls 1506 * 2. APIs to check if any active call, which has connection other than 1507 * disconnected ones, pleaser refer to Call.isIdle() 1508 * 3. APIs to return first active call 1509 * 4. APIs to return the connections of first active call 1510 * 5. APIs to return other property of first active call 1511 */ 1512 1513 /** 1514 * @return list of all ringing calls 1515 */ 1516 public List<Call> getRingingCalls() { 1517 return Collections.unmodifiableList(mRingingCalls); 1518 } 1519 1520 /** 1521 * @return list of all foreground calls 1522 */ 1523 public List<Call> getForegroundCalls() { 1524 return Collections.unmodifiableList(mForegroundCalls); 1525 } 1526 1527 /** 1528 * @return list of all background calls 1529 */ 1530 public List<Call> getBackgroundCalls() { 1531 return Collections.unmodifiableList(mBackgroundCalls); 1532 } 1533 1534 /** 1535 * Return true if there is at least one active foreground call 1536 */ 1537 public boolean hasActiveFgCall() { 1538 return (getFirstActiveCall(mForegroundCalls) != null); 1539 } 1540 1541 /** 1542 * Return true if there is at least one active background call 1543 */ 1544 public boolean hasActiveBgCall() { 1545 // TODO since hasActiveBgCall may get called often 1546 // better to cache it to improve performance 1547 return (getFirstActiveCall(mBackgroundCalls) != null); 1548 } 1549 1550 /** 1551 * Return true if there is at least one active ringing call 1552 * 1553 */ 1554 public boolean hasActiveRingingCall() { 1555 return (getFirstActiveCall(mRingingCalls) != null); 1556 } 1557 1558 /** 1559 * return the active foreground call from foreground calls 1560 * 1561 * Active call means the call is NOT in Call.State.IDLE 1562 * 1563 * 1. If there is active foreground call, return it 1564 * 2. If there is no active foreground call, return the 1565 * foreground call associated with default phone, which state is IDLE. 1566 * 3. If there is no phone registered at all, return null. 1567 * 1568 */ 1569 public Call getActiveFgCall() { 1570 Call call = getFirstNonIdleCall(mForegroundCalls); 1571 if (call == null) { 1572 call = (mDefaultPhone == null) 1573 ? null 1574 : mDefaultPhone.getForegroundCall(); 1575 } 1576 return call; 1577 } 1578 1579 // Returns the first call that is not in IDLE state. If both active calls 1580 // and disconnecting/disconnected calls exist, return the first active call. 1581 private Call getFirstNonIdleCall(List<Call> calls) { 1582 Call result = null; 1583 for (Call call : calls) { 1584 if (!call.isIdle()) { 1585 return call; 1586 } else if (call.getState() != Call.State.IDLE) { 1587 if (result == null) result = call; 1588 } 1589 } 1590 return result; 1591 } 1592 1593 /** 1594 * return one active background call from background calls 1595 * 1596 * Active call means the call is NOT idle defined by Call.isIdle() 1597 * 1598 * 1. If there is only one active background call, return it 1599 * 2. If there is more than one active background call, return the first one 1600 * 3. If there is no active background call, return the background call 1601 * associated with default phone, which state is IDLE. 1602 * 4. If there is no background call at all, return null. 1603 * 1604 * Complete background calls list can be get by getBackgroundCalls() 1605 */ 1606 public Call getFirstActiveBgCall() { 1607 Call call = getFirstNonIdleCall(mBackgroundCalls); 1608 if (call == null) { 1609 call = (mDefaultPhone == null) 1610 ? null 1611 : mDefaultPhone.getBackgroundCall(); 1612 } 1613 return call; 1614 } 1615 1616 /** 1617 * return one active ringing call from ringing calls 1618 * 1619 * Active call means the call is NOT idle defined by Call.isIdle() 1620 * 1621 * 1. If there is only one active ringing call, return it 1622 * 2. If there is more than one active ringing call, return the first one 1623 * 3. If there is no active ringing call, return the ringing call 1624 * associated with default phone, which state is IDLE. 1625 * 4. If there is no ringing call at all, return null. 1626 * 1627 * Complete ringing calls list can be get by getRingingCalls() 1628 */ 1629 public Call getFirstActiveRingingCall() { 1630 Call call = getFirstNonIdleCall(mRingingCalls); 1631 if (call == null) { 1632 call = (mDefaultPhone == null) 1633 ? null 1634 : mDefaultPhone.getRingingCall(); 1635 } 1636 return call; 1637 } 1638 1639 /** 1640 * @return the state of active foreground call 1641 * return IDLE if there is no active foreground call 1642 */ 1643 public Call.State getActiveFgCallState() { 1644 Call fgCall = getActiveFgCall(); 1645 1646 if (fgCall != null) { 1647 return fgCall.getState(); 1648 } 1649 1650 return Call.State.IDLE; 1651 } 1652 1653 /** 1654 * @return the connections of active foreground call 1655 * return empty list if there is no active foreground call 1656 */ 1657 public List<Connection> getFgCallConnections() { 1658 Call fgCall = getActiveFgCall(); 1659 if ( fgCall != null) { 1660 return fgCall.getConnections(); 1661 } 1662 return mEmptyConnections; 1663 } 1664 1665 /** 1666 * @return the connections of active background call 1667 * return empty list if there is no active background call 1668 */ 1669 public List<Connection> getBgCallConnections() { 1670 Call bgCall = getFirstActiveBgCall(); 1671 if ( bgCall != null) { 1672 return bgCall.getConnections(); 1673 } 1674 return mEmptyConnections; 1675 } 1676 1677 /** 1678 * @return the latest connection of active foreground call 1679 * return null if there is no active foreground call 1680 */ 1681 public Connection getFgCallLatestConnection() { 1682 Call fgCall = getActiveFgCall(); 1683 if ( fgCall != null) { 1684 return fgCall.getLatestConnection(); 1685 } 1686 return null; 1687 } 1688 1689 /** 1690 * @return true if there is at least one Foreground call in disconnected state 1691 */ 1692 public boolean hasDisconnectedFgCall() { 1693 return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null); 1694 } 1695 1696 /** 1697 * @return true if there is at least one background call in disconnected state 1698 */ 1699 public boolean hasDisconnectedBgCall() { 1700 return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null); 1701 } 1702 1703 /** 1704 * @return the first active call from a call list 1705 */ 1706 private Call getFirstActiveCall(ArrayList<Call> calls) { 1707 for (Call call : calls) { 1708 if (!call.isIdle()) { 1709 return call; 1710 } 1711 } 1712 return null; 1713 } 1714 1715 /** 1716 * @return the first call in a the Call.state from a call list 1717 */ 1718 private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) { 1719 for (Call call : calls) { 1720 if (call.getState() == state) { 1721 return call; 1722 } 1723 } 1724 return null; 1725 } 1726 1727 1728 private boolean hasMoreThanOneRingingCall() { 1729 int count = 0; 1730 for (Call call : mRingingCalls) { 1731 if (call.getState().isRinging()) { 1732 if (++count > 1) return true; 1733 } 1734 } 1735 return false; 1736 } 1737 1738 private Handler mHandler = new Handler() { 1739 1740 @Override 1741 public void handleMessage(Message msg) { 1742 1743 switch (msg.what) { 1744 case EVENT_DISCONNECT: 1745 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)"); 1746 mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1747 break; 1748 case EVENT_PRECISE_CALL_STATE_CHANGED: 1749 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)"); 1750 mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1751 break; 1752 case EVENT_NEW_RINGING_CONNECTION: 1753 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)"); 1754 if (getActiveFgCallState().isDialing() || hasMoreThanOneRingingCall()) { 1755 Connection c = (Connection) ((AsyncResult) msg.obj).result; 1756 try { 1757 Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall()); 1758 c.getCall().hangup(); 1759 } catch (CallStateException e) { 1760 Rlog.w(LOG_TAG, "new ringing connection", e); 1761 } 1762 } else { 1763 mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1764 } 1765 break; 1766 case EVENT_UNKNOWN_CONNECTION: 1767 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)"); 1768 mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1769 break; 1770 case EVENT_INCOMING_RING: 1771 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)"); 1772 // The event may come from RIL who's not aware of an ongoing fg call 1773 if (!hasActiveFgCall()) { 1774 mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1775 } 1776 break; 1777 case EVENT_RINGBACK_TONE: 1778 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)"); 1779 mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1780 break; 1781 case EVENT_IN_CALL_VOICE_PRIVACY_ON: 1782 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)"); 1783 mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1784 break; 1785 case EVENT_IN_CALL_VOICE_PRIVACY_OFF: 1786 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)"); 1787 mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1788 break; 1789 case EVENT_CALL_WAITING: 1790 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)"); 1791 mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1792 break; 1793 case EVENT_DISPLAY_INFO: 1794 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)"); 1795 mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1796 break; 1797 case EVENT_SIGNAL_INFO: 1798 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)"); 1799 mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1800 break; 1801 case EVENT_CDMA_OTA_STATUS_CHANGE: 1802 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)"); 1803 mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1804 break; 1805 case EVENT_RESEND_INCALL_MUTE: 1806 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)"); 1807 mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1808 break; 1809 case EVENT_MMI_INITIATE: 1810 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)"); 1811 mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1812 break; 1813 case EVENT_MMI_COMPLETE: 1814 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)"); 1815 mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1816 break; 1817 case EVENT_ECM_TIMER_RESET: 1818 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)"); 1819 mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1820 break; 1821 case EVENT_SUBSCRIPTION_INFO_READY: 1822 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)"); 1823 mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1824 break; 1825 case EVENT_SUPP_SERVICE_FAILED: 1826 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)"); 1827 mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1828 break; 1829 case EVENT_SERVICE_STATE_CHANGED: 1830 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)"); 1831 mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj); 1832 break; 1833 case EVENT_POST_DIAL_CHARACTER: 1834 // we need send the character that is being processed in msg.arg1 1835 // so can't use notifyRegistrants() 1836 if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)"); 1837 for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) { 1838 Message notifyMsg; 1839 notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant(); 1840 notifyMsg.obj = msg.obj; 1841 notifyMsg.arg1 = msg.arg1; 1842 notifyMsg.sendToTarget(); 1843 } 1844 break; 1845 } 1846 } 1847 }; 1848 1849 @Override 1850 public String toString() { 1851 Call call; 1852 StringBuilder b = new StringBuilder(); 1853 1854 b.append("CallManager {"); 1855 b.append("\nstate = " + getState()); 1856 call = getActiveFgCall(); 1857 b.append("\n- Foreground: " + getActiveFgCallState()); 1858 b.append(" from " + call.getPhone()); 1859 b.append("\n Conn: ").append(getFgCallConnections()); 1860 call = getFirstActiveBgCall(); 1861 b.append("\n- Background: " + call.getState()); 1862 b.append(" from " + call.getPhone()); 1863 b.append("\n Conn: ").append(getBgCallConnections()); 1864 call = getFirstActiveRingingCall(); 1865 b.append("\n- Ringing: " +call.getState()); 1866 b.append(" from " + call.getPhone()); 1867 1868 for (Phone phone : getAllPhones()) { 1869 if (phone != null) { 1870 b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName() 1871 + ", state = " + phone.getState()); 1872 call = phone.getForegroundCall(); 1873 b.append("\n- Foreground: ").append(call); 1874 call = phone.getBackgroundCall(); 1875 b.append(" Background: ").append(call); 1876 call = phone.getRingingCall(); 1877 b.append(" Ringing: ").append(call); 1878 } 1879 } 1880 b.append("\n}"); 1881 return b.toString(); 1882 } 1883 } 1884