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