1 /* 2 * Copyright (C) 2014 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 android.telecom; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.annotation.TestApi; 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.net.Uri; 26 import android.os.Build; 27 import android.os.Bundle; 28 import android.os.Handler; 29 import android.os.ParcelFileDescriptor; 30 31 import com.android.internal.telecom.IVideoProvider; 32 33 import java.io.IOException; 34 import java.io.InputStreamReader; 35 import java.io.OutputStreamWriter; 36 import java.lang.annotation.Retention; 37 import java.lang.annotation.RetentionPolicy; 38 import java.nio.charset.StandardCharsets; 39 import java.util.ArrayList; 40 import java.util.Arrays; 41 import java.util.Collections; 42 import java.util.List; 43 import java.util.Map; 44 import java.util.Objects; 45 import java.util.concurrent.CopyOnWriteArrayList; 46 47 /** 48 * Represents an ongoing phone call that the in-call app should present to the user. 49 */ 50 public final class Call { 51 /** 52 * The state of a {@code Call} when newly created. 53 */ 54 public static final int STATE_NEW = 0; 55 56 /** 57 * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected. 58 */ 59 public static final int STATE_DIALING = 1; 60 61 /** 62 * The state of an incoming {@code Call} when ringing locally, but not yet connected. 63 */ 64 public static final int STATE_RINGING = 2; 65 66 /** 67 * The state of a {@code Call} when in a holding state. 68 */ 69 public static final int STATE_HOLDING = 3; 70 71 /** 72 * The state of a {@code Call} when actively supporting conversation. 73 */ 74 public static final int STATE_ACTIVE = 4; 75 76 /** 77 * The state of a {@code Call} when no further voice or other communication is being 78 * transmitted, the remote side has been or will inevitably be informed that the {@code Call} 79 * is no longer active, and the local data transport has or inevitably will release resources 80 * associated with this {@code Call}. 81 */ 82 public static final int STATE_DISCONNECTED = 7; 83 84 /** 85 * The state of an outgoing {@code Call} when waiting on user to select a 86 * {@link PhoneAccount} through which to place the call. 87 */ 88 public static final int STATE_SELECT_PHONE_ACCOUNT = 8; 89 90 /** 91 * @hide 92 * @deprecated use STATE_SELECT_PHONE_ACCOUNT. 93 */ 94 @Deprecated 95 @SystemApi 96 public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT; 97 98 /** 99 * The initial state of an outgoing {@code Call}. 100 * Common transitions are to {@link #STATE_DIALING} state for a successful call or 101 * {@link #STATE_DISCONNECTED} if it failed. 102 */ 103 public static final int STATE_CONNECTING = 9; 104 105 /** 106 * The state of a {@code Call} when the user has initiated a disconnection of the call, but the 107 * call has not yet been disconnected by the underlying {@code ConnectionService}. The next 108 * state of the call is (potentially) {@link #STATE_DISCONNECTED}. 109 */ 110 public static final int STATE_DISCONNECTING = 10; 111 112 /** 113 * The state of an external call which is in the process of being pulled from a remote device to 114 * the local device. 115 * <p> 116 * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property 117 * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call. 118 * <p> 119 * An {@link InCallService} will only see this state if it has the 120 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its 121 * manifest. 122 */ 123 public static final int STATE_PULLING_CALL = 11; 124 125 /** 126 * The state of a call that is active with the network, but the audio from the call is 127 * being intercepted by an app on the local device. Telecom does not hold audio focus in this 128 * state, and the call will be invisible to the user except for a persistent notification. 129 */ 130 public static final int STATE_AUDIO_PROCESSING = 12; 131 132 /** 133 * The state of a call that is being presented to the user after being in 134 * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and 135 * Telecom will hold audio focus and play a ringtone if appropriate. 136 */ 137 public static final int STATE_SIMULATED_RINGING = 13; 138 139 /** 140 * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call 141 * extras. Used to pass the phone accounts to display on the front end to the user in order to 142 * select phone accounts to (for example) place a call. 143 * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead. 144 */ 145 @Deprecated 146 public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts"; 147 148 /** 149 * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call 150 * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here 151 * will have the same length and be in the same order as the list passed with 152 * {@link #AVAILABLE_PHONE_ACCOUNTS}. 153 */ 154 public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS = 155 "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS"; 156 157 /** 158 * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC) 159 * when the last outgoing emergency call was made. This is used to identify potential emergency 160 * callbacks. 161 */ 162 public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = 163 "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS"; 164 165 166 /** 167 * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence 168 * the ringtone for a call. If the {@link InCallService} declares 169 * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not 170 * play a ringtone for an incoming call with this extra key set. 171 */ 172 public static final String EXTRA_SILENT_RINGING_REQUESTED = 173 "android.telecom.extra.SILENT_RINGING_REQUESTED"; 174 175 /** 176 * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform 177 * Telecom that the user has requested that the current {@link Call} should be handed over 178 * to another {@link ConnectionService}. 179 * <p> 180 * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to 181 * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to. 182 * @hide 183 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated 184 * APIs instead. 185 */ 186 public static final String EVENT_REQUEST_HANDOVER = 187 "android.telecom.event.REQUEST_HANDOVER"; 188 189 /** 190 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the 191 * {@link PhoneAccountHandle} to which a call should be handed over to. 192 * @hide 193 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated 194 * APIs instead. 195 */ 196 public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE = 197 "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE"; 198 199 /** 200 * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the 201 * video state of the call when it is handed over to the new {@link PhoneAccount}. 202 * <p> 203 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY}, 204 * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and 205 * {@link VideoProfile#STATE_TX_ENABLED}. 206 * @hide 207 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated 208 * APIs instead. 209 */ 210 public static final String EXTRA_HANDOVER_VIDEO_STATE = 211 "android.telecom.extra.HANDOVER_VIDEO_STATE"; 212 213 /** 214 * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Used by the 215 * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra 216 * information to the handover {@link ConnectionService} specified by 217 * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}. 218 * <p> 219 * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the 220 * {@link ConnectionService} via the request extras when 221 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)} 222 * is called to initate the handover. 223 * @hide 224 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated 225 * APIs instead. 226 */ 227 public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS"; 228 229 /** 230 * Call event sent from Telecom to the handover {@link ConnectionService} via 231 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover 232 * to the {@link ConnectionService} has completed successfully. 233 * <p> 234 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event. 235 * @hide 236 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated 237 * APIs instead. 238 */ 239 public static final String EVENT_HANDOVER_COMPLETE = 240 "android.telecom.event.HANDOVER_COMPLETE"; 241 242 /** 243 * Call event sent from Telecom to the handover destination {@link ConnectionService} via 244 * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the 245 * source connection has disconnected. The {@link Bundle} parameter for the call event will be 246 * {@code null}. 247 * <p> 248 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event. 249 * @hide 250 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated 251 * APIs instead. 252 */ 253 public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED = 254 "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED"; 255 256 /** 257 * Call event sent from Telecom to the handover {@link ConnectionService} via 258 * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover 259 * to the {@link ConnectionService} has failed. 260 * <p> 261 * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event. 262 * @hide 263 * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated 264 * APIs instead. 265 */ 266 public static final String EVENT_HANDOVER_FAILED = 267 "android.telecom.event.HANDOVER_FAILED"; 268 269 270 /** 271 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this 272 * call because they have declined to answer it. This typically means that they are unable 273 * to answer the call at this time and would prefer it be sent to voicemail. 274 */ 275 public static final int REJECT_REASON_DECLINED = 1; 276 277 /** 278 * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this 279 * call because it is an unwanted call. This allows the user to indicate that they are 280 * rejecting a call because it is likely a nuisance call. 281 */ 282 public static final int REJECT_REASON_UNWANTED = 2; 283 284 /** 285 * @hide 286 */ 287 @IntDef(prefix = { "REJECT_REASON_" }, 288 value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED}) 289 @Retention(RetentionPolicy.SOURCE) 290 public @interface RejectReason {}; 291 292 public static class Details { 293 /** @hide */ 294 @Retention(RetentionPolicy.SOURCE) 295 @IntDef( 296 prefix = { "DIRECTION_" }, 297 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING}) 298 public @interface CallDirection {} 299 300 /** 301 * Indicates that the call is neither and incoming nor an outgoing call. This can be the 302 * case for calls reported directly by a {@link ConnectionService} in special cases such as 303 * call handovers. 304 */ 305 public static final int DIRECTION_UNKNOWN = -1; 306 307 /** 308 * Indicates that the call is an incoming call. 309 */ 310 public static final int DIRECTION_INCOMING = 0; 311 312 /** 313 * Indicates that the call is an outgoing call. 314 */ 315 public static final int DIRECTION_OUTGOING = 1; 316 317 /** Call can currently be put on hold or unheld. */ 318 public static final int CAPABILITY_HOLD = 0x00000001; 319 320 /** Call supports the hold feature. */ 321 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002; 322 323 /** 324 * Calls within a conference can be merged. A {@link ConnectionService} has the option to 325 * add a {@link Conference} call before the child {@link Connection}s are merged. This is how 326 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this 327 * capability allows a merge button to be shown while the conference call is in the foreground 328 * of the in-call UI. 329 * <p> 330 * This is only intended for use by a {@link Conference}. 331 */ 332 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004; 333 334 /** 335 * Calls within a conference can be swapped between foreground and background. 336 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information. 337 * <p> 338 * This is only intended for use by a {@link Conference}. 339 */ 340 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008; 341 342 /** 343 * @hide 344 */ 345 public static final int CAPABILITY_UNUSED_1 = 0x00000010; 346 347 /** Call supports responding via text option. */ 348 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020; 349 350 /** Call can be muted. */ 351 public static final int CAPABILITY_MUTE = 0x00000040; 352 353 /** 354 * Call supports conference call management. This capability only applies to {@link Conference} 355 * calls which can have {@link Connection}s as children. 356 */ 357 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080; 358 359 /** 360 * Local device supports receiving video. 361 */ 362 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100; 363 364 /** 365 * Local device supports transmitting video. 366 */ 367 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200; 368 369 /** 370 * Local device supports bidirectional video calling. 371 */ 372 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 373 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX; 374 375 /** 376 * Remote device supports receiving video. 377 */ 378 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400; 379 380 /** 381 * Remote device supports transmitting video. 382 */ 383 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800; 384 385 /** 386 * Remote device supports bidirectional video calling. 387 */ 388 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 389 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX; 390 391 /** 392 * Call is able to be separated from its parent {@code Conference}, if any. 393 */ 394 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000; 395 396 /** 397 * Call is able to be individually disconnected when in a {@code Conference}. 398 */ 399 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000; 400 401 /** 402 * Speed up audio setup for MT call. 403 * @hide 404 */ 405 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000; 406 407 /** 408 * Call can be upgraded to a video call. 409 * @hide 410 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and 411 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call 412 * whether or not video calling is supported. 413 */ 414 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590) 415 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000; 416 417 /** 418 * For video calls, indicates whether the outgoing video for the call can be paused using 419 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState. 420 */ 421 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000; 422 423 /** 424 * Call sends responses through connection. 425 * @hide 426 */ 427 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000; 428 429 /** 430 * When set, prevents a video {@code Call} from being downgraded to an audio-only call. 431 * <p> 432 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or 433 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be 434 * downgraded from a video call back to a VideoState of 435 * {@link VideoProfile#STATE_AUDIO_ONLY}. 436 * <p> 437 * Intuitively, a call which can be downgraded to audio should also have local and remote 438 * video 439 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and 440 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}). 441 */ 442 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000; 443 444 /** 445 * When set for an external call, indicates that this {@code Call} can be pulled from a 446 * remote device to the current device. 447 * <p> 448 * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set. 449 * <p> 450 * An {@link InCallService} will only see calls with this capability if it has the 451 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} 452 * in its manifest. 453 * <p> 454 * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and 455 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}. 456 */ 457 public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000; 458 459 /** Call supports the deflect feature. */ 460 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000; 461 462 /** 463 * Call supports adding participants to the call via 464 * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes 465 * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}). 466 */ 467 public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000; 468 469 /** 470 * When set for a call, indicates that this {@code Call} can be transferred to another 471 * number. 472 * Call supports the confirmed and unconfirmed call transfer feature. 473 * 474 * @hide 475 */ 476 public static final int CAPABILITY_TRANSFER = 0x04000000; 477 478 /** 479 * When set for a call, indicates that this {@code Call} can be transferred to another 480 * ongoing call. 481 * Call supports the consultative call transfer feature. 482 * 483 * @hide 484 */ 485 public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000; 486 487 //****************************************************************************************** 488 // Next CAPABILITY value: 0x10000000 489 //****************************************************************************************** 490 491 /** 492 * Whether the call is currently a conference. 493 */ 494 public static final int PROPERTY_CONFERENCE = 0x00000001; 495 496 /** 497 * Whether the call is a generic conference, where we do not know the precise state of 498 * participants in the conference (eg. on CDMA). 499 */ 500 public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002; 501 502 /** 503 * Whether the call is made while the device is in emergency callback mode. 504 */ 505 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004; 506 507 /** 508 * Connection is using WIFI. 509 */ 510 public static final int PROPERTY_WIFI = 0x00000008; 511 512 /** 513 * When set, the UI should indicate to the user that a call is using high definition 514 * audio. 515 * <p> 516 * The underlying {@link ConnectionService} is responsible for reporting this 517 * property. It is important to note that this property is not intended to report the 518 * actual audio codec being used for a Call, but whether the call should be indicated 519 * to the user as high definition. 520 * <p> 521 * The Android Telephony stack reports this property for calls based on a number 522 * of factors, including which audio codec is used and whether a call is using an HD 523 * codec end-to-end. Some mobile operators choose to suppress display of an HD indication, 524 * and in these cases this property will not be set for a call even if the underlying audio 525 * codec is in fact "high definition". 526 */ 527 public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010; 528 529 /** 530 * Whether the call is associated with the work profile. 531 */ 532 public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020; 533 534 /** 535 * When set, indicates that this {@code Call} does not actually exist locally for the 536 * {@link ConnectionService}. 537 * <p> 538 * Consider, for example, a scenario where a user has two phones with the same phone number. 539 * When a user places a call on one device, the telephony stack can represent that call on 540 * the other device by adding it to the {@link ConnectionService} with the 541 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set. 542 * <p> 543 * An {@link InCallService} will only see calls with this property if it has the 544 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} 545 * in its manifest. 546 * <p> 547 * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}. 548 */ 549 public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040; 550 551 /** 552 * Indicates that the call has CDMA Enhanced Voice Privacy enabled. 553 */ 554 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080; 555 556 /** 557 * Indicates that the call is from a self-managed {@link ConnectionService}. 558 * <p> 559 * See also {@link Connection#PROPERTY_SELF_MANAGED} 560 */ 561 public static final int PROPERTY_SELF_MANAGED = 0x00000100; 562 563 /** 564 * Indicates the call used Assisted Dialing. 565 * 566 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING 567 */ 568 public static final int PROPERTY_ASSISTED_DIALING = 0x00000200; 569 570 /** 571 * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the 572 * {@link RttCall} object that is used to send and receive text. 573 */ 574 public static final int PROPERTY_RTT = 0x00000400; 575 576 /** 577 * Indicates that the call has been identified as the network as an emergency call. This 578 * property may be set for both incoming and outgoing calls which the network identifies as 579 * emergency calls. 580 */ 581 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800; 582 583 /** 584 * Indicates that the call is using VoIP audio mode. 585 * <p> 586 * When this property is set, the {@link android.media.AudioManager} audio mode for this 587 * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}. When this 588 * property is not set, the audio mode for this call will be 589 * {@link android.media.AudioManager#MODE_IN_CALL}. 590 * <p> 591 * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}. 592 * <p> 593 * You can use this property to determine whether an un-answered incoming call or a held 594 * call will use VoIP audio mode (if the call does not currently have focus, the system 595 * audio mode may not reflect the mode the call will use). 596 */ 597 public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000; 598 599 /** 600 * Indicates that the call is an adhoc conference call. This property can be set for both 601 * incoming and outgoing calls. An adhoc conference call is formed using 602 * {@link #addConferenceParticipants(List)}, 603 * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or 604 * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing 605 * call using {@link #conference(Call)}. 606 */ 607 public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000; 608 609 //****************************************************************************************** 610 // Next PROPERTY value: 0x00004000 611 //****************************************************************************************** 612 613 private final String mTelecomCallId; 614 private final Uri mHandle; 615 private final int mHandlePresentation; 616 private final String mCallerDisplayName; 617 private final int mCallerDisplayNamePresentation; 618 private final PhoneAccountHandle mAccountHandle; 619 private final int mCallCapabilities; 620 private final int mCallProperties; 621 private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL; 622 private final DisconnectCause mDisconnectCause; 623 private final long mConnectTimeMillis; 624 private final GatewayInfo mGatewayInfo; 625 private final int mVideoState; 626 private final StatusHints mStatusHints; 627 private final Bundle mExtras; 628 private final Bundle mIntentExtras; 629 private final long mCreationTimeMillis; 630 private final String mContactDisplayName; 631 private final @CallDirection int mCallDirection; 632 private final @Connection.VerificationStatus int mCallerNumberVerificationStatus; 633 634 /** 635 * Whether the supplied capabilities supports the specified capability. 636 * 637 * @param capabilities A bit field of capabilities. 638 * @param capability The capability to check capabilities for. 639 * @return Whether the specified capability is supported. 640 */ can(int capabilities, int capability)641 public static boolean can(int capabilities, int capability) { 642 return (capabilities & capability) == capability; 643 } 644 645 /** 646 * Whether the capabilities of this {@code Details} supports the specified capability. 647 * 648 * @param capability The capability to check capabilities for. 649 * @return Whether the specified capability is supported. 650 */ can(int capability)651 public boolean can(int capability) { 652 return can(mCallCapabilities, capability); 653 } 654 655 /** 656 * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string. 657 * 658 * @param capabilities A capability bit field. 659 * @return A human readable string representation. 660 */ capabilitiesToString(int capabilities)661 public static String capabilitiesToString(int capabilities) { 662 StringBuilder builder = new StringBuilder(); 663 builder.append("[Capabilities:"); 664 if (can(capabilities, CAPABILITY_HOLD)) { 665 builder.append(" CAPABILITY_HOLD"); 666 } 667 if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) { 668 builder.append(" CAPABILITY_SUPPORT_HOLD"); 669 } 670 if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) { 671 builder.append(" CAPABILITY_MERGE_CONFERENCE"); 672 } 673 if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) { 674 builder.append(" CAPABILITY_SWAP_CONFERENCE"); 675 } 676 if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) { 677 builder.append(" CAPABILITY_RESPOND_VIA_TEXT"); 678 } 679 if (can(capabilities, CAPABILITY_MUTE)) { 680 builder.append(" CAPABILITY_MUTE"); 681 } 682 if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) { 683 builder.append(" CAPABILITY_MANAGE_CONFERENCE"); 684 } 685 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) { 686 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX"); 687 } 688 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) { 689 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX"); 690 } 691 if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) { 692 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL"); 693 } 694 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) { 695 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX"); 696 } 697 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) { 698 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX"); 699 } 700 if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) { 701 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO"); 702 } 703 if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) { 704 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL"); 705 } 706 if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) { 707 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO"); 708 } 709 if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) { 710 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO"); 711 } 712 if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) { 713 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO"); 714 } 715 if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) { 716 builder.append(" CAPABILITY_CAN_PULL_CALL"); 717 } 718 if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) { 719 builder.append(" CAPABILITY_SUPPORT_DEFLECT"); 720 } 721 if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) { 722 builder.append(" CAPABILITY_ADD_PARTICIPANT"); 723 } 724 if (can(capabilities, CAPABILITY_TRANSFER)) { 725 builder.append(" CAPABILITY_TRANSFER"); 726 } 727 if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) { 728 builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE"); 729 } 730 builder.append("]"); 731 return builder.toString(); 732 } 733 734 /** 735 * Whether the supplied properties includes the specified property. 736 * 737 * @param properties A bit field of properties. 738 * @param property The property to check properties for. 739 * @return Whether the specified property is supported. 740 */ hasProperty(int properties, int property)741 public static boolean hasProperty(int properties, int property) { 742 return (properties & property) == property; 743 } 744 745 /** 746 * Whether the properties of this {@code Details} includes the specified property. 747 * 748 * @param property The property to check properties for. 749 * @return Whether the specified property is supported. 750 */ hasProperty(int property)751 public boolean hasProperty(int property) { 752 return hasProperty(mCallProperties, property); 753 } 754 755 /** 756 * Render a set of property bits ({@code PROPERTY_*}) as a human readable string. 757 * 758 * @param properties A property bit field. 759 * @return A human readable string representation. 760 */ propertiesToString(int properties)761 public static String propertiesToString(int properties) { 762 StringBuilder builder = new StringBuilder(); 763 builder.append("[Properties:"); 764 if (hasProperty(properties, PROPERTY_CONFERENCE)) { 765 builder.append(" PROPERTY_CONFERENCE"); 766 } 767 if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) { 768 builder.append(" PROPERTY_GENERIC_CONFERENCE"); 769 } 770 if (hasProperty(properties, PROPERTY_WIFI)) { 771 builder.append(" PROPERTY_WIFI"); 772 } 773 if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) { 774 builder.append(" PROPERTY_HIGH_DEF_AUDIO"); 775 } 776 if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) { 777 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE"); 778 } 779 if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) { 780 builder.append(" PROPERTY_IS_EXTERNAL_CALL"); 781 } 782 if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) { 783 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY"); 784 } 785 if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) { 786 builder.append(" PROPERTY_ASSISTED_DIALING_USED"); 787 } 788 if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) { 789 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL"); 790 } 791 if (hasProperty(properties, PROPERTY_RTT)) { 792 builder.append(" PROPERTY_RTT"); 793 } 794 if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) { 795 builder.append(" PROPERTY_VOIP_AUDIO_MODE"); 796 } 797 if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) { 798 builder.append(" PROPERTY_IS_ADHOC_CONFERENCE"); 799 } 800 builder.append("]"); 801 return builder.toString(); 802 } 803 804 /** {@hide} */ 805 @TestApi getTelecomCallId()806 public String getTelecomCallId() { 807 return mTelecomCallId; 808 } 809 810 /** 811 * @return The handle (e.g., phone number) to which the {@code Call} is currently 812 * connected. 813 */ getHandle()814 public Uri getHandle() { 815 return mHandle; 816 } 817 818 /** 819 * @return The presentation requirements for the handle. See 820 * {@link TelecomManager} for valid values. 821 */ getHandlePresentation()822 public int getHandlePresentation() { 823 return mHandlePresentation; 824 } 825 826 /** 827 * The display name for the caller. 828 * <p> 829 * This is the name as reported by the {@link ConnectionService} associated with this call. 830 * 831 * @return The display name for the caller. 832 */ getCallerDisplayName()833 public String getCallerDisplayName() { 834 return mCallerDisplayName; 835 } 836 837 /** 838 * @return The presentation requirements for the caller display name. See 839 * {@link TelecomManager} for valid values. 840 */ getCallerDisplayNamePresentation()841 public int getCallerDisplayNamePresentation() { 842 return mCallerDisplayNamePresentation; 843 } 844 845 /** 846 * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being 847 * routed. 848 */ getAccountHandle()849 public PhoneAccountHandle getAccountHandle() { 850 return mAccountHandle; 851 } 852 853 /** 854 * @return A bitmask of the capabilities of the {@code Call}, as defined by the various 855 * {@code CAPABILITY_*} constants in this class. 856 */ getCallCapabilities()857 public int getCallCapabilities() { 858 return mCallCapabilities; 859 } 860 861 /** 862 * @return A bitmask of the properties of the {@code Call}, as defined by the various 863 * {@code PROPERTY_*} constants in this class. 864 */ getCallProperties()865 public int getCallProperties() { 866 return mCallProperties; 867 } 868 869 /** 870 * @return a bitmask of the audio routes available for the call. 871 * 872 * @hide 873 */ getSupportedAudioRoutes()874 public int getSupportedAudioRoutes() { 875 return mSupportedAudioRoutes; 876 } 877 878 /** 879 * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed 880 * by {@link android.telecom.DisconnectCause}. 881 */ getDisconnectCause()882 public DisconnectCause getDisconnectCause() { 883 return mDisconnectCause; 884 } 885 886 /** 887 * Returns the time the {@link Call} connected (i.e. became active). This information is 888 * updated periodically, but user interfaces should not rely on this to display the "call 889 * time clock". For the time when the call was first added to Telecom, see 890 * {@link #getCreationTimeMillis()}. 891 * 892 * @return The time the {@link Call} connected in milliseconds since the epoch. 893 */ getConnectTimeMillis()894 public final long getConnectTimeMillis() { 895 return mConnectTimeMillis; 896 } 897 898 /** 899 * @return Information about any calling gateway the {@code Call} may be using. 900 */ getGatewayInfo()901 public GatewayInfo getGatewayInfo() { 902 return mGatewayInfo; 903 } 904 905 /** 906 * @return The video state of the {@code Call}. 907 */ getVideoState()908 public int getVideoState() { 909 return mVideoState; 910 } 911 912 /** 913 * @return The current {@link android.telecom.StatusHints}, or {@code null} if none 914 * have been set. 915 */ getStatusHints()916 public StatusHints getStatusHints() { 917 return mStatusHints; 918 } 919 920 /** 921 * @return The extras associated with this call. 922 */ getExtras()923 public Bundle getExtras() { 924 return mExtras; 925 } 926 927 /** 928 * @return The extras used with the original intent to place this call. 929 */ getIntentExtras()930 public Bundle getIntentExtras() { 931 return mIntentExtras; 932 } 933 934 /** 935 * Returns the time when the call was first created and added to Telecom. This is the same 936 * time that is logged as the start time in the Call Log (see 937 * {@link android.provider.CallLog.Calls#DATE}). To determine when the call was connected 938 * (became active), see {@link #getConnectTimeMillis()}. 939 * 940 * @return The creation time of the call, in millis since the epoch. 941 */ getCreationTimeMillis()942 public long getCreationTimeMillis() { 943 return mCreationTimeMillis; 944 } 945 946 /** 947 * Returns the name of the caller on the remote end, as derived from a 948 * {@link android.provider.ContactsContract} lookup of the call's handle. 949 * @return The name of the caller, or {@code null} if the lookup is not yet complete, if 950 * there's no contacts entry for the caller, or if the {@link InCallService} does 951 * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission. 952 */ getContactDisplayName()953 public @Nullable String getContactDisplayName() { 954 return mContactDisplayName; 955 } 956 957 /** 958 * Indicates whether the call is an incoming or outgoing call. 959 * @return The call's direction. 960 */ getCallDirection()961 public @CallDirection int getCallDirection() { 962 return mCallDirection; 963 } 964 965 /** 966 * Gets the verification status for the phone number of an incoming call as identified in 967 * ATIS-1000082. 968 * @return the verification status. 969 */ getCallerNumberVerificationStatus()970 public @Connection.VerificationStatus int getCallerNumberVerificationStatus() { 971 return mCallerNumberVerificationStatus; 972 } 973 974 @Override equals(Object o)975 public boolean equals(Object o) { 976 if (o instanceof Details) { 977 Details d = (Details) o; 978 return 979 Objects.equals(mHandle, d.mHandle) && 980 Objects.equals(mHandlePresentation, d.mHandlePresentation) && 981 Objects.equals(mCallerDisplayName, d.mCallerDisplayName) && 982 Objects.equals(mCallerDisplayNamePresentation, 983 d.mCallerDisplayNamePresentation) && 984 Objects.equals(mAccountHandle, d.mAccountHandle) && 985 Objects.equals(mCallCapabilities, d.mCallCapabilities) && 986 Objects.equals(mCallProperties, d.mCallProperties) && 987 Objects.equals(mDisconnectCause, d.mDisconnectCause) && 988 Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) && 989 Objects.equals(mGatewayInfo, d.mGatewayInfo) && 990 Objects.equals(mVideoState, d.mVideoState) && 991 Objects.equals(mStatusHints, d.mStatusHints) && 992 areBundlesEqual(mExtras, d.mExtras) && 993 areBundlesEqual(mIntentExtras, d.mIntentExtras) && 994 Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) && 995 Objects.equals(mContactDisplayName, d.mContactDisplayName) && 996 Objects.equals(mCallDirection, d.mCallDirection) && 997 Objects.equals(mCallerNumberVerificationStatus, 998 d.mCallerNumberVerificationStatus); 999 } 1000 return false; 1001 } 1002 1003 @Override hashCode()1004 public int hashCode() { 1005 return Objects.hash(mHandle, 1006 mHandlePresentation, 1007 mCallerDisplayName, 1008 mCallerDisplayNamePresentation, 1009 mAccountHandle, 1010 mCallCapabilities, 1011 mCallProperties, 1012 mDisconnectCause, 1013 mConnectTimeMillis, 1014 mGatewayInfo, 1015 mVideoState, 1016 mStatusHints, 1017 mExtras, 1018 mIntentExtras, 1019 mCreationTimeMillis, 1020 mContactDisplayName, 1021 mCallDirection, 1022 mCallerNumberVerificationStatus); 1023 } 1024 1025 /** {@hide} */ Details( String telecomCallId, Uri handle, int handlePresentation, String callerDisplayName, int callerDisplayNamePresentation, PhoneAccountHandle accountHandle, int capabilities, int properties, DisconnectCause disconnectCause, long connectTimeMillis, GatewayInfo gatewayInfo, int videoState, StatusHints statusHints, Bundle extras, Bundle intentExtras, long creationTimeMillis, String contactDisplayName, int callDirection, int callerNumberVerificationStatus)1026 public Details( 1027 String telecomCallId, 1028 Uri handle, 1029 int handlePresentation, 1030 String callerDisplayName, 1031 int callerDisplayNamePresentation, 1032 PhoneAccountHandle accountHandle, 1033 int capabilities, 1034 int properties, 1035 DisconnectCause disconnectCause, 1036 long connectTimeMillis, 1037 GatewayInfo gatewayInfo, 1038 int videoState, 1039 StatusHints statusHints, 1040 Bundle extras, 1041 Bundle intentExtras, 1042 long creationTimeMillis, 1043 String contactDisplayName, 1044 int callDirection, 1045 int callerNumberVerificationStatus) { 1046 mTelecomCallId = telecomCallId; 1047 mHandle = handle; 1048 mHandlePresentation = handlePresentation; 1049 mCallerDisplayName = callerDisplayName; 1050 mCallerDisplayNamePresentation = callerDisplayNamePresentation; 1051 mAccountHandle = accountHandle; 1052 mCallCapabilities = capabilities; 1053 mCallProperties = properties; 1054 mDisconnectCause = disconnectCause; 1055 mConnectTimeMillis = connectTimeMillis; 1056 mGatewayInfo = gatewayInfo; 1057 mVideoState = videoState; 1058 mStatusHints = statusHints; 1059 mExtras = extras; 1060 mIntentExtras = intentExtras; 1061 mCreationTimeMillis = creationTimeMillis; 1062 mContactDisplayName = contactDisplayName; 1063 mCallDirection = callDirection; 1064 mCallerNumberVerificationStatus = callerNumberVerificationStatus; 1065 } 1066 1067 /** {@hide} */ createFromParcelableCall(ParcelableCall parcelableCall)1068 public static Details createFromParcelableCall(ParcelableCall parcelableCall) { 1069 return new Details( 1070 parcelableCall.getId(), 1071 parcelableCall.getHandle(), 1072 parcelableCall.getHandlePresentation(), 1073 parcelableCall.getCallerDisplayName(), 1074 parcelableCall.getCallerDisplayNamePresentation(), 1075 parcelableCall.getAccountHandle(), 1076 parcelableCall.getCapabilities(), 1077 parcelableCall.getProperties(), 1078 parcelableCall.getDisconnectCause(), 1079 parcelableCall.getConnectTimeMillis(), 1080 parcelableCall.getGatewayInfo(), 1081 parcelableCall.getVideoState(), 1082 parcelableCall.getStatusHints(), 1083 parcelableCall.getExtras(), 1084 parcelableCall.getIntentExtras(), 1085 parcelableCall.getCreationTimeMillis(), 1086 parcelableCall.getContactDisplayName(), 1087 parcelableCall.getCallDirection(), 1088 parcelableCall.getCallerNumberVerificationStatus()); 1089 } 1090 1091 @Override toString()1092 public String toString() { 1093 StringBuilder sb = new StringBuilder(); 1094 sb.append("[id: "); 1095 sb.append(mTelecomCallId); 1096 sb.append(", pa: "); 1097 sb.append(mAccountHandle); 1098 sb.append(", hdl: "); 1099 sb.append(Log.piiHandle(mHandle)); 1100 sb.append(", hdlPres: "); 1101 sb.append(mHandlePresentation); 1102 sb.append(", videoState: "); 1103 sb.append(VideoProfile.videoStateToString(mVideoState)); 1104 sb.append(", caps: "); 1105 sb.append(capabilitiesToString(mCallCapabilities)); 1106 sb.append(", props: "); 1107 sb.append(propertiesToString(mCallProperties)); 1108 sb.append("]"); 1109 return sb.toString(); 1110 } 1111 } 1112 1113 /** 1114 * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}. 1115 * These callbacks can originate from the Telecom framework, or a {@link ConnectionService} 1116 * implementation. 1117 * <p> 1118 * You can handle these callbacks by extending the {@link Callback} class and overriding the 1119 * callbacks that your {@link InCallService} is interested in. The callback methods include the 1120 * {@link Call} for which the callback applies, allowing reuse of a single instance of your 1121 * {@link Callback} implementation, if desired. 1122 * <p> 1123 * Use {@link Call#registerCallback(Callback)} to register your callback(s). Ensure 1124 * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks 1125 * (typically in {@link InCallService#onCallRemoved(Call)}). 1126 * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not 1127 * reach your implementation of {@link Callback}, so it is important to register your callback 1128 * as soon as your {@link InCallService} is notified of a new call via 1129 * {@link InCallService#onCallAdded(Call)}. 1130 */ 1131 public static abstract class Callback { 1132 /** 1133 * @hide 1134 */ 1135 @IntDef(prefix = { "HANDOVER_" }, 1136 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED, 1137 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL, 1138 HANDOVER_FAILURE_UNKNOWN}) 1139 @Retention(RetentionPolicy.SOURCE) 1140 public @interface HandoverFailureErrors {} 1141 1142 /** 1143 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app 1144 * to handover the call to rejects the handover request. 1145 * <p> 1146 * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called 1147 * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a 1148 * {@code null} {@link Connection} from 1149 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle, 1150 * ConnectionRequest)}. 1151 * <p> 1152 * For more information on call handovers, see 1153 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}. 1154 */ 1155 public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; 1156 1157 /** 1158 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover 1159 * is initiated but the source or destination app does not support handover. 1160 * <p> 1161 * Will be returned when a handover is requested via 1162 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination 1163 * {@link PhoneAccountHandle} does not declare 1164 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. May also be returned when a handover is 1165 * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's 1166 * {@link Details#getAccountHandle()}) does not declare 1167 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. 1168 * <p> 1169 * For more information on call handovers, see 1170 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}. 1171 */ 1172 public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2; 1173 1174 /** 1175 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote 1176 * user rejects the handover request. 1177 * <p> 1178 * For more information on call handovers, see 1179 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}. 1180 */ 1181 public static final int HANDOVER_FAILURE_USER_REJECTED = 3; 1182 1183 /** 1184 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there 1185 * is ongoing emergency call. 1186 * <p> 1187 * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is 1188 * called on an emergency call, or if any other call is an emergency call. 1189 * <p> 1190 * Handovers are not permitted while there are ongoing emergency calls. 1191 * <p> 1192 * For more information on call handovers, see 1193 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}. 1194 */ 1195 public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4; 1196 1197 /** 1198 * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover 1199 * fails for an unknown reason. 1200 * <p> 1201 * For more information on call handovers, see 1202 * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}. 1203 */ 1204 public static final int HANDOVER_FAILURE_UNKNOWN = 5; 1205 1206 /** 1207 * Invoked when the state of this {@code Call} has changed. See {@link #getState()}. 1208 * 1209 * @param call The {@code Call} invoking this method. 1210 * @param state The new state of the {@code Call}. 1211 */ onStateChanged(Call call, int state)1212 public void onStateChanged(Call call, int state) {} 1213 1214 /** 1215 * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}. 1216 * 1217 * @param call The {@code Call} invoking this method. 1218 * @param parent The new parent of the {@code Call}. 1219 */ onParentChanged(Call call, Call parent)1220 public void onParentChanged(Call call, Call parent) {} 1221 1222 /** 1223 * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}. 1224 * 1225 * @param call The {@code Call} invoking this method. 1226 * @param children The new children of the {@code Call}. 1227 */ onChildrenChanged(Call call, List<Call> children)1228 public void onChildrenChanged(Call call, List<Call> children) {} 1229 1230 /** 1231 * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}. 1232 * 1233 * @param call The {@code Call} invoking this method. 1234 * @param details A {@code Details} object describing the {@code Call}. 1235 */ onDetailsChanged(Call call, Details details)1236 public void onDetailsChanged(Call call, Details details) {} 1237 1238 /** 1239 * Invoked when the text messages that can be used as responses to the incoming 1240 * {@code Call} are loaded from the relevant database. 1241 * See {@link #getCannedTextResponses()}. 1242 * 1243 * @param call The {@code Call} invoking this method. 1244 * @param cannedTextResponses The text messages useable as responses. 1245 */ onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses)1246 public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {} 1247 1248 /** 1249 * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause 1250 * character. This causes the post-dial signals to stop pending user confirmation. An 1251 * implementation should present this choice to the user and invoke 1252 * {@link #postDialContinue(boolean)} when the user makes the choice. 1253 * 1254 * @param call The {@code Call} invoking this method. 1255 * @param remainingPostDialSequence The post-dial characters that remain to be sent. 1256 */ onPostDialWait(Call call, String remainingPostDialSequence)1257 public void onPostDialWait(Call call, String remainingPostDialSequence) {} 1258 1259 /** 1260 * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed. 1261 * 1262 * @param call The {@code Call} invoking this method. 1263 * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}. 1264 */ onVideoCallChanged(Call call, InCallService.VideoCall videoCall)1265 public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {} 1266 1267 /** 1268 * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning 1269 * up their UI for the {@code Call} in response to state transitions. Specifically, 1270 * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of 1271 * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather, 1272 * clients should wait for this method to be invoked. 1273 * 1274 * @param call The {@code Call} being destroyed. 1275 */ onCallDestroyed(Call call)1276 public void onCallDestroyed(Call call) {} 1277 1278 /** 1279 * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be 1280 * conferenced. 1281 * 1282 * @param call The {@code Call} being updated. 1283 * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be 1284 * conferenced. 1285 */ onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls)1286 public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {} 1287 1288 /** 1289 * Invoked when a {@link Call} receives an event from its associated {@link Connection} or 1290 * {@link Conference}. 1291 * <p> 1292 * Where possible, the Call should make an attempt to handle {@link Connection} events which 1293 * are part of the {@code android.telecom.*} namespace. The Call should ignore any events 1294 * it does not wish to handle. Unexpected events should be handled gracefully, as it is 1295 * possible that a {@link ConnectionService} has defined its own Connection events which a 1296 * Call is not aware of. 1297 * <p> 1298 * See {@link Connection#sendConnectionEvent(String, Bundle)}, 1299 * {@link Conference#sendConferenceEvent(String, Bundle)}. 1300 * 1301 * @param call The {@code Call} receiving the event. 1302 * @param event The event. 1303 * @param extras Extras associated with the connection event. 1304 */ onConnectionEvent(Call call, String event, Bundle extras)1305 public void onConnectionEvent(Call call, String event, Bundle extras) {} 1306 1307 /** 1308 * Invoked when the RTT mode changes for this call. 1309 * @param call The call whose RTT mode has changed. 1310 * @param mode the new RTT mode, one of 1311 * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO}, 1312 * or {@link RttCall#RTT_MODE_VCO} 1313 */ onRttModeChanged(Call call, int mode)1314 public void onRttModeChanged(Call call, int mode) {} 1315 1316 /** 1317 * Invoked when the call's RTT status changes, either from off to on or from on to off. 1318 * @param call The call whose RTT status has changed. 1319 * @param enabled whether RTT is now enabled or disabled 1320 * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now 1321 * on, null otherwise. 1322 */ onRttStatusChanged(Call call, boolean enabled, RttCall rttCall)1323 public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {} 1324 1325 /** 1326 * Invoked when the remote end of the connection has requested that an RTT communication 1327 * channel be opened. A response to this should be sent via {@link #respondToRttRequest} 1328 * with the same ID that this method is invoked with. 1329 * @param call The call which the RTT request was placed on 1330 * @param id The ID of the request. 1331 */ onRttRequest(Call call, int id)1332 public void onRttRequest(Call call, int id) {} 1333 1334 /** 1335 * Invoked when the RTT session failed to initiate for some reason, including rejection 1336 * by the remote party. 1337 * @param call The call which the RTT initiation failure occurred on. 1338 * @param reason One of the status codes defined in 1339 * {@link android.telecom.Connection.RttModifyStatus}, with the exception of 1340 * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}. 1341 */ onRttInitiationFailure(Call call, int reason)1342 public void onRttInitiationFailure(Call call, int reason) {} 1343 1344 /** 1345 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount} 1346 * has completed successfully. 1347 * <p> 1348 * For a full discussion of the handover process and the APIs involved, see 1349 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}. 1350 * 1351 * @param call The call which had initiated handover. 1352 */ onHandoverComplete(Call call)1353 public void onHandoverComplete(Call call) {} 1354 1355 /** 1356 * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount} 1357 * has failed. 1358 * <p> 1359 * For a full discussion of the handover process and the APIs involved, see 1360 * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}. 1361 * 1362 * @param call The call which had initiated handover. 1363 * @param failureReason Error reason for failure. 1364 */ onHandoverFailed(Call call, @HandoverFailureErrors int failureReason)1365 public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {} 1366 } 1367 1368 /** 1369 * A class that holds the state that describes the state of the RTT channel to the remote 1370 * party, if it is active. 1371 */ 1372 public static final class RttCall { 1373 /** @hide */ 1374 @Retention(RetentionPolicy.SOURCE) 1375 @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO}) 1376 public @interface RttAudioMode {} 1377 1378 /** 1379 * For metrics use. Default value in the proto. 1380 * @hide 1381 */ 1382 public static final int RTT_MODE_INVALID = 0; 1383 1384 /** 1385 * Indicates that there should be a bidirectional audio stream between the two parties 1386 * on the call. 1387 */ 1388 public static final int RTT_MODE_FULL = 1; 1389 1390 /** 1391 * Indicates that the local user should be able to hear the audio stream from the remote 1392 * user, but not vice versa. Equivalent to muting the microphone. 1393 */ 1394 public static final int RTT_MODE_HCO = 2; 1395 1396 /** 1397 * Indicates that the remote user should be able to hear the audio stream from the local 1398 * user, but not vice versa. Equivalent to setting the volume to zero. 1399 */ 1400 public static final int RTT_MODE_VCO = 3; 1401 1402 private static final int READ_BUFFER_SIZE = 1000; 1403 1404 private InputStreamReader mReceiveStream; 1405 private OutputStreamWriter mTransmitStream; 1406 private int mRttMode; 1407 private final InCallAdapter mInCallAdapter; 1408 private final String mTelecomCallId; 1409 private char[] mReadBuffer = new char[READ_BUFFER_SIZE]; 1410 1411 /** 1412 * @hide 1413 */ RttCall(String telecomCallId, InputStreamReader receiveStream, OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter)1414 public RttCall(String telecomCallId, InputStreamReader receiveStream, 1415 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) { 1416 mTelecomCallId = telecomCallId; 1417 mReceiveStream = receiveStream; 1418 mTransmitStream = transmitStream; 1419 mRttMode = mode; 1420 mInCallAdapter = inCallAdapter; 1421 } 1422 1423 /** 1424 * Returns the current RTT audio mode. 1425 * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or 1426 * {@link #RTT_MODE_HCO}. 1427 */ getRttAudioMode()1428 public int getRttAudioMode() { 1429 return mRttMode; 1430 } 1431 1432 /** 1433 * Sets the RTT audio mode. The requested mode change will be communicated through 1434 * {@link Callback#onRttModeChanged(Call, int)}. 1435 * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL}, 1436 * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}. 1437 */ setRttMode(@ttAudioMode int mode)1438 public void setRttMode(@RttAudioMode int mode) { 1439 mInCallAdapter.setRttMode(mTelecomCallId, mode); 1440 } 1441 1442 /** 1443 * Writes the string {@param input} into the outgoing text stream for this RTT call. Since 1444 * RTT transmits text in real-time, this method should be called once for each character 1445 * the user enters into the device. 1446 * 1447 * This method is not thread-safe -- calling it from multiple threads simultaneously may 1448 * lead to interleaved text. 1449 * @param input The message to send to the remote user. 1450 */ write(String input)1451 public void write(String input) throws IOException { 1452 mTransmitStream.write(input); 1453 mTransmitStream.flush(); 1454 } 1455 1456 /** 1457 * Reads a string from the remote user, blocking if there is no data available. Returns 1458 * {@code null} if the RTT conversation has been terminated and there is no further data 1459 * to read. 1460 * 1461 * This method is not thread-safe -- calling it from multiple threads simultaneously may 1462 * lead to interleaved text. 1463 * @return A string containing text sent by the remote user, or {@code null} if the 1464 * conversation has been terminated or if there was an error while reading. 1465 */ read()1466 public String read() { 1467 try { 1468 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE); 1469 if (numRead < 0) { 1470 return null; 1471 } 1472 return new String(mReadBuffer, 0, numRead); 1473 } catch (IOException e) { 1474 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e); 1475 return null; 1476 } 1477 } 1478 1479 /** 1480 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to 1481 * be read. 1482 * @return A string containing text entered by the user, or {@code null} if the user has 1483 * not entered any new text yet. 1484 */ readImmediately()1485 public String readImmediately() throws IOException { 1486 if (mReceiveStream.ready()) { 1487 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE); 1488 if (numRead < 0) { 1489 return null; 1490 } 1491 return new String(mReadBuffer, 0, numRead); 1492 } else { 1493 return null; 1494 } 1495 } 1496 1497 /** 1498 * Closes the underlying file descriptors 1499 * @hide 1500 */ close()1501 public void close() { 1502 try { 1503 mReceiveStream.close(); 1504 } catch (IOException e) { 1505 // ignore 1506 } 1507 try { 1508 mTransmitStream.close(); 1509 } catch (IOException e) { 1510 // ignore 1511 } 1512 } 1513 } 1514 1515 /** 1516 * @deprecated Use {@code Call.Callback} instead. 1517 * @hide 1518 */ 1519 @Deprecated 1520 @SystemApi 1521 public static abstract class Listener extends Callback { } 1522 1523 private final Phone mPhone; 1524 private final String mTelecomCallId; 1525 private final InCallAdapter mInCallAdapter; 1526 private final List<String> mChildrenIds = new ArrayList<>(); 1527 private final List<Call> mChildren = new ArrayList<>(); 1528 private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren); 1529 private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>(); 1530 private final List<Call> mConferenceableCalls = new ArrayList<>(); 1531 private final List<Call> mUnmodifiableConferenceableCalls = 1532 Collections.unmodifiableList(mConferenceableCalls); 1533 1534 private boolean mChildrenCached; 1535 private String mParentId = null; 1536 private String mActiveGenericConferenceChild = null; 1537 private int mState; 1538 private List<String> mCannedTextResponses = null; 1539 private String mCallingPackage; 1540 private int mTargetSdkVersion; 1541 private String mRemainingPostDialSequence; 1542 private VideoCallImpl mVideoCallImpl; 1543 private RttCall mRttCall; 1544 private Details mDetails; 1545 private Bundle mExtras; 1546 1547 /** 1548 * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any. 1549 * 1550 * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence 1551 * remaining or this {@code Call} is not in a post-dial state. 1552 */ getRemainingPostDialSequence()1553 public String getRemainingPostDialSequence() { 1554 return mRemainingPostDialSequence; 1555 } 1556 1557 /** 1558 * Instructs this {@link #STATE_RINGING} {@code Call} to answer. 1559 * @param videoState The video state in which to answer the call. 1560 */ answer(@ideoProfile.VideoState int videoState)1561 public void answer(@VideoProfile.VideoState int videoState) { 1562 mInCallAdapter.answerCall(mTelecomCallId, videoState); 1563 } 1564 1565 /** 1566 * Instructs this {@link #STATE_RINGING} {@code Call} to deflect. 1567 * 1568 * @param address The address to which the call will be deflected. 1569 */ deflect(Uri address)1570 public void deflect(Uri address) { 1571 mInCallAdapter.deflectCall(mTelecomCallId, address); 1572 } 1573 1574 /** 1575 * Instructs this {@link #STATE_RINGING} {@code Call} to reject. 1576 * 1577 * @param rejectWithMessage Whether to reject with a text message. 1578 * @param textMessage An optional text message with which to respond. 1579 */ reject(boolean rejectWithMessage, String textMessage)1580 public void reject(boolean rejectWithMessage, String textMessage) { 1581 mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage); 1582 } 1583 1584 /** 1585 * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the 1586 * user has chosen to reject the call and has indicated a reason why the call is being rejected. 1587 * 1588 * @param rejectReason the reason the call is being rejected. 1589 */ reject(@ejectReason int rejectReason)1590 public void reject(@RejectReason int rejectReason) { 1591 mInCallAdapter.rejectCall(mTelecomCallId, rejectReason); 1592 } 1593 1594 /** 1595 * Instructs this {@code Call} to be transferred to another number. 1596 * 1597 * @param targetNumber The address to which the call will be transferred. 1598 * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer, 1599 * if {@code false}, it will initiate an unconfirmed transfer. 1600 * 1601 * @hide 1602 */ transfer(@onNull Uri targetNumber, boolean isConfirmationRequired)1603 public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) { 1604 mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired); 1605 } 1606 1607 /** 1608 * Instructs this {@code Call} to be transferred to another ongoing call. 1609 * This will initiate CONSULTATIVE transfer. 1610 * @param toCall The other ongoing {@code Call} to which this call will be transferred. 1611 * 1612 * @hide 1613 */ transfer(@onNull android.telecom.Call toCall)1614 public void transfer(@NonNull android.telecom.Call toCall) { 1615 mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId); 1616 } 1617 1618 /** 1619 * Instructs this {@code Call} to disconnect. 1620 */ disconnect()1621 public void disconnect() { 1622 mInCallAdapter.disconnectCall(mTelecomCallId); 1623 } 1624 1625 /** 1626 * Instructs this {@code Call} to go on hold. 1627 */ hold()1628 public void hold() { 1629 mInCallAdapter.holdCall(mTelecomCallId); 1630 } 1631 1632 /** 1633 * Instructs this {@link #STATE_HOLDING} call to release from hold. 1634 */ unhold()1635 public void unhold() { 1636 mInCallAdapter.unholdCall(mTelecomCallId); 1637 } 1638 1639 /** 1640 * Instructs Telecom to put the call into the background audio processing state. 1641 * 1642 * This method can be called either when the call is in {@link #STATE_RINGING} or 1643 * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to 1644 * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in 1645 * order to capture and play audio on the call stream. 1646 * 1647 * This method can only be called by the default dialer app. 1648 * @hide 1649 */ 1650 @SystemApi 1651 @TestApi enterBackgroundAudioProcessing()1652 public void enterBackgroundAudioProcessing() { 1653 if (mState != STATE_ACTIVE && mState != STATE_RINGING) { 1654 throw new IllegalStateException("Call must be active or ringing"); 1655 } 1656 mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId); 1657 } 1658 1659 /** 1660 * Instructs Telecom to come out of the background audio processing state requested by 1661 * {@link #enterBackgroundAudioProcessing()} or from the call screening service. 1662 * 1663 * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}. 1664 * 1665 * @param shouldRing If true, Telecom will put the call into the 1666 * {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is 1667 * a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE} 1668 * immediately. 1669 * @hide 1670 */ 1671 @SystemApi 1672 @TestApi exitBackgroundAudioProcessing(boolean shouldRing)1673 public void exitBackgroundAudioProcessing(boolean shouldRing) { 1674 if (mState != STATE_AUDIO_PROCESSING) { 1675 throw new IllegalStateException("Call must in the audio processing state"); 1676 } 1677 mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing); 1678 } 1679 1680 /** 1681 * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone. 1682 * 1683 * Any other currently playing DTMF tone in the specified call is immediately stopped. 1684 * 1685 * @param digit A character representing the DTMF digit for which to play the tone. This 1686 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}. 1687 */ playDtmfTone(char digit)1688 public void playDtmfTone(char digit) { 1689 mInCallAdapter.playDtmfTone(mTelecomCallId, digit); 1690 } 1691 1692 /** 1693 * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone 1694 * currently playing. 1695 * 1696 * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is 1697 * currently playing, this method will do nothing. 1698 */ stopDtmfTone()1699 public void stopDtmfTone() { 1700 mInCallAdapter.stopDtmfTone(mTelecomCallId); 1701 } 1702 1703 /** 1704 * Instructs this {@code Call} to continue playing a post-dial DTMF string. 1705 * 1706 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed, 1707 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made. 1708 * 1709 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this 1710 * {@code Call} will temporarily pause playing the tones for a pre-defined period of time. 1711 * 1712 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this 1713 * {@code Call} will pause playing the tones and notify callbacks via 1714 * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app 1715 * should display to the user an indication of this state and an affordance to continue 1716 * the postdial sequence. When the user decides to continue the postdial sequence, the in-call 1717 * app should invoke the {@link #postDialContinue(boolean)} method. 1718 * 1719 * @param proceed Whether or not to continue with the post-dial sequence. 1720 */ postDialContinue(boolean proceed)1721 public void postDialContinue(boolean proceed) { 1722 mInCallAdapter.postDialContinue(mTelecomCallId, proceed); 1723 } 1724 1725 /** 1726 * Notifies this {@code Call} that an account has been selected and to proceed with placing 1727 * an outgoing call. Optionally sets this account as the default account. 1728 */ phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault)1729 public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) { 1730 mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault); 1731 1732 } 1733 1734 /** 1735 * Instructs this {@code Call} to enter a conference. 1736 * 1737 * @param callToConferenceWith The other call with which to conference. 1738 */ conference(Call callToConferenceWith)1739 public void conference(Call callToConferenceWith) { 1740 if (callToConferenceWith != null) { 1741 mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId); 1742 } 1743 } 1744 1745 /** 1746 * Instructs this {@code Call} to split from any conference call with which it may be 1747 * connected. 1748 */ splitFromConference()1749 public void splitFromConference() { 1750 mInCallAdapter.splitFromConference(mTelecomCallId); 1751 } 1752 1753 /** 1754 * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}. 1755 */ mergeConference()1756 public void mergeConference() { 1757 mInCallAdapter.mergeConference(mTelecomCallId); 1758 } 1759 1760 /** 1761 * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}. 1762 */ swapConference()1763 public void swapConference() { 1764 mInCallAdapter.swapConference(mTelecomCallId); 1765 } 1766 1767 /** 1768 * Pulls participants to existing call by forming a conference call. 1769 * See {@link Details#CAPABILITY_ADD_PARTICIPANT}. 1770 * 1771 * @param participants participants to be pulled to existing call. 1772 */ addConferenceParticipants(@onNull List<Uri> participants)1773 public void addConferenceParticipants(@NonNull List<Uri> participants) { 1774 mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants); 1775 } 1776 1777 /** 1778 * Initiates a request to the {@link ConnectionService} to pull an external call to the local 1779 * device. 1780 * <p> 1781 * Calls to this method are ignored if the call does not have the 1782 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set. 1783 * <p> 1784 * An {@link InCallService} will only see calls which support this method if it has the 1785 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} 1786 * in its manifest. 1787 */ pullExternalCall()1788 public void pullExternalCall() { 1789 // If this isn't an external call, ignore the request. 1790 if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) { 1791 return; 1792 } 1793 1794 mInCallAdapter.pullExternalCall(mTelecomCallId); 1795 } 1796 1797 /** 1798 * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in 1799 * the {@link ConnectionService}. 1800 * <p> 1801 * Call events are used to communicate point in time information from an {@link InCallService} 1802 * to a {@link ConnectionService}. A {@link ConnectionService} implementation could define 1803 * events which enable the {@link InCallService}, for example, toggle a unique feature of the 1804 * {@link ConnectionService}. 1805 * <p> 1806 * A {@link ConnectionService} can communicate to the {@link InCallService} using 1807 * {@link Connection#sendConnectionEvent(String, Bundle)}. 1808 * <p> 1809 * Events are exposed to {@link ConnectionService} implementations via 1810 * {@link android.telecom.Connection#onCallEvent(String, Bundle)}. 1811 * <p> 1812 * No assumptions should be made as to how a {@link ConnectionService} will handle these events. 1813 * The {@link InCallService} must assume that the {@link ConnectionService} could chose to 1814 * ignore some events altogether. 1815 * <p> 1816 * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid 1817 * conflicts between {@link InCallService} implementations. Further, {@link InCallService} 1818 * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall 1819 * they define their own event types in this namespace. When defining a custom event type, 1820 * ensure the contents of the extras {@link Bundle} is clearly defined. Extra keys for this 1821 * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}). 1822 * <p> 1823 * When defining events and the associated extras, it is important to keep their behavior 1824 * consistent when the associated {@link InCallService} is updated. Support for deprecated 1825 * events/extras should me maintained to ensure backwards compatibility with older 1826 * {@link ConnectionService} implementations which were built to support the older behavior. 1827 * 1828 * @param event The connection event. 1829 * @param extras Bundle containing extra information associated with the event. 1830 */ sendCallEvent(String event, Bundle extras)1831 public void sendCallEvent(String event, Bundle extras) { 1832 mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras); 1833 } 1834 1835 /** 1836 * Sends an RTT upgrade request to the remote end of the connection. Success is not 1837 * guaranteed, and notification of success will be via the 1838 * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback. 1839 */ sendRttRequest()1840 public void sendRttRequest() { 1841 mInCallAdapter.sendRttRequest(mTelecomCallId); 1842 } 1843 1844 /** 1845 * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )} 1846 * callback. 1847 * The ID used here should be the same as the ID that was received via the callback. 1848 * @param id The request ID received via {@link Callback#onRttRequest(Call, int)} 1849 * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise. 1850 */ respondToRttRequest(int id, boolean accept)1851 public void respondToRttRequest(int id, boolean accept) { 1852 mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept); 1853 } 1854 1855 /** 1856 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified 1857 * by {@code toHandle}. The videoState specified indicates the desired video state after the 1858 * handover. 1859 * <p> 1860 * A call handover is the process where an ongoing call is transferred from one app (i.e. 1861 * {@link ConnectionService} to another app. The user could, for example, choose to continue a 1862 * mobile network call in a video calling app. The mobile network call via the Telephony stack 1863 * is referred to as the source of the handover, and the video calling app is referred to as the 1864 * destination. 1865 * <p> 1866 * When considering a handover scenario the device this method is called on is considered the 1867 * <em>initiating</em> device (since the user initiates the handover from this device), and the 1868 * other device is considered the <em>receiving</em> device. 1869 * <p> 1870 * When this method is called on the <em>initiating</em> device, the Telecom framework will bind 1871 * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle} 1872 * and invoke 1873 * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle, 1874 * ConnectionRequest)} to inform the destination app that a request has been made to handover a 1875 * call to it. The app returns an instance of {@link Connection} to represent the handover call 1876 * At this point the app should display UI to indicate to the user that a call 1877 * handover is in process. 1878 * <p> 1879 * The destination app is responsible for communicating the handover request from the 1880 * <em>initiating</em> device to the <em>receiving</em> device. 1881 * <p> 1882 * When the app on the <em>receiving</em> device receives the handover request, it calls 1883 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover 1884 * process from the <em>initiating</em> device to the <em>receiving</em> device. At this point 1885 * the destination app on the <em>receiving</em> device should show UI to allow the user to 1886 * choose whether they want to continue their call in the destination app. 1887 * <p> 1888 * When the destination app on the <em>receiving</em> device calls 1889 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its 1890 * {@link ConnectionService} and call 1891 * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle, 1892 * ConnectionRequest)} to inform it of the handover request. The app returns an instance of 1893 * {@link Connection} to represent the handover call. 1894 * <p> 1895 * If the user of the <em>receiving</em> device accepts the handover, the app calls 1896 * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the 1897 * original call. If the user rejects the handover, the app calls 1898 * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause} 1899 * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled. 1900 * <p> 1901 * Telecom will only allow handovers from {@link PhoneAccount}s which declare 1902 * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}. Similarly, the {@link PhoneAccount} 1903 * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}. 1904 * <p> 1905 * Errors in the handover process are reported to the {@link InCallService} via 1906 * {@link Callback#onHandoverFailed(Call, int)}. Errors in the handover process are reported to 1907 * the involved {@link ConnectionService}s via 1908 * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}. 1909 * 1910 * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover 1911 * this call to. 1912 * @param videoState Indicates the video state desired after the handover (see the 1913 * {@code STATE_*} constants defined in {@link VideoProfile}). 1914 * @param extras Bundle containing extra information to be passed to the 1915 * {@link ConnectionService} 1916 */ handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState, Bundle extras)1917 public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState, 1918 Bundle extras) { 1919 mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras); 1920 } 1921 1922 /** 1923 * Terminate the RTT session on this call. The resulting state change will be notified via 1924 * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback. 1925 */ stopRtt()1926 public void stopRtt() { 1927 mInCallAdapter.stopRtt(mTelecomCallId); 1928 } 1929 1930 /** 1931 * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are 1932 * added. 1933 * <p> 1934 * No assumptions should be made as to how an In-Call UI or service will handle these 1935 * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts. 1936 * 1937 * @param extras The extras to add. 1938 */ putExtras(Bundle extras)1939 public final void putExtras(Bundle extras) { 1940 if (extras == null) { 1941 return; 1942 } 1943 1944 if (mExtras == null) { 1945 mExtras = new Bundle(); 1946 } 1947 mExtras.putAll(extras); 1948 mInCallAdapter.putExtras(mTelecomCallId, extras); 1949 } 1950 1951 /** 1952 * Adds a boolean extra to this {@link Call}. 1953 * 1954 * @param key The extra key. 1955 * @param value The value. 1956 * @hide 1957 */ putExtra(String key, boolean value)1958 public final void putExtra(String key, boolean value) { 1959 if (mExtras == null) { 1960 mExtras = new Bundle(); 1961 } 1962 mExtras.putBoolean(key, value); 1963 mInCallAdapter.putExtra(mTelecomCallId, key, value); 1964 } 1965 1966 /** 1967 * Adds an integer extra to this {@link Call}. 1968 * 1969 * @param key The extra key. 1970 * @param value The value. 1971 * @hide 1972 */ putExtra(String key, int value)1973 public final void putExtra(String key, int value) { 1974 if (mExtras == null) { 1975 mExtras = new Bundle(); 1976 } 1977 mExtras.putInt(key, value); 1978 mInCallAdapter.putExtra(mTelecomCallId, key, value); 1979 } 1980 1981 /** 1982 * Adds a string extra to this {@link Call}. 1983 * 1984 * @param key The extra key. 1985 * @param value The value. 1986 * @hide 1987 */ putExtra(String key, String value)1988 public final void putExtra(String key, String value) { 1989 if (mExtras == null) { 1990 mExtras = new Bundle(); 1991 } 1992 mExtras.putString(key, value); 1993 mInCallAdapter.putExtra(mTelecomCallId, key, value); 1994 } 1995 1996 /** 1997 * Removes extras from this {@link Call}. 1998 * 1999 * @param keys The keys of the extras to remove. 2000 */ removeExtras(List<String> keys)2001 public final void removeExtras(List<String> keys) { 2002 if (mExtras != null) { 2003 for (String key : keys) { 2004 mExtras.remove(key); 2005 } 2006 if (mExtras.size() == 0) { 2007 mExtras = null; 2008 } 2009 } 2010 mInCallAdapter.removeExtras(mTelecomCallId, keys); 2011 } 2012 2013 /** 2014 * Removes extras from this {@link Call}. 2015 * 2016 * @param keys The keys of the extras to remove. 2017 */ removeExtras(String .... keys)2018 public final void removeExtras(String ... keys) { 2019 removeExtras(Arrays.asList(keys)); 2020 } 2021 2022 /** 2023 * Obtains the parent of this {@code Call} in a conference, if any. 2024 * 2025 * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a 2026 * child of any conference {@code Call}s. 2027 */ getParent()2028 public Call getParent() { 2029 if (mParentId != null) { 2030 return mPhone.internalGetCallByTelecomId(mParentId); 2031 } 2032 return null; 2033 } 2034 2035 /** 2036 * Obtains the children of this conference {@code Call}, if any. 2037 * 2038 * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty 2039 * {@code List} otherwise. 2040 */ getChildren()2041 public List<Call> getChildren() { 2042 if (!mChildrenCached) { 2043 mChildrenCached = true; 2044 mChildren.clear(); 2045 2046 for(String id : mChildrenIds) { 2047 Call call = mPhone.internalGetCallByTelecomId(id); 2048 if (call == null) { 2049 // At least one child was still not found, so do not save true for "cached" 2050 mChildrenCached = false; 2051 } else { 2052 mChildren.add(call); 2053 } 2054 } 2055 } 2056 2057 return mUnmodifiableChildren; 2058 } 2059 2060 /** 2061 * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference. 2062 * 2063 * @return The list of conferenceable {@code Call}s. 2064 */ getConferenceableCalls()2065 public List<Call> getConferenceableCalls() { 2066 return mUnmodifiableConferenceableCalls; 2067 } 2068 2069 /** 2070 * Obtains the state of this {@code Call}. 2071 * 2072 * @return A state value, chosen from the {@code STATE_*} constants. 2073 */ getState()2074 public int getState() { 2075 return mState; 2076 } 2077 2078 /** 2079 * Returns the child {@link Call} in a generic conference that is currently active. 2080 * 2081 * A "generic conference" is the mechanism used to support two simultaneous calls on a device 2082 * in CDMA networks. It is effectively equivalent to having one call active and one call on hold 2083 * in GSM or IMS calls. This method returns the currently active call. 2084 * 2085 * In a generic conference, the network exposes the conference to us as a single call, and we 2086 * switch between talking to the two participants using a CDMA flash command. Since the network 2087 * exposes no additional information about the call, the only way we know which caller we're 2088 * currently talking to is by keeping track of the flash commands that we've sent to the 2089 * network. 2090 * 2091 * For calls that are not generic conferences, or when the generic conference has more than 2092 * 2 children, returns {@code null}. 2093 * @see Details#PROPERTY_GENERIC_CONFERENCE 2094 * @return The active child call. 2095 */ getGenericConferenceActiveChildCall()2096 public @Nullable Call getGenericConferenceActiveChildCall() { 2097 if (mActiveGenericConferenceChild != null) { 2098 return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild); 2099 } 2100 return null; 2101 } 2102 2103 /** 2104 * Obtains a list of canned, pre-configured message responses to present to the user as 2105 * ways of rejecting this {@code Call} using via a text message. 2106 * 2107 * @see #reject(boolean, String) 2108 * 2109 * @return A list of canned text message responses. 2110 */ getCannedTextResponses()2111 public List<String> getCannedTextResponses() { 2112 return mCannedTextResponses; 2113 } 2114 2115 /** 2116 * Obtains an object that can be used to display video from this {@code Call}. 2117 * 2118 * @return An {@code Call.VideoCall}. 2119 */ getVideoCall()2120 public InCallService.VideoCall getVideoCall() { 2121 return mVideoCallImpl; 2122 } 2123 2124 /** 2125 * Obtains an object containing call details. 2126 * 2127 * @return A {@link Details} object. Depending on the state of the {@code Call}, the 2128 * result may be {@code null}. 2129 */ getDetails()2130 public Details getDetails() { 2131 return mDetails; 2132 } 2133 2134 /** 2135 * Returns this call's RttCall object. The {@link RttCall} instance is used to send and 2136 * receive RTT text data, as well as to change the RTT mode. 2137 * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection. 2138 */ getRttCall()2139 public @Nullable RttCall getRttCall() { 2140 return mRttCall; 2141 } 2142 2143 /** 2144 * Returns whether this call has an active RTT connection. 2145 * @return true if there is a connection, false otherwise. 2146 */ isRttActive()2147 public boolean isRttActive() { 2148 return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT); 2149 } 2150 2151 /** 2152 * Registers a callback to this {@code Call}. 2153 * 2154 * @param callback A {@code Callback}. 2155 */ registerCallback(Callback callback)2156 public void registerCallback(Callback callback) { 2157 registerCallback(callback, new Handler()); 2158 } 2159 2160 /** 2161 * Registers a callback to this {@code Call}. 2162 * 2163 * @param callback A {@code Callback}. 2164 * @param handler A handler which command and status changes will be delivered to. 2165 */ registerCallback(Callback callback, Handler handler)2166 public void registerCallback(Callback callback, Handler handler) { 2167 unregisterCallback(callback); 2168 // Don't allow new callback registration if the call is already being destroyed. 2169 if (callback != null && handler != null && mState != STATE_DISCONNECTED) { 2170 mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler)); 2171 } 2172 } 2173 2174 /** 2175 * Unregisters a callback from this {@code Call}. 2176 * 2177 * @param callback A {@code Callback}. 2178 */ unregisterCallback(Callback callback)2179 public void unregisterCallback(Callback callback) { 2180 // Don't allow callback deregistration if the call is already being destroyed. 2181 if (callback != null && mState != STATE_DISCONNECTED) { 2182 for (CallbackRecord<Callback> record : mCallbackRecords) { 2183 if (record.getCallback() == callback) { 2184 mCallbackRecords.remove(record); 2185 break; 2186 } 2187 } 2188 } 2189 } 2190 2191 @Override toString()2192 public String toString() { 2193 return new StringBuilder(). 2194 append("Call [id: "). 2195 append(mTelecomCallId). 2196 append(", state: "). 2197 append(stateToString(mState)). 2198 append(", details: "). 2199 append(mDetails). 2200 append("]").toString(); 2201 } 2202 2203 /** 2204 * @param state An integer value of a {@code STATE_*} constant. 2205 * @return A string representation of the value. 2206 */ stateToString(int state)2207 private static String stateToString(int state) { 2208 switch (state) { 2209 case STATE_NEW: 2210 return "NEW"; 2211 case STATE_RINGING: 2212 return "RINGING"; 2213 case STATE_DIALING: 2214 return "DIALING"; 2215 case STATE_ACTIVE: 2216 return "ACTIVE"; 2217 case STATE_HOLDING: 2218 return "HOLDING"; 2219 case STATE_DISCONNECTED: 2220 return "DISCONNECTED"; 2221 case STATE_CONNECTING: 2222 return "CONNECTING"; 2223 case STATE_DISCONNECTING: 2224 return "DISCONNECTING"; 2225 case STATE_SELECT_PHONE_ACCOUNT: 2226 return "SELECT_PHONE_ACCOUNT"; 2227 case STATE_SIMULATED_RINGING: 2228 return "SIMULATED_RINGING"; 2229 case STATE_AUDIO_PROCESSING: 2230 return "AUDIO_PROCESSING"; 2231 default: 2232 Log.w(Call.class, "Unknown state %d", state); 2233 return "UNKNOWN"; 2234 } 2235 } 2236 2237 /** 2238 * Adds a listener to this {@code Call}. 2239 * 2240 * @param listener A {@code Listener}. 2241 * @deprecated Use {@link #registerCallback} instead. 2242 * @hide 2243 */ 2244 @Deprecated 2245 @SystemApi addListener(Listener listener)2246 public void addListener(Listener listener) { 2247 registerCallback(listener); 2248 } 2249 2250 /** 2251 * Removes a listener from this {@code Call}. 2252 * 2253 * @param listener A {@code Listener}. 2254 * @deprecated Use {@link #unregisterCallback} instead. 2255 * @hide 2256 */ 2257 @Deprecated 2258 @SystemApi removeListener(Listener listener)2259 public void removeListener(Listener listener) { 2260 unregisterCallback(listener); 2261 } 2262 2263 /** {@hide} */ Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage, int targetSdkVersion)2264 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage, 2265 int targetSdkVersion) { 2266 mPhone = phone; 2267 mTelecomCallId = telecomCallId; 2268 mInCallAdapter = inCallAdapter; 2269 mState = STATE_NEW; 2270 mCallingPackage = callingPackage; 2271 mTargetSdkVersion = targetSdkVersion; 2272 } 2273 2274 /** {@hide} */ Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state, String callingPackage, int targetSdkVersion)2275 Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state, 2276 String callingPackage, int targetSdkVersion) { 2277 mPhone = phone; 2278 mTelecomCallId = telecomCallId; 2279 mInCallAdapter = inCallAdapter; 2280 mState = state; 2281 mCallingPackage = callingPackage; 2282 mTargetSdkVersion = targetSdkVersion; 2283 } 2284 2285 /** {@hide} */ internalGetCallId()2286 final String internalGetCallId() { 2287 return mTelecomCallId; 2288 } 2289 2290 /** {@hide} */ internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap)2291 final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) { 2292 2293 // First, we update the internal state as far as possible before firing any updates. 2294 Details details = Details.createFromParcelableCall(parcelableCall); 2295 boolean detailsChanged = !Objects.equals(mDetails, details); 2296 if (detailsChanged) { 2297 mDetails = details; 2298 } 2299 2300 boolean cannedTextResponsesChanged = false; 2301 if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null 2302 && !parcelableCall.getCannedSmsResponses().isEmpty()) { 2303 mCannedTextResponses = 2304 Collections.unmodifiableList(parcelableCall.getCannedSmsResponses()); 2305 cannedTextResponsesChanged = true; 2306 } 2307 2308 IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null : 2309 mVideoCallImpl.getVideoProvider(); 2310 IVideoProvider newVideoProvider = parcelableCall.getVideoProvider(); 2311 2312 // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider 2313 // specified; so we should check if the actual IVideoProvider changes as well. 2314 boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() 2315 && !Objects.equals(previousVideoProvider, newVideoProvider); 2316 if (videoCallChanged) { 2317 if (mVideoCallImpl != null) { 2318 mVideoCallImpl.destroy(); 2319 } 2320 mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ? 2321 parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null; 2322 } 2323 2324 if (mVideoCallImpl != null) { 2325 mVideoCallImpl.setVideoState(getDetails().getVideoState()); 2326 } 2327 2328 int state = parcelableCall.getState(); 2329 if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) { 2330 state = Call.STATE_RINGING; 2331 } 2332 boolean stateChanged = mState != state; 2333 if (stateChanged) { 2334 mState = state; 2335 } 2336 2337 String parentId = parcelableCall.getParentCallId(); 2338 boolean parentChanged = !Objects.equals(mParentId, parentId); 2339 if (parentChanged) { 2340 mParentId = parentId; 2341 } 2342 2343 List<String> childCallIds = parcelableCall.getChildCallIds(); 2344 boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds); 2345 if (childrenChanged) { 2346 mChildrenIds.clear(); 2347 mChildrenIds.addAll(parcelableCall.getChildCallIds()); 2348 mChildrenCached = false; 2349 } 2350 2351 String activeChildCallId = parcelableCall.getActiveChildCallId(); 2352 boolean activeChildChanged = !Objects.equals(activeChildCallId, 2353 mActiveGenericConferenceChild); 2354 if (activeChildChanged) { 2355 mActiveGenericConferenceChild = activeChildCallId; 2356 } 2357 2358 List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds(); 2359 List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size()); 2360 for (String otherId : conferenceableCallIds) { 2361 if (callIdMap.containsKey(otherId)) { 2362 conferenceableCalls.add(callIdMap.get(otherId)); 2363 } 2364 } 2365 2366 if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) { 2367 mConferenceableCalls.clear(); 2368 mConferenceableCalls.addAll(conferenceableCalls); 2369 fireConferenceableCallsChanged(); 2370 } 2371 2372 boolean isRttChanged = false; 2373 boolean rttModeChanged = false; 2374 if (parcelableCall.getIsRttCallChanged() 2375 && mDetails.hasProperty(Details.PROPERTY_RTT)) { 2376 ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall(); 2377 InputStreamReader receiveStream = new InputStreamReader( 2378 new ParcelFileDescriptor.AutoCloseInputStream( 2379 parcelableRttCall.getReceiveStream()), 2380 StandardCharsets.UTF_8); 2381 OutputStreamWriter transmitStream = new OutputStreamWriter( 2382 new ParcelFileDescriptor.AutoCloseOutputStream( 2383 parcelableRttCall.getTransmitStream()), 2384 StandardCharsets.UTF_8); 2385 RttCall newRttCall = new Call.RttCall(mTelecomCallId, 2386 receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter); 2387 if (mRttCall == null) { 2388 isRttChanged = true; 2389 } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) { 2390 rttModeChanged = true; 2391 } 2392 mRttCall = newRttCall; 2393 } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null 2394 && parcelableCall.getIsRttCallChanged()) { 2395 isRttChanged = true; 2396 mRttCall = null; 2397 } 2398 2399 // Now we fire updates, ensuring that any client who listens to any of these notifications 2400 // gets the most up-to-date state. 2401 2402 if (stateChanged) { 2403 fireStateChanged(mState); 2404 } 2405 if (detailsChanged) { 2406 fireDetailsChanged(mDetails); 2407 } 2408 if (cannedTextResponsesChanged) { 2409 fireCannedTextResponsesLoaded(mCannedTextResponses); 2410 } 2411 if (videoCallChanged) { 2412 fireVideoCallChanged(mVideoCallImpl); 2413 } 2414 if (parentChanged) { 2415 fireParentChanged(getParent()); 2416 } 2417 if (childrenChanged || activeChildChanged) { 2418 fireChildrenChanged(getChildren()); 2419 } 2420 if (isRttChanged) { 2421 fireOnIsRttChanged(mRttCall != null, mRttCall); 2422 } 2423 if (rttModeChanged) { 2424 fireOnRttModeChanged(mRttCall.getRttAudioMode()); 2425 } 2426 2427 // If we have transitioned to DISCONNECTED, that means we need to notify clients and 2428 // remove ourselves from the Phone. Note that we do this after completing all state updates 2429 // so a client can cleanly transition all their UI to the state appropriate for a 2430 // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list. 2431 if (mState == STATE_DISCONNECTED) { 2432 fireCallDestroyed(); 2433 } 2434 } 2435 2436 /** {@hide} */ internalSetPostDialWait(String remaining)2437 final void internalSetPostDialWait(String remaining) { 2438 mRemainingPostDialSequence = remaining; 2439 firePostDialWait(mRemainingPostDialSequence); 2440 } 2441 2442 /** {@hide} */ internalSetDisconnected()2443 final void internalSetDisconnected() { 2444 if (mState != Call.STATE_DISCONNECTED) { 2445 mState = Call.STATE_DISCONNECTED; 2446 fireStateChanged(mState); 2447 fireCallDestroyed(); 2448 } 2449 } 2450 2451 /** {@hide} */ internalOnConnectionEvent(String event, Bundle extras)2452 final void internalOnConnectionEvent(String event, Bundle extras) { 2453 fireOnConnectionEvent(event, extras); 2454 } 2455 2456 /** {@hide} */ internalOnRttUpgradeRequest(final int requestId)2457 final void internalOnRttUpgradeRequest(final int requestId) { 2458 for (CallbackRecord<Callback> record : mCallbackRecords) { 2459 final Call call = this; 2460 final Callback callback = record.getCallback(); 2461 record.getHandler().post(() -> callback.onRttRequest(call, requestId)); 2462 } 2463 } 2464 2465 /** @hide */ internalOnRttInitiationFailure(int reason)2466 final void internalOnRttInitiationFailure(int reason) { 2467 for (CallbackRecord<Callback> record : mCallbackRecords) { 2468 final Call call = this; 2469 final Callback callback = record.getCallback(); 2470 record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason)); 2471 } 2472 } 2473 2474 /** {@hide} */ internalOnHandoverFailed(int error)2475 final void internalOnHandoverFailed(int error) { 2476 for (CallbackRecord<Callback> record : mCallbackRecords) { 2477 final Call call = this; 2478 final Callback callback = record.getCallback(); 2479 record.getHandler().post(() -> callback.onHandoverFailed(call, error)); 2480 } 2481 } 2482 2483 /** {@hide} */ internalOnHandoverComplete()2484 final void internalOnHandoverComplete() { 2485 for (CallbackRecord<Callback> record : mCallbackRecords) { 2486 final Call call = this; 2487 final Callback callback = record.getCallback(); 2488 record.getHandler().post(() -> callback.onHandoverComplete(call)); 2489 } 2490 } 2491 fireStateChanged(final int newState)2492 private void fireStateChanged(final int newState) { 2493 for (CallbackRecord<Callback> record : mCallbackRecords) { 2494 final Call call = this; 2495 final Callback callback = record.getCallback(); 2496 record.getHandler().post(new Runnable() { 2497 @Override 2498 public void run() { 2499 callback.onStateChanged(call, newState); 2500 } 2501 }); 2502 } 2503 } 2504 fireParentChanged(final Call newParent)2505 private void fireParentChanged(final Call newParent) { 2506 for (CallbackRecord<Callback> record : mCallbackRecords) { 2507 final Call call = this; 2508 final Callback callback = record.getCallback(); 2509 record.getHandler().post(new Runnable() { 2510 @Override 2511 public void run() { 2512 callback.onParentChanged(call, newParent); 2513 } 2514 }); 2515 } 2516 } 2517 fireChildrenChanged(final List<Call> children)2518 private void fireChildrenChanged(final List<Call> children) { 2519 for (CallbackRecord<Callback> record : mCallbackRecords) { 2520 final Call call = this; 2521 final Callback callback = record.getCallback(); 2522 record.getHandler().post(new Runnable() { 2523 @Override 2524 public void run() { 2525 callback.onChildrenChanged(call, children); 2526 } 2527 }); 2528 } 2529 } 2530 fireDetailsChanged(final Details details)2531 private void fireDetailsChanged(final Details details) { 2532 for (CallbackRecord<Callback> record : mCallbackRecords) { 2533 final Call call = this; 2534 final Callback callback = record.getCallback(); 2535 record.getHandler().post(new Runnable() { 2536 @Override 2537 public void run() { 2538 callback.onDetailsChanged(call, details); 2539 } 2540 }); 2541 } 2542 } 2543 fireCannedTextResponsesLoaded(final List<String> cannedTextResponses)2544 private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) { 2545 for (CallbackRecord<Callback> record : mCallbackRecords) { 2546 final Call call = this; 2547 final Callback callback = record.getCallback(); 2548 record.getHandler().post(new Runnable() { 2549 @Override 2550 public void run() { 2551 callback.onCannedTextResponsesLoaded(call, cannedTextResponses); 2552 } 2553 }); 2554 } 2555 } 2556 fireVideoCallChanged(final InCallService.VideoCall videoCall)2557 private void fireVideoCallChanged(final InCallService.VideoCall videoCall) { 2558 for (CallbackRecord<Callback> record : mCallbackRecords) { 2559 final Call call = this; 2560 final Callback callback = record.getCallback(); 2561 record.getHandler().post(new Runnable() { 2562 @Override 2563 public void run() { 2564 callback.onVideoCallChanged(call, videoCall); 2565 } 2566 }); 2567 } 2568 } 2569 firePostDialWait(final String remainingPostDialSequence)2570 private void firePostDialWait(final String remainingPostDialSequence) { 2571 for (CallbackRecord<Callback> record : mCallbackRecords) { 2572 final Call call = this; 2573 final Callback callback = record.getCallback(); 2574 record.getHandler().post(new Runnable() { 2575 @Override 2576 public void run() { 2577 callback.onPostDialWait(call, remainingPostDialSequence); 2578 } 2579 }); 2580 } 2581 } 2582 fireCallDestroyed()2583 private void fireCallDestroyed() { 2584 /** 2585 * To preserve the ordering of the Call's onCallDestroyed callback and Phone's 2586 * onCallRemoved callback, we remove this call from the Phone's record 2587 * only once all of the registered onCallDestroyed callbacks are executed. 2588 * All the callbacks get removed from our records as a part of this operation 2589 * since onCallDestroyed is the final callback. 2590 */ 2591 final Call call = this; 2592 if (mCallbackRecords.isEmpty()) { 2593 // No callbacks registered, remove the call from Phone's record. 2594 mPhone.internalRemoveCall(call); 2595 } 2596 for (final CallbackRecord<Callback> record : mCallbackRecords) { 2597 final Callback callback = record.getCallback(); 2598 record.getHandler().post(new Runnable() { 2599 @Override 2600 public void run() { 2601 boolean isFinalRemoval = false; 2602 RuntimeException toThrow = null; 2603 try { 2604 callback.onCallDestroyed(call); 2605 } catch (RuntimeException e) { 2606 toThrow = e; 2607 } 2608 synchronized(Call.this) { 2609 mCallbackRecords.remove(record); 2610 if (mCallbackRecords.isEmpty()) { 2611 isFinalRemoval = true; 2612 } 2613 } 2614 if (isFinalRemoval) { 2615 mPhone.internalRemoveCall(call); 2616 } 2617 if (toThrow != null) { 2618 throw toThrow; 2619 } 2620 } 2621 }); 2622 } 2623 } 2624 fireConferenceableCallsChanged()2625 private void fireConferenceableCallsChanged() { 2626 for (CallbackRecord<Callback> record : mCallbackRecords) { 2627 final Call call = this; 2628 final Callback callback = record.getCallback(); 2629 record.getHandler().post(new Runnable() { 2630 @Override 2631 public void run() { 2632 callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls); 2633 } 2634 }); 2635 } 2636 } 2637 2638 /** 2639 * Notifies listeners of an incoming connection event. 2640 * <p> 2641 * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}. 2642 * 2643 * @param event 2644 * @param extras 2645 */ fireOnConnectionEvent(final String event, final Bundle extras)2646 private void fireOnConnectionEvent(final String event, final Bundle extras) { 2647 for (CallbackRecord<Callback> record : mCallbackRecords) { 2648 final Call call = this; 2649 final Callback callback = record.getCallback(); 2650 record.getHandler().post(new Runnable() { 2651 @Override 2652 public void run() { 2653 callback.onConnectionEvent(call, event, extras); 2654 } 2655 }); 2656 } 2657 } 2658 2659 /** 2660 * Notifies listeners of an RTT on/off change 2661 * 2662 * @param enabled True if RTT is now enabled, false otherwise 2663 */ fireOnIsRttChanged(final boolean enabled, final RttCall rttCall)2664 private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) { 2665 for (CallbackRecord<Callback> record : mCallbackRecords) { 2666 final Call call = this; 2667 final Callback callback = record.getCallback(); 2668 record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall)); 2669 } 2670 } 2671 2672 /** 2673 * Notifies listeners of a RTT mode change 2674 * 2675 * @param mode The new RTT mode 2676 */ fireOnRttModeChanged(final int mode)2677 private void fireOnRttModeChanged(final int mode) { 2678 for (CallbackRecord<Callback> record : mCallbackRecords) { 2679 final Call call = this; 2680 final Callback callback = record.getCallback(); 2681 record.getHandler().post(() -> callback.onRttModeChanged(call, mode)); 2682 } 2683 } 2684 2685 /** 2686 * Determines if two bundles are equal. 2687 * 2688 * @param bundle The original bundle. 2689 * @param newBundle The bundle to compare with. 2690 * @retrun {@code true} if the bundles are equal, {@code false} otherwise. 2691 */ areBundlesEqual(Bundle bundle, Bundle newBundle)2692 private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) { 2693 if (bundle == null || newBundle == null) { 2694 return bundle == newBundle; 2695 } 2696 2697 if (bundle.size() != newBundle.size()) { 2698 return false; 2699 } 2700 2701 for(String key : bundle.keySet()) { 2702 if (key != null) { 2703 final Object value = bundle.get(key); 2704 final Object newValue = newBundle.get(key); 2705 if (!Objects.equals(value, newValue)) { 2706 return false; 2707 } 2708 } 2709 } 2710 return true; 2711 } 2712 } 2713