1 /* 2 * Copyright (C) 2006 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 android.annotation.UnsupportedAppUsage; 20 import android.net.Uri; 21 import android.os.Bundle; 22 import android.os.SystemClock; 23 import android.telecom.ConferenceParticipant; 24 import android.telephony.DisconnectCause; 25 import android.telephony.Rlog; 26 import android.telephony.ServiceState; 27 import android.telephony.emergency.EmergencyNumber; 28 import android.util.Log; 29 30 import com.android.internal.telephony.emergency.EmergencyNumberTracker; 31 32 import java.util.ArrayList; 33 import java.util.List; 34 import java.util.Set; 35 import java.util.concurrent.CopyOnWriteArraySet; 36 37 /** 38 * {@hide} 39 */ 40 public abstract class Connection { 41 private static final String TAG = "Connection"; 42 43 public interface PostDialListener { onPostDialWait()44 void onPostDialWait(); onPostDialChar(char c)45 void onPostDialChar(char c); 46 } 47 48 /** 49 * Capabilities that will be mapped to telecom connection 50 * capabilities. 51 */ 52 public static class Capability { 53 54 /** 55 * For an IMS video call, indicates that the local side of the call supports downgrading 56 * from a video call to an audio-only call. 57 */ 58 public static final int SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL = 0x00000001; 59 60 /** 61 * For an IMS video call, indicates that the peer supports downgrading to an audio-only 62 * call. 63 */ 64 public static final int SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE = 0x00000002; 65 66 /** 67 * For an IMS call, indicates that the call supports video locally. 68 */ 69 public static final int SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 0x00000004; 70 71 /** 72 * For an IMS call, indicates that the peer supports video. 73 */ 74 public static final int SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 0x00000008; 75 76 /** 77 * Indicates that the connection is an external connection (e.g. an instance of the class 78 * {@link com.android.internal.telephony.imsphone.ImsExternalConnection}. 79 */ 80 public static final int IS_EXTERNAL_CONNECTION = 0x00000010; 81 82 /** 83 * Indicates that this external connection can be pulled from the remote device to the 84 * local device. 85 */ 86 public static final int IS_PULLABLE = 0x00000020; 87 } 88 89 /** 90 * Listener interface for events related to the connection which should be reported to the 91 * {@link android.telecom.Connection}. 92 */ 93 public interface Listener { onVideoStateChanged(int videoState)94 public void onVideoStateChanged(int videoState); onConnectionCapabilitiesChanged(int capability)95 public void onConnectionCapabilitiesChanged(int capability); onCallRadioTechChanged(@erviceState.RilRadioTechnology int vrat)96 public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat); onVideoProviderChanged( android.telecom.Connection.VideoProvider videoProvider)97 public void onVideoProviderChanged( 98 android.telecom.Connection.VideoProvider videoProvider); onAudioQualityChanged(int audioQuality)99 public void onAudioQualityChanged(int audioQuality); onConferenceParticipantsChanged(List<ConferenceParticipant> participants)100 public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants); onCallSubstateChanged(int callSubstate)101 public void onCallSubstateChanged(int callSubstate); onMultipartyStateChanged(boolean isMultiParty)102 public void onMultipartyStateChanged(boolean isMultiParty); onConferenceMergedFailed()103 public void onConferenceMergedFailed(); onExtrasChanged(Bundle extras)104 public void onExtrasChanged(Bundle extras); onExitedEcmMode()105 public void onExitedEcmMode(); onCallPullFailed(Connection externalConnection)106 public void onCallPullFailed(Connection externalConnection); onHandoverToWifiFailed()107 public void onHandoverToWifiFailed(); onConnectionEvent(String event, Bundle extras)108 public void onConnectionEvent(String event, Bundle extras); onRttModifyRequestReceived()109 public void onRttModifyRequestReceived(); onRttModifyResponseReceived(int status)110 public void onRttModifyResponseReceived(int status); onDisconnect(int cause)111 public void onDisconnect(int cause); onRttInitiated()112 public void onRttInitiated(); onRttTerminated()113 public void onRttTerminated(); onOriginalConnectionReplaced(Connection newConnection)114 public void onOriginalConnectionReplaced(Connection newConnection); onIsNetworkEmergencyCallChanged(boolean isEmergencyCall)115 public void onIsNetworkEmergencyCallChanged(boolean isEmergencyCall); 116 } 117 118 /** 119 * Base listener implementation. 120 */ 121 public abstract static class ListenerBase implements Listener { 122 @Override onVideoStateChanged(int videoState)123 public void onVideoStateChanged(int videoState) {} 124 @Override onConnectionCapabilitiesChanged(int capability)125 public void onConnectionCapabilitiesChanged(int capability) {} 126 @Override onCallRadioTechChanged(@erviceState.RilRadioTechnology int vrat)127 public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat) {} 128 @Override onVideoProviderChanged( android.telecom.Connection.VideoProvider videoProvider)129 public void onVideoProviderChanged( 130 android.telecom.Connection.VideoProvider videoProvider) {} 131 @Override onAudioQualityChanged(int audioQuality)132 public void onAudioQualityChanged(int audioQuality) {} 133 @Override onConferenceParticipantsChanged(List<ConferenceParticipant> participants)134 public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {} 135 @Override onCallSubstateChanged(int callSubstate)136 public void onCallSubstateChanged(int callSubstate) {} 137 @Override onMultipartyStateChanged(boolean isMultiParty)138 public void onMultipartyStateChanged(boolean isMultiParty) {} 139 @Override onConferenceMergedFailed()140 public void onConferenceMergedFailed() {} 141 @Override onExtrasChanged(Bundle extras)142 public void onExtrasChanged(Bundle extras) {} 143 @Override onExitedEcmMode()144 public void onExitedEcmMode() {} 145 @Override onCallPullFailed(Connection externalConnection)146 public void onCallPullFailed(Connection externalConnection) {} 147 @Override onHandoverToWifiFailed()148 public void onHandoverToWifiFailed() {} 149 @Override onConnectionEvent(String event, Bundle extras)150 public void onConnectionEvent(String event, Bundle extras) {} 151 @Override onRttModifyRequestReceived()152 public void onRttModifyRequestReceived() {} 153 @Override onRttModifyResponseReceived(int status)154 public void onRttModifyResponseReceived(int status) {} 155 @Override onDisconnect(int cause)156 public void onDisconnect(int cause) {} 157 @Override onRttInitiated()158 public void onRttInitiated() {} 159 @Override onRttTerminated()160 public void onRttTerminated() {} 161 @Override onOriginalConnectionReplaced(Connection newConnection)162 public void onOriginalConnectionReplaced(Connection newConnection) {} 163 @Override onIsNetworkEmergencyCallChanged(boolean isEmergencyCall)164 public void onIsNetworkEmergencyCallChanged(boolean isEmergencyCall) {} 165 } 166 167 public static final int AUDIO_QUALITY_STANDARD = 1; 168 public static final int AUDIO_QUALITY_HIGH_DEFINITION = 2; 169 170 /** 171 * The telecom internal call ID associated with this connection. Only to be used for debugging 172 * purposes. 173 */ 174 private String mTelecomCallId; 175 176 //Caller Name Display 177 @UnsupportedAppUsage 178 protected String mCnapName; 179 @UnsupportedAppUsage 180 protected int mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED; 181 @UnsupportedAppUsage 182 protected String mAddress; // MAY BE NULL!!! 183 @UnsupportedAppUsage 184 protected String mDialString; // outgoing calls only 185 @UnsupportedAppUsage 186 protected int mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED; 187 @UnsupportedAppUsage 188 protected boolean mIsIncoming; 189 /* 190 * These time/timespan values are based on System.currentTimeMillis(), 191 * i.e., "wall clock" time. 192 */ 193 protected long mCreateTime; 194 protected long mConnectTime; 195 /* 196 * These time/timespan values are based on SystemClock.elapsedRealTime(), 197 * i.e., time since boot. They are appropriate for comparison and 198 * calculating deltas. 199 */ 200 protected long mConnectTimeReal; 201 @UnsupportedAppUsage 202 protected long mDuration; 203 protected long mHoldingStartTime; // The time when the Connection last transitioned 204 // into HOLDING 205 protected Connection mOrigConnection; 206 private List<PostDialListener> mPostDialListeners = new ArrayList<>(); 207 public Set<Listener> mListeners = new CopyOnWriteArraySet<>(); 208 209 protected boolean mNumberConverted = false; 210 protected String mConvertedNumber; 211 212 protected String mPostDialString; // outgoing calls only 213 protected int mNextPostDialChar; // index into postDialString 214 215 protected int mCause = DisconnectCause.NOT_DISCONNECTED; 216 protected PostDialState mPostDialState = PostDialState.NOT_STARTED; 217 218 @UnsupportedAppUsage 219 private static String LOG_TAG = "Connection"; 220 221 Object mUserData; 222 private int mVideoState; 223 private int mConnectionCapabilities; 224 /** 225 * Determines the call radio technology for current connection. 226 * 227 * This is used to propagate the call radio technology to upper layer. 228 */ 229 private @ServiceState.RilRadioTechnology int mCallRadioTech = 230 ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; 231 private boolean mAudioModeIsVoip; 232 private int mAudioQuality; 233 private int mCallSubstate; 234 private android.telecom.Connection.VideoProvider mVideoProvider; 235 public Call.State mPreHandoverState = Call.State.IDLE; 236 private Bundle mExtras; 237 private int mPhoneType; 238 private boolean mAnsweringDisconnectsActiveCall; 239 private boolean mAllowAddCallDuringVideoCall; 240 241 private boolean mIsEmergencyCall; 242 243 /** 244 * The emergency number information, only valid if {@link #isEmergencyCall} returns 245 * {@code true}. 246 */ 247 private EmergencyNumber mEmergencyNumberInfo; 248 249 /** 250 * Whether the call is from emergency dialer, only valid if {@link #isEmergencyCall} returns 251 * {@code true}. 252 */ 253 private boolean mHasKnownUserIntentEmergency; 254 255 /** 256 * When {@code true}, the network has indicated that this is an emergency call. 257 */ 258 private boolean mIsNetworkIdentifiedEmergencyCall; 259 260 /** 261 * Used to indicate that this originated from pulling a {@link android.telecom.Connection} with 262 * {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL}. 263 */ 264 private boolean mIsPulledCall = false; 265 266 /** 267 * Where {@link #mIsPulledCall} is {@code true}, contains the dialog Id of the external call 268 * which is being pulled (e.g. 269 * {@link com.android.internal.telephony.imsphone.ImsExternalConnection#getCallId()}). 270 */ 271 private int mPulledDialogId; 272 273 @UnsupportedAppUsage Connection(int phoneType)274 protected Connection(int phoneType) { 275 mPhoneType = phoneType; 276 } 277 278 /* Instance Methods */ 279 280 /** 281 * @return The telecom internal call ID associated with this connection. Only to be used for 282 * debugging purposes. 283 */ getTelecomCallId()284 public String getTelecomCallId() { 285 return mTelecomCallId; 286 } 287 288 /** 289 * Sets the telecom call ID associated with this connection. 290 * 291 * @param telecomCallId The telecom call ID. 292 */ setTelecomCallId(String telecomCallId)293 public void setTelecomCallId(String telecomCallId) { 294 mTelecomCallId = telecomCallId; 295 } 296 297 /** 298 * Gets address (e.g. phone number) associated with connection. 299 * TODO: distinguish reasons for unavailability 300 * 301 * @return address or null if unavailable 302 */ 303 304 @UnsupportedAppUsage getAddress()305 public String getAddress() { 306 return mAddress; 307 } 308 309 /** 310 * Gets CNAP name associated with connection. 311 * @return cnap name or null if unavailable 312 */ getCnapName()313 public String getCnapName() { 314 return mCnapName; 315 } 316 317 /** 318 * Get original dial string. 319 * @return original dial string or null if unavailable 320 */ getOrigDialString()321 public String getOrigDialString(){ 322 return null; 323 } 324 325 /** 326 * Gets CNAP presentation associated with connection. 327 * @return cnap name or null if unavailable 328 */ 329 getCnapNamePresentation()330 public int getCnapNamePresentation() { 331 return mCnapNamePresentation; 332 } 333 334 /** 335 * @return Call that owns this Connection, or null if none 336 */ 337 @UnsupportedAppUsage getCall()338 public abstract Call getCall(); 339 340 /** 341 * Connection create time in currentTimeMillis() format 342 * Basically, set when object is created. 343 * Effectively, when an incoming call starts ringing or an 344 * outgoing call starts dialing 345 */ 346 @UnsupportedAppUsage getCreateTime()347 public long getCreateTime() { 348 return mCreateTime; 349 } 350 351 /** 352 * Connection connect time in currentTimeMillis() format. 353 * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition. 354 * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition. 355 * Returns 0 before then. 356 */ 357 @UnsupportedAppUsage getConnectTime()358 public long getConnectTime() { 359 return mConnectTime; 360 } 361 362 /** 363 * Sets the Connection connect time in currentTimeMillis() format. 364 * 365 * @param connectTime the new connect time. 366 */ setConnectTime(long connectTime)367 public void setConnectTime(long connectTime) { 368 mConnectTime = connectTime; 369 } 370 371 /** 372 * Sets the Connection connect time in {@link SystemClock#elapsedRealtime()} format. 373 * 374 * @param connectTimeReal the new connect time. 375 */ setConnectTimeReal(long connectTimeReal)376 public void setConnectTimeReal(long connectTimeReal) { 377 mConnectTimeReal = connectTimeReal; 378 } 379 380 /** 381 * Connection connect time in elapsedRealtime() format. 382 * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition. 383 * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition. 384 * Returns 0 before then. 385 */ getConnectTimeReal()386 public long getConnectTimeReal() { 387 return mConnectTimeReal; 388 } 389 390 /** 391 * Disconnect time in currentTimeMillis() format. 392 * The time when this Connection makes a transition into ENDED or FAIL. 393 * Returns 0 before then. 394 */ 395 @UnsupportedAppUsage getDisconnectTime()396 public abstract long getDisconnectTime(); 397 398 /** 399 * Returns the number of milliseconds the call has been connected, 400 * or 0 if the call has never connected. 401 * If the call is still connected, then returns the elapsed 402 * time since connect. 403 */ 404 @UnsupportedAppUsage getDurationMillis()405 public long getDurationMillis() { 406 if (mConnectTimeReal == 0) { 407 return 0; 408 } else if (mDuration == 0) { 409 return SystemClock.elapsedRealtime() - mConnectTimeReal; 410 } else { 411 return mDuration; 412 } 413 } 414 415 /** 416 * The time when this Connection last transitioned into HOLDING 417 * in elapsedRealtime() format. 418 * Returns 0, if it has never made a transition into HOLDING. 419 */ getHoldingStartTime()420 public long getHoldingStartTime() { 421 return mHoldingStartTime; 422 } 423 424 /** 425 * If this connection is HOLDING, return the number of milliseconds 426 * that it has been on hold for (approximately). 427 * If this connection is in any other state, return 0. 428 */ 429 getHoldDurationMillis()430 public abstract long getHoldDurationMillis(); 431 432 /** 433 * Returns call disconnect cause. Values are defined in 434 * {@link android.telephony.DisconnectCause}. If the call is not yet 435 * disconnected, NOT_DISCONNECTED is returned. 436 */ 437 @UnsupportedAppUsage getDisconnectCause()438 public int getDisconnectCause() { 439 return mCause; 440 } 441 442 /** 443 * Returns a string disconnect cause which is from vendor. 444 * Vendors may use this string to explain the underline causes of failed calls. 445 * There is no guarantee that it is non-null nor it'll have meaningful stable values. 446 * Only use it when getDisconnectCause() returns a value that is not specific enough, like 447 * ERROR_UNSPECIFIED. 448 */ getVendorDisconnectCause()449 public abstract String getVendorDisconnectCause(); 450 451 /** 452 * Returns true of this connection originated elsewhere 453 * ("MT" or mobile terminated; another party called this terminal) 454 * or false if this call originated here (MO or mobile originated). 455 */ 456 @UnsupportedAppUsage isIncoming()457 public boolean isIncoming() { 458 return mIsIncoming; 459 } 460 461 /** 462 * Sets whether this call is an incoming call or not. 463 * @param isIncoming {@code true} if the call is an incoming call, {@code false} if it is an 464 * outgoing call. 465 */ setIsIncoming(boolean isIncoming)466 public void setIsIncoming(boolean isIncoming) { 467 mIsIncoming = isIncoming; 468 } 469 470 /** 471 * Checks if the connection is for an emergency call. 472 * 473 * @return {@code true} if the call is an emergency call 474 * or {@code false} otherwise. 475 */ isEmergencyCall()476 public boolean isEmergencyCall() { 477 return mIsEmergencyCall; 478 } 479 480 /** 481 * Get the emergency number info. The value is valid only if {@link #isEmergencyCall()} 482 * returns {@code true}. 483 * 484 * @return the emergency number info 485 */ getEmergencyNumberInfo()486 public EmergencyNumber getEmergencyNumberInfo() { 487 return mEmergencyNumberInfo; 488 } 489 490 /** 491 * Checks if we have known the user's intent for the call is emergency. 492 * 493 * This is only used to specify when the dialed number is ambiguous, identified as both 494 * emergency number and any other non-emergency number; e.g. in some situation, 611 could 495 * be both an emergency number in a country and a non-emergency number of a carrier's 496 * customer service hotline. 497 * 498 * @return whether the call is from emergency dialer 499 */ hasKnownUserIntentEmergency()500 public boolean hasKnownUserIntentEmergency() { 501 return mHasKnownUserIntentEmergency; 502 } 503 504 /** 505 * Set the emergency number information if it is an emergency call. 506 * 507 * @hide 508 */ setEmergencyCallInfo(CallTracker ct)509 public void setEmergencyCallInfo(CallTracker ct) { 510 if (ct != null) { 511 Phone phone = ct.getPhone(); 512 if (phone != null) { 513 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker(); 514 if (tracker != null) { 515 EmergencyNumber num = tracker.getEmergencyNumber(mAddress); 516 if (num != null) { 517 mIsEmergencyCall = true; 518 mEmergencyNumberInfo = num; 519 } else { 520 Rlog.e(TAG, "setEmergencyCallInfo: emergency number is null"); 521 } 522 } else { 523 Rlog.e(TAG, "setEmergencyCallInfo: emergency number tracker is null"); 524 } 525 } else { 526 Rlog.e(TAG, "setEmergencyCallInfo: phone is null"); 527 } 528 } else { 529 Rlog.e(TAG, "setEmergencyCallInfo: call tracker is null"); 530 } 531 } 532 533 /** 534 * Set if we have known the user's intent for the call is emergency. 535 * 536 * This is only used to specify when the dialed number is ambiguous, identified as both 537 * emergency number and any other non-emergency number; e.g. in some situation, 611 could 538 * be both an emergency number in a country and a non-emergency number of a carrier's 539 * customer service hotline. 540 * 541 * @hide 542 */ setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency)543 public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) { 544 mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency; 545 } 546 547 /** 548 * If this Connection is connected, then it is associated with 549 * a Call. 550 * 551 * Returns getCall().getState() or Call.State.IDLE if not 552 * connected 553 */ 554 @UnsupportedAppUsage getState()555 public Call.State getState() { 556 Call c; 557 558 c = getCall(); 559 560 if (c == null) { 561 return Call.State.IDLE; 562 } else { 563 return c.getState(); 564 } 565 } 566 567 /** 568 * If this connection went through handover return the state of the 569 * call that contained this connection before handover. 570 */ getStateBeforeHandover()571 public Call.State getStateBeforeHandover() { 572 return mPreHandoverState; 573 } 574 575 /** 576 * Get the details of conference participants. Expected to be 577 * overwritten by the Connection subclasses. 578 */ getConferenceParticipants()579 public List<ConferenceParticipant> getConferenceParticipants() { 580 Call c; 581 582 c = getCall(); 583 584 if (c == null) { 585 return null; 586 } else { 587 return c.getConferenceParticipants(); 588 } 589 } 590 591 /** 592 * isAlive() 593 * 594 * @return true if the connection isn't disconnected 595 * (could be active, holding, ringing, dialing, etc) 596 */ 597 @UnsupportedAppUsage 598 public boolean isAlive()599 isAlive() { 600 return getState().isAlive(); 601 } 602 603 /** 604 * Returns true if Connection is connected and is INCOMING or WAITING 605 */ 606 public boolean isRinging()607 isRinging() { 608 return getState().isRinging(); 609 } 610 611 /** 612 * 613 * @return the userdata set in setUserData() 614 */ 615 @UnsupportedAppUsage getUserData()616 public Object getUserData() { 617 return mUserData; 618 } 619 620 /** 621 * 622 * @param userdata user can store an any userdata in the Connection object. 623 */ setUserData(Object userdata)624 public void setUserData(Object userdata) { 625 mUserData = userdata; 626 } 627 628 /** 629 * Deflect individual Connection 630 */ deflect(String number)631 public abstract void deflect(String number) throws CallStateException; 632 633 /** 634 * Hangup individual Connection 635 */ 636 @UnsupportedAppUsage hangup()637 public abstract void hangup() throws CallStateException; 638 639 /** 640 * Separate this call from its owner Call and assigns it to a new Call 641 * (eg if it is currently part of a Conference call 642 * TODO: Throw exception? Does GSM require error display on failure here? 643 */ separate()644 public abstract void separate() throws CallStateException; 645 646 public enum PostDialState { 647 @UnsupportedAppUsage 648 NOT_STARTED, /* The post dial string playback hasn't 649 been started, or this call is not yet 650 connected, or this is an incoming call */ 651 @UnsupportedAppUsage 652 STARTED, /* The post dial string playback has begun */ 653 @UnsupportedAppUsage 654 WAIT, /* The post dial string playback is waiting for a 655 call to proceedAfterWaitChar() */ 656 @UnsupportedAppUsage 657 WILD, /* The post dial string playback is waiting for a 658 call to proceedAfterWildChar() */ 659 @UnsupportedAppUsage 660 COMPLETE, /* The post dial string playback is complete */ 661 @UnsupportedAppUsage 662 CANCELLED, /* The post dial string playback was cancelled 663 with cancelPostDial() */ 664 PAUSE /* The post dial string playback is pausing for a 665 call to processNextPostDialChar*/ 666 } 667 clearUserData()668 public void clearUserData(){ 669 mUserData = null; 670 } 671 addPostDialListener(PostDialListener listener)672 public void addPostDialListener(PostDialListener listener) { 673 if (!mPostDialListeners.contains(listener)) { 674 mPostDialListeners.add(listener); 675 } 676 } 677 removePostDialListener(PostDialListener listener)678 public final void removePostDialListener(PostDialListener listener) { 679 mPostDialListeners.remove(listener); 680 } 681 clearPostDialListeners()682 protected final void clearPostDialListeners() { 683 if (mPostDialListeners != null) { 684 mPostDialListeners.clear(); 685 } 686 } 687 notifyPostDialListeners()688 protected final void notifyPostDialListeners() { 689 if (getPostDialState() == PostDialState.WAIT) { 690 for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) { 691 listener.onPostDialWait(); 692 } 693 } 694 } 695 notifyPostDialListenersNextChar(char c)696 protected final void notifyPostDialListenersNextChar(char c) { 697 for (PostDialListener listener : new ArrayList<>(mPostDialListeners)) { 698 listener.onPostDialChar(c); 699 } 700 } 701 getPostDialState()702 public PostDialState getPostDialState() { 703 return mPostDialState; 704 } 705 706 /** 707 * Returns the portion of the post dial string that has not 708 * yet been dialed, or "" if none 709 */ getRemainingPostDialString()710 public String getRemainingPostDialString() { 711 if (mPostDialState == PostDialState.CANCELLED 712 || mPostDialState == PostDialState.COMPLETE 713 || mPostDialString == null 714 || mPostDialString.length() <= mNextPostDialChar) { 715 return ""; 716 } 717 718 return mPostDialString.substring(mNextPostDialChar); 719 } 720 721 /** 722 * See Phone.setOnPostDialWaitCharacter() 723 */ 724 proceedAfterWaitChar()725 public abstract void proceedAfterWaitChar(); 726 727 /** 728 * See Phone.setOnPostDialWildCharacter() 729 */ proceedAfterWildChar(String str)730 public abstract void proceedAfterWildChar(String str); 731 /** 732 * Cancel any post 733 */ cancelPostDial()734 public abstract void cancelPostDial(); 735 736 /** Called when the connection has been disconnected */ onDisconnect(int cause)737 public boolean onDisconnect(int cause) { 738 return false; 739 } 740 741 /** 742 * Returns the caller id presentation type for incoming and waiting calls 743 * @return one of PRESENTATION_* 744 */ getNumberPresentation()745 public abstract int getNumberPresentation(); 746 747 /** 748 * Returns the User to User Signaling (UUS) information associated with 749 * incoming and waiting calls 750 * @return UUSInfo containing the UUS userdata. 751 */ getUUSInfo()752 public abstract UUSInfo getUUSInfo(); 753 754 /** 755 * Returns the CallFail reason provided by the RIL with the result of 756 * RIL_REQUEST_LAST_CALL_FAIL_CAUSE 757 */ getPreciseDisconnectCause()758 public abstract int getPreciseDisconnectCause(); 759 760 /** 761 * Returns the original Connection instance associated with 762 * this Connection 763 */ getOrigConnection()764 public Connection getOrigConnection() { 765 return mOrigConnection; 766 } 767 768 /** 769 * Returns whether the original ImsPhoneConnection was a member 770 * of a conference call 771 * @return valid only when getOrigConnection() is not null 772 */ isMultiparty()773 public abstract boolean isMultiparty(); 774 775 /** 776 * Applicable only for IMS Call. Determines if this call is the origin of the conference call 777 * (i.e. {@code #isConferenceHost()} is {@code true}), or if it is a member of a conference 778 * hosted on another device. 779 * 780 * @return {@code true} if this call is the origin of the conference call it is a member of, 781 * {@code false} otherwise. 782 */ isConferenceHost()783 public boolean isConferenceHost() { 784 return false; 785 } 786 787 /** 788 * Applicable only for IMS Call. Determines if a connection is a member of a conference hosted 789 * on another device. 790 * 791 * @return {@code true} if the connection is a member of a conference hosted on another device. 792 */ isMemberOfPeerConference()793 public boolean isMemberOfPeerConference() { 794 return false; 795 } 796 migrateFrom(Connection c)797 public void migrateFrom(Connection c) { 798 if (c == null) return; 799 mListeners = c.mListeners; 800 mDialString = c.getOrigDialString(); 801 mCreateTime = c.getCreateTime(); 802 mConnectTime = c.getConnectTime(); 803 mConnectTimeReal = c.getConnectTimeReal(); 804 mHoldingStartTime = c.getHoldingStartTime(); 805 mOrigConnection = c.getOrigConnection(); 806 mPostDialString = c.mPostDialString; 807 mNextPostDialChar = c.mNextPostDialChar; 808 mPostDialState = c.mPostDialState; 809 810 // Migrate Emergency call parameters 811 mIsEmergencyCall = c.isEmergencyCall(); 812 mEmergencyNumberInfo = c.getEmergencyNumberInfo(); 813 mHasKnownUserIntentEmergency = c.hasKnownUserIntentEmergency(); 814 } 815 816 /** 817 * Assign a listener to be notified of state changes. 818 * 819 * @param listener A listener. 820 */ addListener(Listener listener)821 public void addListener(Listener listener) { 822 mListeners.add(listener); 823 } 824 825 /** 826 * Removes a listener. 827 * 828 * @param listener A listener. 829 */ removeListener(Listener listener)830 public final void removeListener(Listener listener) { 831 mListeners.remove(listener); 832 } 833 834 /** 835 * Returns the current video state of the connection. 836 * 837 * @return The video state of the connection. 838 */ getVideoState()839 public int getVideoState() { 840 return mVideoState; 841 } 842 843 /** 844 * Called to get Connection capabilities.Returns Capabilities bitmask. 845 * @See Connection.Capability. 846 */ getConnectionCapabilities()847 public int getConnectionCapabilities() { 848 return mConnectionCapabilities; 849 } 850 851 /** 852 * @return {@code} true if the connection has the specified capabilities. 853 */ hasCapabilities(int connectionCapabilities)854 public boolean hasCapabilities(int connectionCapabilities) { 855 return (mConnectionCapabilities & connectionCapabilities) == connectionCapabilities; 856 } 857 858 /** 859 * Applies a capability to a capabilities bit-mask. 860 * 861 * @param capabilities The capabilities bit-mask. 862 * @param capability The capability to apply. 863 * @return The capabilities bit-mask with the capability applied. 864 */ addCapability(int capabilities, int capability)865 public static int addCapability(int capabilities, int capability) { 866 return capabilities | capability; 867 } 868 869 /** 870 * Removes a capability to a capabilities bit-mask. 871 * 872 * @param capabilities The capabilities bit-mask. 873 * @param capability The capability to remove. 874 * @return The capabilities bit-mask with the capability removed. 875 */ removeCapability(int capabilities, int capability)876 public static int removeCapability(int capabilities, int capability) { 877 return capabilities & ~capability; 878 } 879 880 /** 881 * Returns whether the connection is using a wifi network. 882 * 883 * @return {@code True} if the connection is using a wifi network. 884 */ isWifi()885 public boolean isWifi() { 886 return getCallRadioTech() == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN; 887 } 888 889 /** 890 * Returns radio technology is used for the connection. 891 * 892 * @return the RIL Voice Radio Technology used for current connection, 893 * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}. 894 */ getCallRadioTech()895 public @ServiceState.RilRadioTechnology int getCallRadioTech() { 896 return mCallRadioTech; 897 } 898 899 /** 900 * Returns whether the connection uses voip audio mode 901 * 902 * @return {@code True} if the connection uses voip audio mode 903 */ getAudioModeIsVoip()904 public boolean getAudioModeIsVoip() { 905 return mAudioModeIsVoip; 906 } 907 908 /** 909 * Returns the {@link android.telecom.Connection.VideoProvider} for the connection. 910 * 911 * @return The {@link android.telecom.Connection.VideoProvider}. 912 */ getVideoProvider()913 public android.telecom.Connection.VideoProvider getVideoProvider() { 914 return mVideoProvider; 915 } 916 917 /** 918 * Returns the audio-quality for the connection. 919 * 920 * @return The audio quality for the connection. 921 */ getAudioQuality()922 public int getAudioQuality() { 923 return mAudioQuality; 924 } 925 926 927 /** 928 * Returns the current call substate of the connection. 929 * 930 * @return The call substate of the connection. 931 */ getCallSubstate()932 public int getCallSubstate() { 933 return mCallSubstate; 934 } 935 936 937 /** 938 * Sets the videoState for the current connection and reports the changes to all listeners. 939 * Valid video states are defined in {@link android.telecom.VideoProfile}. 940 * 941 * @return The video state. 942 */ 943 @UnsupportedAppUsage setVideoState(int videoState)944 public void setVideoState(int videoState) { 945 mVideoState = videoState; 946 for (Listener l : mListeners) { 947 l.onVideoStateChanged(mVideoState); 948 } 949 } 950 951 /** 952 * Called to set Connection capabilities. This will take Capabilities bitmask as input which is 953 * converted from Capabilities constants. 954 * 955 * @See Connection.Capability. 956 * @param capabilities The Capabilities bitmask. 957 */ setConnectionCapabilities(int capabilities)958 public void setConnectionCapabilities(int capabilities) { 959 if (mConnectionCapabilities != capabilities) { 960 mConnectionCapabilities = capabilities; 961 for (Listener l : mListeners) { 962 l.onConnectionCapabilitiesChanged(mConnectionCapabilities); 963 } 964 } 965 } 966 967 /** 968 * Sets RIL voice radio technology used for current connection. 969 * 970 * @param vrat the RIL voice radio technology for current connection, 971 * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}. 972 */ setCallRadioTech(@erviceState.RilRadioTechnology int vrat)973 public void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) { 974 if (mCallRadioTech == vrat) { 975 return; 976 } 977 mCallRadioTech = vrat; 978 for (Listener l : mListeners) { 979 l.onCallRadioTechChanged(vrat); 980 } 981 } 982 983 /** 984 * Set the voip audio mode for the connection 985 * 986 * @param isVoip {@code True} if voip audio mode is being used. 987 */ setAudioModeIsVoip(boolean isVoip)988 public void setAudioModeIsVoip(boolean isVoip) { 989 mAudioModeIsVoip = isVoip; 990 } 991 992 /** 993 * Set the audio quality for the connection. 994 * 995 * @param audioQuality The audio quality. 996 */ setAudioQuality(int audioQuality)997 public void setAudioQuality(int audioQuality) { 998 mAudioQuality = audioQuality; 999 for (Listener l : mListeners) { 1000 l.onAudioQualityChanged(mAudioQuality); 1001 } 1002 } 1003 1004 /** 1005 * Notifies listeners that connection extras has changed. 1006 * @param extras New connection extras. This Bundle will be cloned to ensure that any concurrent 1007 * modifications to the extras Bundle do not affect Bundle operations in the onExtrasChanged 1008 * listeners. 1009 */ setConnectionExtras(Bundle extras)1010 public void setConnectionExtras(Bundle extras) { 1011 if (extras != null) { 1012 mExtras = new Bundle(extras); 1013 1014 int previousCount = mExtras.size(); 1015 // Prevent vendors from passing in extras other than primitive types and android API 1016 // parcelables. 1017 mExtras = mExtras.filterValues(); 1018 int filteredCount = mExtras.size(); 1019 if (filteredCount != previousCount) { 1020 Rlog.i(TAG, "setConnectionExtras: filtering " + (previousCount - filteredCount) 1021 + " invalid extras."); 1022 } 1023 } else { 1024 mExtras = null; 1025 } 1026 1027 for (Listener l : mListeners) { 1028 l.onExtrasChanged(mExtras); 1029 } 1030 } 1031 1032 /** 1033 * Retrieves the current connection extras. 1034 * @return the connection extras. 1035 */ getConnectionExtras()1036 public Bundle getConnectionExtras() { 1037 return mExtras == null ? null : new Bundle(mExtras); 1038 } 1039 1040 /** 1041 * @return {@code true} if answering the call will cause the current active call to be 1042 * disconnected, {@code false} otherwise. 1043 */ isActiveCallDisconnectedOnAnswer()1044 public boolean isActiveCallDisconnectedOnAnswer() { 1045 return mAnsweringDisconnectsActiveCall; 1046 } 1047 1048 /** 1049 * Sets whether answering this call will cause the active call to be disconnected. 1050 * <p> 1051 * Should only be set {@code true} if there is an active call and this call is ringing. 1052 * 1053 * @param answeringDisconnectsActiveCall {@code true} if answering the call will call the active 1054 * call to be disconnected. 1055 */ setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall)1056 public void setActiveCallDisconnectedOnAnswer(boolean answeringDisconnectsActiveCall) { 1057 mAnsweringDisconnectsActiveCall = answeringDisconnectsActiveCall; 1058 } 1059 shouldAllowAddCallDuringVideoCall()1060 public boolean shouldAllowAddCallDuringVideoCall() { 1061 return mAllowAddCallDuringVideoCall; 1062 } 1063 setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall)1064 public void setAllowAddCallDuringVideoCall(boolean allowAddCallDuringVideoCall) { 1065 mAllowAddCallDuringVideoCall = allowAddCallDuringVideoCall; 1066 } 1067 1068 /** 1069 * Sets whether the connection is the result of an external call which was pulled to the local 1070 * device. 1071 * 1072 * @param isPulledCall {@code true} if this connection is the result of pulling an external call 1073 * to the local device. 1074 */ setIsPulledCall(boolean isPulledCall)1075 public void setIsPulledCall(boolean isPulledCall) { 1076 mIsPulledCall = isPulledCall; 1077 } 1078 isPulledCall()1079 public boolean isPulledCall() { 1080 return mIsPulledCall; 1081 } 1082 1083 /** 1084 * For an external call which is being pulled (e.g. {@link #isPulledCall()} is {@code true}), 1085 * sets the dialog Id for the external call. Used to handle failures to pull a call so that the 1086 * pulled call can be reconciled with its original external connection. 1087 * 1088 * @param pulledDialogId The dialog id associated with a pulled call. 1089 */ setPulledDialogId(int pulledDialogId)1090 public void setPulledDialogId(int pulledDialogId) { 1091 mPulledDialogId = pulledDialogId; 1092 } 1093 getPulledDialogId()1094 public int getPulledDialogId() { 1095 return mPulledDialogId; 1096 } 1097 1098 /** 1099 * Sets the call substate for the current connection and reports the changes to all listeners. 1100 * Valid call substates are defined in {@link android.telecom.Connection}. 1101 * 1102 * @return The call substate. 1103 */ setCallSubstate(int callSubstate)1104 public void setCallSubstate(int callSubstate) { 1105 mCallSubstate = callSubstate; 1106 for (Listener l : mListeners) { 1107 l.onCallSubstateChanged(mCallSubstate); 1108 } 1109 } 1110 1111 /** 1112 * Sets the {@link android.telecom.Connection.VideoProvider} for the connection. 1113 * 1114 * @param videoProvider The video call provider. 1115 */ setVideoProvider(android.telecom.Connection.VideoProvider videoProvider)1116 public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) { 1117 mVideoProvider = videoProvider; 1118 for (Listener l : mListeners) { 1119 l.onVideoProviderChanged(mVideoProvider); 1120 } 1121 } 1122 setConverted(String oriNumber)1123 public void setConverted(String oriNumber) { 1124 mNumberConverted = true; 1125 mConvertedNumber = mAddress; 1126 mAddress = oriNumber; 1127 mDialString = oriNumber; 1128 } 1129 1130 /** 1131 * Changes the address and presentation for this call. 1132 * @param newAddress The new address. 1133 * @param numberPresentation The number presentation for the address. 1134 */ setAddress(String newAddress, int numberPresentation)1135 public void setAddress(String newAddress, int numberPresentation) { 1136 Rlog.i(TAG, "setAddress = " + newAddress); 1137 mAddress = newAddress; 1138 mNumberPresentation = numberPresentation; 1139 } 1140 setDialString(String newDialString)1141 public void setDialString(String newDialString) { 1142 mDialString = newDialString; 1143 } 1144 1145 /** 1146 * Notifies listeners of a change to conference participant(s). 1147 * 1148 * @param conferenceParticipants The participant(s). 1149 */ updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants)1150 public void updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants) { 1151 for (Listener l : mListeners) { 1152 l.onConferenceParticipantsChanged(conferenceParticipants); 1153 } 1154 } 1155 1156 /** 1157 * Notifies listeners of a change to the multiparty state of the connection. 1158 * 1159 * @param isMultiparty The participant(s). 1160 */ updateMultipartyState(boolean isMultiparty)1161 public void updateMultipartyState(boolean isMultiparty) { 1162 for (Listener l : mListeners) { 1163 l.onMultipartyStateChanged(isMultiparty); 1164 } 1165 } 1166 1167 /** 1168 * Notifies listeners of a failure in merging this connection with the background connection. 1169 */ onConferenceMergeFailed()1170 public void onConferenceMergeFailed() { 1171 for (Listener l : mListeners) { 1172 l.onConferenceMergedFailed(); 1173 } 1174 } 1175 1176 /** 1177 * Notifies that the underlying phone has exited ECM mode. 1178 */ onExitedEcmMode()1179 public void onExitedEcmMode() { 1180 for (Listener l : mListeners) { 1181 l.onExitedEcmMode(); 1182 } 1183 } 1184 1185 /** 1186 * Notifies the connection that a call to {@link #pullExternalCall()} has failed to pull the 1187 * call to the local device. 1188 * 1189 * @param externalConnection The original 1190 * {@link com.android.internal.telephony.imsphone.ImsExternalConnection} from which the 1191 * pull was initiated. 1192 */ onCallPullFailed(Connection externalConnection)1193 public void onCallPullFailed(Connection externalConnection) { 1194 for (Listener l : mListeners) { 1195 l.onCallPullFailed(externalConnection); 1196 } 1197 } 1198 onOriginalConnectionReplaced(Connection newConnection)1199 public void onOriginalConnectionReplaced(Connection newConnection) { 1200 for (Listener l : mListeners) { 1201 l.onOriginalConnectionReplaced(newConnection); 1202 } 1203 } 1204 /** 1205 * Notifies the connection that there was a failure while handing over to WIFI. 1206 */ onHandoverToWifiFailed()1207 public void onHandoverToWifiFailed() { 1208 for (Listener l : mListeners) { 1209 l.onHandoverToWifiFailed(); 1210 } 1211 } 1212 1213 /** 1214 * Notifies the connection of a connection event. 1215 */ onConnectionEvent(String event, Bundle extras)1216 public void onConnectionEvent(String event, Bundle extras) { 1217 for (Listener l : mListeners) { 1218 l.onConnectionEvent(event, extras); 1219 } 1220 } 1221 1222 /** 1223 * Notifies this Connection of a request to disconnect a participant of the conference managed 1224 * by the connection. 1225 * 1226 * @param endpoint the {@link Uri} of the participant to disconnect. 1227 */ onDisconnectConferenceParticipant(Uri endpoint)1228 public void onDisconnectConferenceParticipant(Uri endpoint) { 1229 } 1230 1231 /** 1232 * Called by a {@link android.telecom.Connection} to indicate that this call should be pulled 1233 * to the local device. 1234 */ pullExternalCall()1235 public void pullExternalCall() { 1236 } 1237 onRttModifyRequestReceived()1238 public void onRttModifyRequestReceived() { 1239 for (Listener l : mListeners) { 1240 l.onRttModifyRequestReceived(); 1241 } 1242 } 1243 onRttModifyResponseReceived(int status)1244 public void onRttModifyResponseReceived(int status) { 1245 for (Listener l : mListeners) { 1246 l.onRttModifyResponseReceived(status); 1247 } 1248 } 1249 onRttInitiated()1250 public void onRttInitiated() { 1251 for (Listener l : mListeners) { 1252 l.onRttInitiated(); 1253 } 1254 } 1255 onRttTerminated()1256 public void onRttTerminated() { 1257 for (Listener l : mListeners) { 1258 l.onRttTerminated(); 1259 } 1260 } 1261 /** 1262 * Notify interested parties that this connection disconnected. 1263 * {@code TelephonyConnection}, for example, uses this. 1264 * @param reason the disconnect code, per {@link DisconnectCause}. 1265 */ notifyDisconnect(int reason)1266 protected void notifyDisconnect(int reason) { 1267 Rlog.i(TAG, "notifyDisconnect: callId=" + getTelecomCallId() + ", reason=" + reason); 1268 for (Listener l : mListeners) { 1269 l.onDisconnect(reason); 1270 } 1271 } 1272 1273 /** 1274 * 1275 */ getPhoneType()1276 public int getPhoneType() { 1277 return mPhoneType; 1278 } 1279 1280 /** 1281 * Reset the Connection time and Duration 1282 */ resetConnectionTime()1283 public void resetConnectionTime() { 1284 if (mPhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE || 1285 mPhoneType == PhoneConstants.PHONE_TYPE_CDMA) { 1286 mConnectTime = System.currentTimeMillis(); 1287 mConnectTimeReal = SystemClock.elapsedRealtime(); 1288 mDuration = 0; 1289 } 1290 } 1291 1292 /** 1293 * Sets whether this {@link Connection} has been identified by the network as an emergency call. 1294 * @param isNetworkIdentifiedEmergencyCall {@code true} if ecall, {@code false} otherwise. 1295 */ setIsNetworkIdentifiedEmergencyCall(boolean isNetworkIdentifiedEmergencyCall)1296 public void setIsNetworkIdentifiedEmergencyCall(boolean isNetworkIdentifiedEmergencyCall) { 1297 mIsNetworkIdentifiedEmergencyCall = isNetworkIdentifiedEmergencyCall; 1298 for (Listener l : mListeners) { 1299 l.onIsNetworkEmergencyCallChanged(isNetworkIdentifiedEmergencyCall); 1300 } 1301 } 1302 1303 /** 1304 * @return Whether this {@link Connection} has been identified by the network as an emergency 1305 * call. 1306 */ isNetworkIdentifiedEmergencyCall()1307 public boolean isNetworkIdentifiedEmergencyCall() { 1308 return mIsNetworkIdentifiedEmergencyCall; 1309 } 1310 1311 /** 1312 * Build a human representation of a connection instance, suitable for debugging. 1313 * Don't log personal stuff unless in debug mode. 1314 * @return a string representing the internal state of this connection. 1315 */ toString()1316 public String toString() { 1317 StringBuilder str = new StringBuilder(128); 1318 1319 str.append(" callId: " + getTelecomCallId()); 1320 str.append(" isExternal: " + (((mConnectionCapabilities & Capability.IS_EXTERNAL_CONNECTION) 1321 == Capability.IS_EXTERNAL_CONNECTION) ? "Y" : "N")); 1322 if (Rlog.isLoggable(LOG_TAG, Log.DEBUG)) { 1323 str.append("addr: " + getAddress()) 1324 .append(" pres.: " + getNumberPresentation()) 1325 .append(" dial: " + getOrigDialString()) 1326 .append(" postdial: " + getRemainingPostDialString()) 1327 .append(" cnap name: " + getCnapName()) 1328 .append("(" + getCnapNamePresentation() + ")"); 1329 } 1330 str.append(" incoming: " + isIncoming()) 1331 .append(" state: " + getState()) 1332 .append(" post dial state: " + getPostDialState()); 1333 return str.toString(); 1334 } 1335 } 1336