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